Извлечь выпадающее меню рядом с кликом внутри

У меня есть раскрывающееся меню Twitter Bootstrap. Как известно всем пользователям Twitter Bootstrap, выпадающее меню закрывается щелчком (даже щелкая внутри него).

Чтобы этого избежать, я могу легко подключить обработчик события клика в раскрывающемся меню и просто добавить знаменитый event.stopPropagation() .

  

Однако это выглядит просто и очень часто, и поскольку обработчики событий carousel-controls (а также carousel indicators ) делегированы объекту document , событие click на этих элементах ( предыдущие / следующие элементы управления, …) будет «игнорируется».

 $('ul.dropdown-menu.mega-dropdown-menu').on('click', function(event){ // The event won't be propagated up to the document NODE and // therefore delegated events won't be fired event.stopPropagation(); }); 

Опираясь на Twitter Выпадающий список Bootstrap hide / hidden events не является решением по следующим причинам:

  • Предоставленное событие для обоих обработчиков событий не дает вам ссылки на элемент с щелчком
  • Содержимое выпадающего меню динамически генерируется, поэтому добавление classа flag невозможно

Эта скрипка – обычное поведение, и эта скрипка с event.stopPropagation() .

Обновить

Спасибо Роману за его ответ . Я также нашел ответ, который вы можете найти ниже .

Удаление данных атрибута data-toggle="dropdown" и реализация раскрытия / закрытия раскрывающегося списка может быть решением.

Сначала обработав щелчок по ссылке, чтобы открыть / закрыть раскрывающийся список следующим образом:

 $('li.dropdown.mega-dropdown a').on('click', function (event) { $(this).parent().toggleClass('open'); }); 

а затем прослушивание кликов за пределами раскрывающегося списка, чтобы закрыть его следующим образом:

 $('body').on('click', function (e) { if (!$('li.dropdown.mega-dropdown').is(e.target) && $('li.dropdown.mega-dropdown').has(e.target).length === 0 && $('.open').has(e.target).length === 0 ) { $('li.dropdown.mega-dropdown').removeClass('open'); } }); 

Вот демо: http://jsfiddle.net/RomaLefrancois/hh81rhcm/2/

Это также должно помочь

 $(document).on('click', 'someyourContainer .dropdown-menu', function (e) { e.stopPropagation(); }); 

Bootstrap предоставляет следующую функцию:

  |  Это событие запускается немедленно, когда метод экземпляра hide 
 hide.bs.dropdown |  был вызван.  Переключающий анкерный элемент доступен как 
                  |  relatedTarget свойства события. 

Поэтому реализация этой функции должна быть способна отключить выпадающий список из закрытия.

 $('#myDropdown').on('hide.bs.dropdown', function (e) { var target = $(e.target); if(target.hasClass("keepopen") || target.parents(".keepopen").length){ return false; // returning false should stop the dropdown from hiding. }else{ return true; } }); 

Абсолютный лучший ответ – поместить тег формы после раскрывающегося меню classа

поэтому ваш код

  

Я также нашел решение.

Предполагая, что обработчики событий, связанных с Twitter Bootstrap Components , делегированы объекту document , я зацикляю прикрепленные обработчики и проверяю, связано ли текущий элемент clicked (или один из его родителей) делегированным событием.

 $('ul.dropdown-menu.mega-dropdown-menu').on('click', function(event){ var events = $._data(document, 'events') || {}; events = events.click || []; for(var i = 0; i < events.length; i++) { if(events[i].selector) { //Check if the clicked element matches the event selector if($(event.target).is(events[i].selector)) { events[i].handler.call(event.target, event); } // Check if any of the clicked element parents matches the // delegated event selector (Emulating propagation) $(event.target).parents(events[i].selector).each(function(){ events[i].handler.call(this, event); }); } } event.stopPropagation(); //Always stop propagation }); 

Надеюсь, это поможет любому, кто ищет аналогичное решение.

Спасибо за вашу помощь.

 $('body').on("click", ".dropdown-menu", function (e) { $(this).parent().is(".open") && e.stopPropagation(); }); 

Это может работать для любых условий.

Это может помочь:

 $("dropdownmenuname").click(function(e){ e.stopPropagation(); }) 

JQuery:

  

HTML:

  

Демо :

Общий: https://jsfiddle.net/kerryjohnson/omefq68b/1/

Демо с этим решением: http://jsfiddle.net/kerryjohnson/80oLdtbf/101/

 $('ul.nav.navbar-nav').on('click.bs.dropdown', function(e){ var $a = $(e.target), is_a = $a.is('.is_a'); if($a.hasClass('dropdown-toggle')){ $('ul.dropdown-menu', this).toggle(!is_a); $a.toggleClass('is_a', !is_a); } }).on('mouseleave', function(){ $('ul.dropdown-menu',this).hide(); $('.is_a', this).removeClass('is_a'); }); 

я обновил его еще раз, чтобы быть максимально умным и функциональным. теперь он закрывается, когда вы нависаете за пределами навигатора, оставаясь открытым, пока вы находитесь внутри него. просто идеально.

Недавно я столкнулся с подобной проблемой и попробовал разные способы ее устранения, удалив данные атрибута data-toggle="dropdown" и прослушивая click с event.stopPropagation() .

Второй способ выглядит более предпочтительным. Также разработчики Bootstrap используют этот способ. В исходном файле я нашел инициализацию выпадающих элементов:

 // APPLY TO STANDARD DROPDOWN ELEMENTS $(document) .on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) }(jQuery); 

Итак, эта строка:

 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) 

предполагает, что вы можете поместить элемент form внутри контейнера с classом .dropdown чтобы не закрывать раскрывающееся меню.

Вы можете остановить нажатие на раскрывающееся меню, а затем вручную переопределить элементы управления карусели с помощью методов javascript с помощью карусели .

 $('ul.dropdown-menu.mega-dropdown-menu').on('click', function(event) { event.stopPropagation(); }); $('a.left').click(function () { $('#carousel').carousel('prev'); }); $('a.right').click(function () { $('#carousel').carousel('next'); }); $('ol.carousel-indicators li').click(function (event) { var index = $(this).data("slide-to"); $('#carousel').carousel(index); }); . $('ul.dropdown-menu.mega-dropdown-menu').on('click', function(event) { event.stopPropagation(); }); $('a.left').click(function () { $('#carousel').carousel('prev'); }); $('a.right').click(function () { $('#carousel').carousel('next'); }); $('ol.carousel-indicators li').click(function (event) { var index = $(this).data("slide-to"); $('#carousel').carousel(index); }); 

Вот jsfiddle .

С помощью Angular2 Bootstrap вы можете использовать nonInput для большинства сценариев:

 

nonInput – (по умолчанию) автоматически закрывает раскрывающийся список, когда нажимается любой из его элементов, – пока элемент с кликом не является вводом или текстовым полем.

https://valor-software.com/ng2-bootstrap/#/dropdowns

Подобно, например, Bootstrap 4 Alpha имеет это событие меню. Почему бы не использовать?

 // PREVENT INSIDE MEGA DROPDOWN $('.dropdown-menu').on("click.bs.dropdown", function (e) { e.stopPropagation(); e.preventDefault(); }); 

Я знаю, что этот вопрос был специально для jQuery, но для тех, кто использует AngularJS, у которого есть эта проблема, вы можете создать директиву, которая обрабатывает это:

 angular.module('app').directive('dropdownPreventClose', function() { return { restrict: 'A', link: function(scope, element, attrs) { element.on('click', function(e) { e.stopPropagation(); //prevent the default behavior of closing the dropdown-menu }); } }; }); 

Затем просто добавьте dropdown-prevent-close меню атрибута dropdown-prevent-close к вашему элементу, который вызывает закрытие меню, и он должен его предотвратить. Для меня это был элемент select который автоматически закрывал меню:

  

[Bootstrap 4 Alpha 6] [Rails] Для разработчика rails e.stopPropagation() приведет к нежелательному поведению для link_to с data-method не равным get поскольку по умолчанию он будет возвращать весь ваш запрос как get .

Чтобы исправить эту проблему, я предлагаю это решение, которое является универсальным

 $('.dropdown .dropdown-menu').on('click.bs.dropdown', function() { return $('.dropdown').one('hide.bs.dropdown', function() { return false; }); }); 
 $('.dropdown .dropdown-menu').on('click.bs.dropdown', function() { return $('.dropdown').one('hide.bs.dropdown', function() { return false; }); }); 
      

Самое простое решение для меня:

  • добавление keep-open classа к элементам, которые не должны вызывать закрытие выпадающего списка
  • и эта часть кода делает все остальное:
 $('.dropdown').on('click', function(e) { var target = $(e.target); var dropdown = target.closest('.dropdown'); return !dropdown.hasClass('open') || !target.hasClass('keep-open'); }); 

Я не нашел ни одного из этих решений, поскольку я хотел бы использовать загрузку по умолчанию. Вот мое решение этой проблемы:

  $(document).on('hide.bs.dropdown', function (e) { if ($(e.currentTarget.activeElement).hasClass('dropdown-toggle')) { $(e.relatedTarget).parent().removeClass('open'); return true; } return false; }); 

Вместо написания кода javascript или jquery (переосмысление колеса). Вышеупомянутый сценарий может управляться с помощью опции автозагрузки bootstrap. Вы можете указать одно из значений для автоматического закрытия :

  1. всегда – (по умолчанию) автоматически закрывает раскрывающийся список, когда нажимается любой из его элементов.

  2. externalClick – закрывает раскрывающийся список автоматически только тогда, когда пользователь нажимает на любой элемент за пределами раскрывающегося списка.

  3. отключено – отключает автоматическое закрытие

Взгляните на следующий plunkr:

http://plnkr.co/edit/gnU8M2fqlE0GscUQtCWa?p=preview

Задавать

 uib-dropdown auto-close="disabled" 

Надеюсь это поможет 🙂

В .dropdown content поместите .keep-open на любой ярлык следующим образом:

 $('.dropdown').on('click', function (e) { var target = $(e.target); var dropdown = target.closest('.dropdown'); if (target.hasClass('keep-open')) { $(dropdown).addClass('keep-open'); } else { $(dropdown).removeClass('keep-open'); } }); $(document).on('hide.bs.dropdown', function (e) { var target = $(e.target); if ($(target).is('.keep-open')) { return false } }); 

В предыдущих случаях избегались события, связанные с объектами контейнера, теперь контейнер наследует class keep-open и проверку перед закрытием.

 $(function() { $('.mega-dropdown').on('hide.bs.dropdown', function(e) { var $target = $(e.target); return !($target.hasClass("keep-open") || $target.parents(".keep-open").size() > 0); }); $('.mega-dropdown > ul.dropdown-menu').on('mouseenter', function() { $(this).parent('li').addClass('keep-open') }).on('mouseleave', function() { $(this).parent('li').removeClass('keep-open') }); }); 

Чтобы закрыть раскрывающийся список, только если событие щелчка было запущено за пределами выпадающего списка, это то, что сработало для меня:

JS-файл:

  $('.createNewElement').on('click.bs.dropdown.data-api', '.tags-btn-group.keep-open-dropdown', function (e) { var target = $(e.target); if (target.hasClass("dropdown-menu") || target.parents(".dropdown-menu").length) { e.stopPropagation(); } }); 

HTML-файл:

  

Я знаю, что уже есть предыдущий ответ, предлагающий использовать форму, но предоставленная разметка неверна / идеальна. Вот самое простое решение, вообще не требуется javascript, и оно не разбивает ваш раскрывающийся список. Работает с Bootstrap 4.

 $('body').on("click", ".dropdown-menu", function (e) { $(this).parent().is(".show") && e.stopPropagation(); }); 

это работает в 2018 году

 $(function() { var closeble = false; $('body').on('click', function (e) { if (!$(event.target).is("a.dropdown-toggle")) { closeble = false; } }); $('.dropdown').on({ "click": function(event) { if ($(event.target).closest('.dropdown-toggle').length) { closeble = true; } else { closeble = false; } }, "hide.bs.dropdown": function() { return closeble; } }); 

});