在 Bootstrap 3 中单击导航栏元素外部时如何关闭打开的折叠导航栏?

Posted

技术标签:

【中文标题】在 Bootstrap 3 中单击导航栏元素外部时如何关闭打开的折叠导航栏?【英文标题】:How to close an open collapsed navbar when clicking outside of the navbar element in Bootstrap 3? 【发布时间】:2014-07-09 00:20:09 【问题描述】:

如何在单击导航栏元素外部时关闭打开的折叠导航栏?目前,打开或关闭它的唯一方法是单击navbar-toggle 按钮。

示例和代码见here:

到目前为止,我尝试了以下似乎不起作用的方法:

jQuery(document).click(function() 

);

jQuery('.navbar').click(function(event) 
    jQuery(".navbar-collapse").collapse('hide');
    event.stopPropagation();
);

【问题讨论】:

当我在菜单外单击时,演示中的“损坏”链接会关闭;什么坏了? @Paulie_D 我已经用我的尝试更新了我的问题。 @cDima 你指的是什么断开的链接?我没有看到。 我假设他的意思是“汉堡包”元素以适当的宽度打开菜单并重新单击将其关闭。我假设他希望在单击任意位置时发生相同的“关闭”。 所以只要在你的 JQuery 函数中选择 body 就可以了,假设检查菜单是否打开。 【参考方案1】:

看看:

$(document).ready(function () 
    $(document).click(function (event) 
        var clickover = $(event.target);
        var _opened = $(".navbar-collapse").hasClass("navbar-collapse in");
        if (_opened === true && !clickover.hasClass("navbar-toggle")) 
            $("button.navbar-toggle").click();
        
    );
);

你的小提琴适用于:http://jsfiddle.net/52VtD/5718/

它是this answer的修改版,缺少动画,也稍微复杂一点。

我知道,调用 click() 不是很优雅,但 collapse('hide') 对我也不起作用,而且我认为动画比几乎添加和删除类要好一些。

【讨论】:

是的,我不确定为什么 collapse('hide) 不起作用。不过,这个解决方案效果很好。 如果导航栏包含搜索框则不起作用,点击搜索文本输入一定不能关闭导航栏:jsfiddle.net/duongphuhiep/xtyb6wwu/1 无论出于何种原因,我在最新的引导程序 3 上都需要这个:.hasClass("navbar-collapse collapse in") 这在 angularJS 和 ui-router 中使用时非常好用。在 $stateChangeSuccess 上使用它非常好 如果使用 Aurelia 你可以这样使用this.eventAggregator.subscribe('router:navigation:success', response => jQuery("navigation button.navbar-toggle").click(); );【参考方案2】:

接受的答案似乎无法正常工作。它只需要检查“navbar-collapse”是否有“in”类。然后我们可以使用导航栏的引用按预期触发折叠方法。

$(document).click(function (event) 
    var clickover = $(event.target);
    var $navbar = $(".navbar-collapse");               
    var _opened = $navbar.hasClass("in");
    if (_opened === true && !clickover.hasClass("navbar-toggle"))       
        $navbar.collapse('hide');
    
);

【讨论】:

对我来说进行了一次更改,效果很好。我会确保如果用户确实点击了不是链接的打开导航上的某个位置,它将保持打开状态。 如何将它与导航栏中的输入框结合起来?因为当我点击导航栏内的输入框时,导航栏也消失了。 是的,接受的答案也没有为我做任何事情。这行得通。 谢谢!我找这个太久了。 我在哪里可以添加这个?【参考方案3】:

使用它对我有用。

$(function() 
  $(document).click(function (event) 
    $('.navbar-collapse').collapse('hide');
  );
);

【讨论】:

您缺少一个右括号来终止 click 方法。 );【参考方案4】:

我决定使用的解决方案取自此处接受的答案和this answer

jQuery('body').bind('click', function(e) 
    if(jQuery(e.target).closest('.navbar').length == 0) 
        // click happened outside of .navbar, so hide
        var opened = jQuery('.navbar-collapse').hasClass('collapse in');
        if ( opened === true ) 
            jQuery('.navbar-collapse').collapse('hide');
        
    
);

如果用户单击.navbar 元素之外的任何位置,这将隐藏打开的折叠导航菜单。当然,点击.navbar-toggle 仍然可以关闭菜单。

【讨论】:

我会将body 更改为html 以解决高设备或内容很少的页面。 body 的高度与内容匹配,而不是可见的屏幕区域,因此如果您的页面内容很少,则不会触发内容区域下方的点击。否则,即使使用导航栏子菜单,也是一个很好的答案并且效果很好。 效果很好。要使其关闭菜单本身和导航栏切换按钮以外的任何单击,只需将第一个“.navbar”替换为“.navbar-collapse”,这样即使您单击导航栏中的其他链接,它仍然会关闭菜单。 我不得不从 hasClass 检查中删除“in”类,没有它就无法工作。可能是因为我的 .navbar-collapse 元素中没有“in”类。我正在使用引导程序 4。【参考方案5】:

Bootstrap 4(.3.1) 转换后的喷嘴人答案:

$(document).ready(function () 
    $(document).click(
        function (event) 
            var target = $(event.target);
            var _mobileMenuOpen = $(".navbar-collapse").hasClass("show");
            if (_mobileMenuOpen === true && !target.hasClass("navbar-toggler")) 
                $("button.navbar-toggler").click();
            
        
    );
);

放置在 ngOnInit() 中。

加载文档时,此代码等待点击事件。如果移动菜单下拉菜单打开(即导航栏的可折叠部分具有“显示”类)并且单击的对象(目标)不是移动菜单按钮(即没有“导航栏切换器”类),则我们告诉移动菜单按钮它已被点击,然后菜单关闭。

【讨论】:

这对我有用。所有其他答案都是几年前的,可能不起作用。如果您按照指南使用 Bootstrap 4,这将起作用【参考方案6】:

stopPropagation() 并不总是最好的解决方案。而是使用类似的东西:

jQuery(document.body).on('click', function(ev)
    if(jQuery(ev.target).closest('.navbar-collapse').length) return; // Not return false

    // Hide navbar
);

我认为假设您永远不想收听来自.navbar 的任何其他事件是很危险的。如果你使用stopPropagation(),这是不可能的。

【讨论】:

嗨@pstenstrm。谢谢你,虽然它似乎不起作用?我已经用你的 jQuery 更新了 JSFIDDLE:jsfiddle.net/52VtD/5708 嗯,.navbar 几乎是整个文档的一部分。我已经更新了答案 注意点!我给 body 指定了 700px 的高度,所以 jsfiddle 更好地说明了正在发生的事情:jsfiddle.net/52VtD/5709 - 现在的问题是在 body 中单击会关闭并打开下拉菜单。我只需要关闭它。只能通过切换按钮 navbar-toggle 打开【参考方案7】:

我有一个场景,我有纯文本,如果用户意外单击纯文本,我不希望面板关闭。即使您单击不是链接的项目的文本,此处的其他答案关闭面板。

为了解决这个问题,我在 Paul Tarr 的回答中添加了一个检查方法,以查看点击是否发生在内部任何地方:

if ($(event.target).parents(".navbar-collapse").length < 1)  

完整的代码将变为:

$(document).click(function (event) 
if ($(event.target).parents(".navbar-collapse").length < 1) 
    var clickover = $(event.target);
    var $navbar = $(".navbar-collapse");               
    var _opened = $navbar.hasClass("in");
    if (_opened === true && !clickover.hasClass("navbar-toggle"))       
        $navbar.collapse('hide');
    
  
);

在这个demo fiddle 中,您可以看到,如果您单击面板内的非链接,它不会折叠它。

【讨论】:

【参考方案8】:

我在@nozzleman 的回答中添加了一个条件,以检查是否对菜单中的任何元素进行了点击或单击,如果是这样,请不要折叠它。

$(document).ready(function () 
    $(document).click(function (event) 
        var clickover = $(event.target);
        var _opened = $(".navbar-collapse").hasClass("navbar-collapse in");
        if (_opened === true && !clickover.hasClass("navbar-toggle") && clickover.parents('.navbar-collapse').length == 0) 
            $("button.navbar-toggle").click();
        
    );
);

【讨论】:

【参考方案9】:

以下代码对我有用,其优点是在小屏幕上,当您使用 .navbar .navbar-expand 类单击其导航父级时,它不会隐藏 .collapse:

$(document).click(function (e)   
    if($('.collapse').hasClass('show') && !$('nav').is(e.target) && $('nav').has(e.target).length === 0)
        $('.navbar-toggler').click()
    
)

【讨论】:

【参考方案10】:

对于最新的 Bootstrap,这是正确的答案。

$(document).click(function (event) 
    var clickover = $(event.target);
    var $navbar = $(".navbar-collapse");               
    var _opened = $navbar.hasClass("show");
    if (_opened === true && !clickover.hasClass("navbar-toggler"))       
        $navbar.collapse('hide');
    
);

它会读取 .navbar-collapse 是否在类中包含单词 show(这意味着菜单已打开),并在您单击/点击任意位置时隐藏导航栏。

【讨论】:

【参考方案11】:

对于引导程序 4

Bootstrap 4 没有 in 类。这是 Coffeescript。

  $(document).click (e)->
    #console.log e.target
    unless $('#toggle-button').has(e.target).length || $('#toggle-menu').has(e.target).length
      $('#toggle-menu').collapse('hide')

所以基本上,除非你点击按钮或菜单,否则关闭菜单。

注意:奇怪的是,在 ios 上点击文本不会注册点击事件,也不会注册 mouseup 事件。但是,单击图像会触发事件。

【讨论】:

【参考方案12】:

对于引导程序 4:

$(document).click(function(event) 
  $(event.target).closest(".navbar").length || $(".navbar-collapse.show").length && $(".navbar-collapse.show").collapse("hide")
);

【讨论】:

请为您的答案添加解释。【参考方案13】:
$(document).click(function (event) 
 if ($('.navbar-collapse').attr('aria-expanded') == "true") 
        $('.navbar-collapse:visible').click();
    
);

【讨论】:

【参考方案14】:
$(window).click(function (e) 
     if ($(e.target).closest('.codehim-dropdown').length) 
         return;
     
     if ($(e.target).closest(offCanvas).length) 
         return;
     

     //check if menu really opened
     if ($(hamburger).hasClass("active")) 
         closeMenu();
     

     $(dimOverlay).fadeOut();

     $(".menu-items").slideUp();
     $(".dropdown-heading").removeClass("active");

);

【讨论】:

【参考方案15】:

我在这里的一些答案有一些问题,我也希望能够按需关闭扩展菜单。所以我用一个简单的函数来模拟点击。

function closeMenu()
  element = document.getElementById('nav_top');
  if(element)
    if(element.classList.contains('show'))
      document.getElementById('navbar_toggler').dispatchEvent(new CustomEvent('click'));
    
  

$(document).ready(function () 
  $(document).click(function (event) 
    closeMenu();
  );
);

使用此方法,您可以在外部单击时关闭它,也可以随时从任何其他函数调用closeMenu()

【讨论】:

谢谢@Cosmin Staicu 更好地格式化我的答案。

以上是关于在 Bootstrap 3 中单击导航栏元素外部时如何关闭打开的折叠导航栏?的主要内容,如果未能解决你的问题,请参考以下文章

如何在折叠的导航栏中默认打开 Bootstrap 3 下拉菜单

当用户在菜单外单击时,如何关闭 Bootstrap 导航栏下拉菜单?

从 bootstrap 3 导航栏的折叠中排除菜单项

Bootstrap 4导航栏折叠菜单右对齐

Bootstrap 导航栏切换器仅在第一次单击时起作用

激活 Twitter Bootstrap 导航栏链接