Twitter Bootstrap 3 dropdown menu disappears when used with prototype.js

13,408

Solution 1

I've also used code from here: http://kk-medienreich.at/techblog/magento-bootstrap-integration-mit-prototype-framework but without a need to modify any source. Just put code below somewhere after prototype and jquery includes:

(function() {
    var isBootstrapEvent = false;
    if (window.jQuery) {
        var all = jQuery('*');
        jQuery.each(['hide.bs.dropdown', 
            'hide.bs.collapse', 
            'hide.bs.modal', 
            'hide.bs.tooltip',
            'hide.bs.popover',
            'hide.bs.tab'], function(index, eventName) {
            all.on(eventName, function( event ) {
                isBootstrapEvent = true;
            });
        });
    }
    var originalHide = Element.hide;
    Element.addMethods({
        hide: function(element) {
            if(isBootstrapEvent) {
                isBootstrapEvent = false;
                return element;
            }
            return originalHide(element);
        }
    });
})();

Solution 2

Late to the party, but found this github issue which links to this informational page which links to this jsfiddle which works really nicely. It doesn't patch on every jQuery selector and is, I think, the nicest fix by far. Copying the code here to help future peoples:

jQuery.noConflict();
if (Prototype.BrowserFeatures.ElementExtensions) {
  var pluginsToDisable = ['collapse', 'dropdown', 'modal', 'tooltip', 'popover'];
  var disablePrototypeJS = function (method, pluginsToDisable) {
    var handler = function (event) {
      event.target[method] = undefined;
      setTimeout(function () {
        delete event.target[method];
      }, 0);
    };
    pluginsToDisable.each(function (plugin) {
      jQuery(window).on(method + '.bs.' + plugin, handler);
    });
  };


  disablePrototypeJS('show', pluginsToDisable);
  disablePrototypeJS('hide', pluginsToDisable);
}

Solution 3

Very late to the party: if you don't feel like having extra scripts running, you can add a simple CSS override to prevent it from getting hidden.

.dropdown {
    display: inherit !important;
}

Generally the use of !important in CSS is advised against, but I think this counts as an acceptable use in my opinion.

Solution 4

Using the * selector with jQuery is not advised. This takes every DOM object on the page and puts it in the variable. I would advice to select the elements that use a Bootstrap component specific. Solution below only uses the dropdown component:

(function() {
    var isBootstrapEvent = false;
    if (window.jQuery) {
        var all = jQuery('.dropdown');
        jQuery.each(['hide.bs.dropdown'], function(index, eventName) {
            all.on(eventName, function( event ) {
                isBootstrapEvent = true;
            });
        });
    }
    var originalHide = Element.hide;
    Element.addMethods({
        hide: function(element) {
            if(isBootstrapEvent) {
                isBootstrapEvent = false;
                return element;
            }
            return originalHide(element);
        }
    });
})();

Solution 5

see http://kk-medienreich.at/techblog/magento-bootstrap-integration-mit-prototype-framework/.

It's quite an easy fix to validate the namespace of the element clicked.

Add a validation function to prototype.js:

and after that, validate the namespace before the element will be hidden:

  hide: function(element) {
    element = $(element);
    if(!isBootstrapEvent)
    {
        element.style.display = 'none';
    }
    return element;
  },
Share:
13,408
MWD
Author by

MWD

Updated on June 06, 2022

Comments

  • MWD
    MWD almost 2 years

    I have an issue when using bootstrap 3 & prototype.js together on a magento website.

    Basically if you click on the dropdown menu (Our Products) & then click on the background, the dropdown menu (Our Products) disappears (prototype.js adds "display: none;" to the li).

    Here is a demo of the issue: http://ridge.mydevelopmentserver.com/contact.html

    You can see that the dropdown menu works like it should without including prototype.js on the page at the link below: http://ridge.mydevelopmentserver.com/

    Has anyone else ran into this issue before or have a possible solution for the conflict?

    EASY FIX:

    Just replace Magento's prototype.js file with this bootstrap friendly one:

    https://raw.github.com/zikula/core/079df47e7c1f536a0d9eea2993ae19768e1f0554/src/javascript/ajax/original_uncompressed/prototype.js

    You can see the changes made in the prototype.js file to fix the bootstrap issue here:

    https://github.com/zikula/core/commit/079df47e7c1f536a0d9eea2993ae19768e1f0554

    NOTE: JQuery must be include in your magento skin before prototype.js.. Example:

    <script type="text/javascript" src="/js/jquery.js"></script>
    <script type="text/javascript" src="/js/prototype/prototype.js"></script>
    <script type="text/javascript" src="/js/lib/ccard.js"></script>
    <script type="text/javascript" src="/js/prototype/validation.js"></script>
    <script type="text/javascript" src="/js/scriptaculous/builder.js"></script>
    <script type="text/javascript" src="/js/scriptaculous/effects.js"></script>
    <script type="text/javascript" src="/js/scriptaculous/dragdrop.js"></script>
    <script type="text/javascript" src="/js/scriptaculous/controls.js"></script>
    <script type="text/javascript" src="/js/scriptaculous/slider.js"></script>
    <script type="text/javascript" src="/js/varien/js.js"></script>
    <script type="text/javascript" src="/js/varien/form.js"></script>
    <script type="text/javascript" src="/js/varien/menu.js"></script>
    <script type="text/javascript" src="/js/mage/translate.js"></script>
    <script type="text/javascript" src="/js/mage/cookies.js"></script>
    <script type="text/javascript" src="/js/mage/captcha.js"></script>
    
  • Anthony
    Anthony almost 10 years
    Thank you so much for this solution. Are there any other events apart from hide() which may potentially conflict?
  • Janith Chinthana
    Janith Chinthana almost 10 years
    it is giving an error at all.on..... line as, TypeError: all.on is not a function
  • evgeny.myasishchev
    evgeny.myasishchev over 9 years
    @Anthony I haven't found any so far, have you?
  • Ananth
    Ananth over 9 years
    @evgeny.myasishchev , Thank you, this code works for me. But when i click the menu, its not redirecting to the particular page.
  • Phil
    Phil almost 9 years
    I like not using '*'. On the flip side, this issue affects other twitter bootstrap functionality like popover. So, multiple elements have to be selected; albeit not all.
  • Justin
    Justin over 8 years
    This is the best solution. Very easy to understand what it is doing and makes sense to go into your existing no-conflict js file if you're already using jquery.
  • Chris Watts
    Chris Watts over 8 years
    In case this conflicts with intended functionality of Prototype, refine the selector with .nav .dropdown
  • medoingthings
    medoingthings over 8 years
    Modifying a library is always bad advice. You won’t be able to update jQuery without modifying the new version. If you forget to update it, things will break. Your modifications might break even more things than you fixed.
  • James Long
    James Long over 8 years
    The highest-rated answer is replacing functionality from PrototypeJS. I don't see how modifying jQuery is any more dangerous or any worse advice. As an aside, I can't remember the last time I updated a library without a serious overhaul and a simple unit test would show-up the missing modification.
  • medoingthings
    medoingthings over 8 years
    Indeed, the highest rated answer is changing prototype.js. While this is still not ideal, the changes are tightly scoped to the Bootstrap issue (if you look at the diff mentioned within the answer). Your approach changes jQuery functionality globally, which is much more error prone than the approach from @MWD. Btw: as far as I can tell, @CJxD’s answer seems to be the most elegant one, since it doesn’t add JavaScript events to every single DOM element. Once again the highest rated answer might not be the best answer that everyone else should go for. TLDR: Be careful with changing libraries.
  • Jeff Yates
    Jeff Yates about 8 years
    True Gold, Sir. Thanks very much!
  • Debakant Mohanty
    Debakant Mohanty about 8 years
    Thanks evgeny, the solution works for me! You made my day!
  • Thomas Harding
    Thomas Harding almost 8 years
    Absolutely brilliant. My company use a custom framework based on bootstrap, which we're starting to port into Magento. I was pulling my hair out for days when neither the dropdown, tab nor modal worked properly. Thank you SO much!