Избегайте выпадающего меню закрыть по щелчку внутри
у меня есть выпадающее меню Twitter Bootstrap. Как знают все пользователи Twitter Bootstrap, выпадающее меню закрывается при щелчке (даже щелчок внутри него).
чтобы избежать этого, я могу легко прикрепить обработчик событий click в выпадающем меню и просто добавить знаменитый event.stopPropagation().
<ul class="nav navbar-nav">
<li class="dropdown mega-dropdown">
<a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-list-alt"></i> Menu item 1
<span class="fa fa-chevron-down pull-right"></span>
</a>
<ul class="dropdown-menu mega-dropdown-menu">
<li>
<div id="carousel" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-slide-to="0" data-target="#carousel"></li>
<li class="active" data-slide-to="1" data-target="#carousel"></li>
</ol>
<div class="carousel-inner">
<div class="item">
<img alt="" class="img-rounded" src="img1.jpg">
</div>
<div class="item active">
<img alt="" class="img-rounded" src="img2.jpg">
</div>
</div>
<a data-slide="prev" role="button" href="#carousel"
class="left carousel-control">
<span class="glyphicon glyphicon-chevron-left"></span>
</a>
<a data-slide="next" role="button" href="#carousel"
class="right carousel-control">
<span class="glyphicon glyphicon-chevron-right"></span>
</a>
</div>
</li>
</ul>
</li>
</ul>
это выглядит легко и очень распространенное поведение, впрочем, и с carousel-controls (а также carousel indicators) обработчики событий делегируются
24 ответов:
удаление данных атрибута
data-toggle="dropdown"и реализация open / close выпадающего списка может быть решением.во-первых, обработав щелчок по ссылке, чтобы открыть / закрыть раскрывающийся список следующим образом:
$('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'); } });
Это тоже должно помочь
$(document).on('click', 'someyourContainer .dropdown-menu', function (e) { e.stopPropagation(); });
Bootstrap предоставляет следующую функцию:
| This event is fired immediately when the hide instance method hide.bs.dropdown | has been called. The toggling anchor element is available as the | relatedTarget property of the event.таким образом, реализация этой функции должна быть в состоянии отключить выпадающее меню от закрытия.
$('#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; } });
абсолютный лучший ответ-поставить тег формы после выпадающего меню класса
Итак, ваш код
<ul class="dropdown-menu"> <form> <li> <div class="menu-item">bla bla bla</div> </li> </form> </ul>
Я нашел решение.
предполагая, что
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(); });Это может работать на любых условиях.
jQuery:
<script> $(document).on('click.bs.dropdown.data-api', '.dropdown.keep-inside-clicks-open', function (e) { e.stopPropagation(); }); </script>HTML:
<div class="dropdown keep-inside-clicks-open"> <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown"> Dropdown Example <span class="caret"></span> </button> <ul class="dropdown-menu"> <li><a href="#">HTML</a></li> <li><a href="#">CSS</a></li> <li><a href="#">JavaScript</a></li> </ul> </div>демо:
универсальный: 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элемент внутри контейнера с классом.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); });здесь jsfiddle.
С Angular2 Bootstrap, вы можете использовать nonInput для большинства сценариев:
<div dropdown autoClose="nonInput">nonInput - (по умолчанию) автоматически закрывает выпадающий список при нажатии любого из его элементов-до тех пор, пока щелкнутый элемент не является входом или текстовым полем.
как, например, 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к вашему элементу, который запускает меню, чтобы закрыть, и он должен предотвратить его. Для меня это былоselectэлемент, который автоматически закрывается меню:<div class="dropdown-menu"> <select dropdown-prevent-close name="myInput" id="myInput" ng-model="myModel"> <option value="">Select Me</option> </select> </div>
[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; }); });<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script> <ul class="nav navbar-nav"> <li class="dropdown mega-dropdown"> <a href="javascript:;" class="dropdown-toggle" data-toggle="dropdown"> <i class="fa fa-list-alt"></i> Menu item 1 <span class="fa fa-chevron-down pull-right"></span> </a> <ul class="dropdown-menu mega-dropdown-menu"> <li> <div id="carousel" class="carousel slide" data-ride="carousel"> <ol class="carousel-indicators"> <li data-slide-to="0" data-target="#carousel"></li> <li class="active" data-slide-to="1" data-target="#carousel"></li> </ol> <div class="carousel-inner"> <div class="item"> <img alt="" class="img-rounded" src="img1.jpg"> </div> <div class="item active"> <img alt="" class="img-rounded" src="img2.jpg"> </div> </div> <a data-slide="prev" role="button" href="#carousel" class="left carousel-control"> <span class="glyphicon glyphicon-chevron-left"></span> </a> <a data-slide="next" role="button" href="#carousel" class="right carousel-control"> <span class="glyphicon glyphicon-chevron-right"></span> </a> </div> </li> </ul> </li> </ul>
самое простое рабочее решение для меня-это:
- добавлять
keep-openкласс для элементов, которые не должны вызвать выпадающее закрытия- и этот кусок кода делает все остальное:
$('.dropdown').on('click', function(e) { var target = $(e.target); var dropdown = target.closest('.dropdown'); return !dropdown.hasClass('open') || !target.hasClass('keep-open'); });
Я не нашел ни одного из решений, которые работали бы так, как я хотел бы использовать по умолчанию bootstrap nav. Вот мое решение этой проблемы:
$(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(изобретение колеса). Вышеприведенный сценарий может управляться опцией автоматического закрытия начальной загрузки. Вы можете указать любое из значений для закрыть:
всегда - (по умолчанию) автоматически закрывает выпадающий список при нажатии любого из его элементов.
outsideClick - закрывает выпадающий список автоматически только тогда, когда пользователь щелкает любой элемент за пределами раскрывающийся.
disabled-отключает автоматическое закрытие
взгляните на следующих plunkr :
http://plnkr.co/edit/gnU8M2fqlE0GscUQtCWa?p=preview
Set
uib-dropdown auto-close="disabled"надеюсь, что это помогает :)
на
.dropdownсодержание поставить.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 } });предыдущие случаи избежали событий, связанных с объектами контейнера, теперь контейнер наследует класс keep-open и проверяет перед закрытием.
Я знаю, что уже есть в предыдущем ответе, предложив использовать форму, но синтаксис не правильный/идеальный. Вот самое простое решение, не требуется javascript вообще, и это не нарушает ваш выпадающий список. Работы с Bootstrap 4.
<form class="dropdown-item"> <!-- Your elements go here --> </form>
$('body').on("click", ".dropdown-menu", function (e) { $(this).parent().is(".show") && e.stopPropagation(); });это работает в 2018 году
$(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') }); });
для закрытия выпадающего списка только в том случае, если событие click было вызвано вне раскрывающегося списка bootstrap, это то, что сработало для меня:
JS file:
$('.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-файл:
<!-- button: --> <div class="createNewElement"> <div class="btn-group tags-btn-group keep-open-dropdown"> <div class="dropdown-toggle" data-toggle="dropdown" aria-expanded="false">OPEN DROPDOWN</div> <ul class="dropdown-menu"> WHAT EVER YOU WANT HERE... </ul> </div> </div>
$(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; } });});
Comments