避免点击里面的下拉菜单closures
我有一个Twitter的Bootstrap下拉菜单。 正如所有Twitter Bootstrap用户所知道的,下拉菜单在点击时closures(甚至在其内部点击)。
为了避免这种情况,我可以轻松地在下拉菜单上附加一个点击事件处理程序,并简单地添加着名的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
)事件处理程序被委托给document
对象,因此这些元素( prev / next控件,…)上的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
事件不是一个解决scheme,原因如下:
- 为两个事件处理程序提供的事件不会引用您单击的元素
- 下拉菜单的内容是dynamic生成的,所以添加
flag
类是不可能的
这小提琴是正常的行为, 这个小提琴与event.stopPropagation()
添加。
更新
感谢罗马的回答 。 我也find了一个答案,你可以在下面find 。
删除数据属性data-toggle="dropdown"
并执行data-toggle="dropdown"
的打开/closures可以是一个解决scheme。
首先通过点击链接来打开/closures下拉菜单,如下所示:
$('li.dropdown.mega-dropdown a').on('click', function (event) { $(this).parent().toggleClass('open'); });
然后在下拉列表外部听取点击以closures它:
$('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提供以下function:
| 当隐藏实例方法时立即触发此事件 hide.bs.dropdown | 已被调用。 切换的锚点元素是可用的 | related事件的relatedTarget属性。
因此,实现这个function应该可以禁用closures下拉菜单。
$('#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; } });
我也find了解决办法。
假设Twitter Bootstrap Components
相关的事件处理程序被委托给document
对象,我循环附加的处理程序,并检查当前点击元素(或其父母之一)是否由委派的事件。
$('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 });
希望它可以帮助任何寻找类似解决scheme的人。
感谢大家的帮助。
绝对最好的答案是在类下拉菜单后面放置一个表单标签
所以你的代码是
<ul class="dropdown-menu"> <form> <li> <div class="menu-item">bla bla bla</div> </li> </form> </ul>
$('body').on("click", ".dropdown-menu", function (e) { $(this).parent().is(".open") && e.stopPropagation(); });
这可能适用于任何情况。
- 演示: http : //jsfiddle.net/4y8tLgcp/
$('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'); });
我已经再次更新,以尽可能最聪明和function。 当您hover在导航之外时,它现在closures,在您进入导航时保持打开状态。 简单完美。
我最近有一个类似的问题,并试图通过删除data属性data-toggle="dropdown"
和监听click
与event.stopPropagation()
调用解决它的不同方式。
第二种方式看起来更可取。 Bootstrap开发者也使用这种方式。 在源文件中我find了下拉元素的初始化:
// 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() })
build议您可以在类的.dropdown
放置一个form
元素,以避免closures下拉菜单。
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>
演示 :
generics: https : //jsfiddle.net/kerryjohnson/omefq68b/1/
您的演示与此解决scheme: http : //jsfiddle.net/kerryjohnson/80oLdtbf/101/
您可以停止点击传播的下拉列表,然后使用传送带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 – (默认)在单击任何元素时自动closures下拉列表,只要点击的元素不是input或textarea。
像例如Bootstrap 4 Alpha有这个菜单事件。 为什么不使用?
// PREVENT INSIDE MEGA DROPDOWN $('.dropdown-menu').on("click.bs.dropdown", function (e) { e.stopPropagation(); e.preventDefault(); });
我知道这个问题是专门针对jQuery,但对于任何使用AngularJS的人都有这个问题,你可以创build一个处理这个问题的指令:
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
到触发菜单closures的元素中,就可以防止它。 对我来说,这是一个自动closures菜单的select
元素:
<div class="dropdown-menu"> <select dropdown-prevent-close name="myInput" id="myInput" ng-model="myModel"> <option value="">Select Me</option> </select> </div>
我发现没有解决scheme,因为我想使用默认的引导程序导航。 这是我解决这个问题的方法:
$(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代码(重新发明轮子)。 上述场景可以通过引导自动closures选项进行pipe理。 您可以提供以下任一值来自动closures :
-
总是 – (默认)当点击任何元素时自动closures下拉菜单。
-
outsideClick – 仅在用户点击下拉菜单之外的任何元素时自动closures下拉菜单。
-
禁用 – 禁用自动closures
看看下面的plunkr:
http://plnkr.co/edit/gnU8M2fqlE0GscUQtCWa?p=preview
组
uib-dropdown auto-close="disabled"
希望这可以帮助 :)
$(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') }); });
对我来说最简单的工作解决scheme是:
- 向不应导致下拉式closures的元素添加
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 4 Alpha 6] [Rails]对于Rails开发者, e.stopPropagation()
会导致link_to
与data-method
不良行为不相等,因为默认情况下它会将所有的请求作为get
返回。
为了解决这个问题,我build议这个解决scheme是普遍的
$('.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>
在.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 } });
前面的例子避免了与容器对象有关的事件,现在容器inheritance了类保持打开状态,并在closures之前检查。
没有别的为我工作,所以我终于做了这个问题,自己解决了这个问题。
这解决了问题,而没有制动别的东西
$(".navbar").on("click",".megadropdown .dropdown-menu,.megadropdown .dropdown-menu *",function(e){ setTimeout(function(){$(e.target).parents(".dropdown").addClass("open");},50); });
$(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; } });
});