Apologies for yet another issue concerning modals. This is probably just a support request. I'm using Boostrap theme with the sass starter kit and opening a modal via JavaScript. The following is in the "attach" behavior:

      var myDialog = Drupal.dialog(('#drupal-modal'), {
        title: 'A title'
      });
      $('.modal-link').on('click', function () {
        myDialog.showModal();
      });

The HTML has a span with the class "modal-link". The modal opens as expected when the span is clicked and closes with the X in the top right corner is clicked. The second time the link is clicked 3 modals open. These can can be closed by clicking on the Xs of any of the modals.

The 3rd time the link is clicked the number of modals opened increases exponentially.

Again, clicking on any of the Close Xs will close them all. After deselecting "Enable Bootstrap Modals" in the sub theme, the jQuery UI modal pops up instead.

Only a single jQuery UI modal opens up no matter how many times I click the link.

My question is, is there something I'm missing when I'm opening a Bootstrap modal using Drupal core's modal API?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

imclean created an issue. See original summary.

imclean’s picture

I've also tried:

    $('.modal-link').once().on('click', function () {
        myDialog.showModal();
      });
markhalliwell’s picture

Status: Active » Postponed (maintainer needs more info)

There's probably something not quite right in the Modal jQuery UI Bridge code.

What that is, I really don't know. I'd need to step through the creation process of the modal to figure out what's going on. Something I don't really have a lot of time right now to do.

kerrivader’s picture

The issue appears to be on line 82 of modal.jquery.ui.bridge.js, where content is being appended to .modal-body. With JS modals, the content is sometimes the entire modal markup, not just the body. Attached patch checks for the .modal class and conditionally chooses whether to append to .modal or .modal-body based on that.

markhalliwell’s picture

Status: Postponed (maintainer needs more info) » Closed (works as designed)

#2 is on the correct path. The problem (and why by the 3rd click it's exponential) is that the click event is being bound more than once.

You can see with the following code how to properly bind an event if it's wrapped inside an attachment behavior; which can be invoked a multitude of times:
http://cgit.drupalcode.org/bootstrap/tree/js/theme-settings.js#n63

pwaterz’s picture

Status: Closed (works as designed) » Needs review

I am experiencing the exact same issue. Adding .once did not fix it. The patch from #4 fixed it.

markhalliwell’s picture

Status: Needs review » Closed (works as designed)

The patch from #4 is merely a hack to detect duplicate initialization (which shouldn't happen in the first place). Clearly, the custom code that is initiating said dialog/modal isn't being constructed properly. This isn't a bug in the code.

Make sure your code isn't being invoked multiple times; debug it. If it is, figure out what's causing it (likely more custom code somewhere).

edit: often times, more than not, the real reason for things like this is due to the lack of understanding how DOM/jQuery ready events work and then the Drupal behavior system. It can get even more screwy when adding AJAX on top of that, which triggers all Drupal behaviors for new content. So unless you wrap your code in the proper initializer and put in proper detection for when said code should execute... you'll get this exact scenario. This isn't anything new.

pwaterz’s picture

Status: Closed (works as designed) » Active

I'm bit confused. To me it seems like bootstrap is doing something not right. Here is a very simple test.

- Enabled bartik
- Enter the following into the browser console:

  jQuery('body').prepend('<a class="my-modal" href="#test-modal">Open Modal</a><div style="display:none" id="test-modal">Some Content</div>');
      
      jQuery('.my-modal').once("toggle-open").each(function(a){
      jQuery(this).click(function(b){
        jQuery('#test-modal').dialog({modal: true});
      });
      });

Opening the modal repeatedly works fine.

- Enable bootstrap
- Enter the same js in the browser console
- Bootstrap ends up nesting it self deeper and deeper the more times you click it.

I also noticed that it's creating new modal markup on event change and not reusing the previously built modal.

imclean’s picture

I also noticed that it's creating new modal markup on event change and not reusing the previously built modal.

This is interesting.

The question is, in the specific case of opening a modal using javascript, should Bootstrap modal behave the same was as jQuery Modal when using Drupal's modal API?

markhalliwell’s picture

Title: Opening a modal with JavaScript » Using $.fn.dialog duplicates content when it lives in DOM
Assigned: Unassigned » markhalliwell
Category: Support request » Bug report
Status: Active » Needs work

@pwaterz, thanks for the additional example code.

This is, in fact, a bug. I was originally adamant that this was just an initialization issue, but it does go a little deeper than that. I think I've narrowed down what this specific issue really is. This seems to only really happen when the content is in located in the DOM rather than being created dynamically (as most core/contrib code does, either in JS or via AJAX commands).

As stated before, the patch in #4 is really just a band-aid for the symptom. I'll upload a patch shortly that should remedy this issue by only creating the modal structure when it's truly needed.

I also noticed that it's creating new modal markup on event change and not reusing the previously built modal.

Correct. The idea was, originally, that for the bridge to work properly new markup/modal instances needed to be created. That being said and stepping through this again through various testing modals (including the example code above), this is no longer always necessary due to recent changes to other portions of the modal code.

...in the specific case of opening a modal using javascript, should Bootstrap modal behave the same was as jQuery Modal when using Drupal's modal API?

The Bootstrap modal has to handle several different initialization methods: direct/native ($.fn.modal), jQuery UI dialog direct/native ($.fn.dialog) and the various other intricacies that come with Drupal.dialog and AJAX.

Regardless of the initialization method, it should all work relatively the same (when applicable).

markhalliwell’s picture

Assigned: markhalliwell » Unassigned
Status: Needs work » Needs review
FileSize
6.43 KB
pwaterz’s picture

Mark you rock dude! I'll give this patch a test today.

pwaterz’s picture

I tested the patch yesterday and it appears to be working. I am still having another issue and am in the process of trying to determine if the issue is in my code or some where else.

  • markcarver committed 26c83e1 on 8.x-3.x
    Issue #2997347 by markcarver, imclean, pwaterz: Using $.fn.dialog...
markhalliwell’s picture

Status: Needs review » Fixed

Ok, then I'm going to go ahead and commit this.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.