web-dev-qa-db-ja.com

Twitter Bootstrap 3のドロップダウンメニューがprototype.jsで使用すると消える

Magento Webサイトでbootstrap 3とprototype.jsを一緒に使用すると問題が発生します。

基本的に、ドロップダウンメニュー(私たちの製品)をクリックしてから背景をクリックすると、ドロップダウンメニュー(私たちの製品)が消えます(prototype.jsが "display:none;"をliに追加します)。

これが問題のデモです: http://ridge.mydevelopmentserver.com/contact.html

以下のリンクのページにprototype.jsを含めなくても、ドロップダウンメニューが正常に機能することがわかります。 http://ridge.mydevelopmentserver.com/

他の誰かが以前にこの問題に遭遇したか、または競合の可能な解決策を持っていますか?

簡単な修正:

Magentoのprototype.jsファイルをこのbootstrapフレンドリーなファイルに置き換えてください:

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

ここでbootstrap問題を修正するためにprototype.jsファイルに加えられた変更を確認できます。

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

注:JQueryは、prototype.jsの前にmagentoスキンに含める必要があります。例:

<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>
40
MWD

私はここからコードも使用しました: http://kk-medienreich.at/techblog/magento-bootstrap-integration-mit-prototype-framework しかし、ソースを変更する必要はありません。プロトタイプとjqueryがインクルードした後のどこかにコードを以下に置くだけです:

(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);
        }
    });
})();
42

パーティーには遅れましたが、 このgithubの問題 へのリンク この情報ページ へのリンク このjsfiddle がうまく機能しています。それはすべてのjQueryセレクターにパッチを当てるわけではなく、私が思うに、これは最も優れた修正です。将来の人々を助けるためにここにコードをコピーします:

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);
}
8
patrickdavey

JQueryで*セレクターを使用することはお勧めしません。これにより、ページ上のすべてのDOMオブジェクトが取得され、変数に入れられます。 Bootstrapコンポーネント固有を使用する要素を選択することをお勧めします。以下の解決策はドロップダウンコンポーネントのみを使用します。

(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);
        }
    });
})();
7
Tom Franssen

パーティーに非常に遅れています。追加のスクリプトを実行したくない場合は、簡単なCSSオーバーライドを追加して、スクリプトが非表示にならないようにすることができます。

.dropdown {
    display: inherit !important;
}

一般に、CSSでの!importantの使用は推奨されませんが、これは私の意見では許容できる使用と見なされます。

6
CJxD

Magentoのprototype.jsファイルをbootstrap MWDによって提案されたフレンドリーなバージョンに置き換えると、構成可能な製品の保存を妨げるエラーがスローされます。

Uncaught TypeError: Object [object Array] has no method 'gsub' prototype.js:5826

(Magento Magento 1.7.0.2を実行)

evgeny.myasishchevソリューションはうまく機能しました。

(function() {
    var isBootstrapEvent = false;
    if (window.jQuery) {
        var all = jQuery('*');
        jQuery.each(['hide.bs.dropdown', 
            'hide.bs.collapse', 
            'hide.bs.modal', 
            'hide.bs.tooltip'], 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);
        }
    });
})();
2
Perez Jr

http://kk-medienreich.at/techblog/magento-bootstrap-integration-mit-prototype-framework/ を参照してください。

クリックされた要素の名前空間を検証するのは非常に簡単な修正です。

検証関数をprototype.jsに追加します。

その後、要素が非表示になる前に名前空間を検証します。

  hide: function(element) {
    element = $(element);
    if(!isBootstrapEvent)
    {
        element.style.display = 'none';
    }
    return element;
  },
2
klma

この答え は、bootstrapprototypeの競合の問題を取り除くのに役立ちました。

@ GeekNum88が問題を説明しているように、

PrototypeJSはElementプロトタイプにメソッドを追加するので、jQueryが要素のhide()メソッドをトリガーしようとすると、実際にはPrototypeJS hide()メソッドを起動します。これは、jQuery hide()と同等です。メソッドと要素のスタイルをdisplay:none;に設定します

質問自体で示唆しているように、bootstrapフレンドリーprototypeを使用するか、またはbootstrapの数行を次のようにコメントアウトすることができます。

Tooltip.prototype.hide関数内

this.$element.trigger(e)
if (e.isDefaultPrevented()) return
0