【问题标题】:Hiding Bootstrap Popover on Click Outside Popover在弹出框外单击时隐藏引导弹出框
【发布时间】:2013-07-24 09:47:05
【问题描述】:

当用户单击弹出框外的任何位置时,我试图隐藏 Bootstrap 弹出框。 (我真的不知道为什么 Bootstrap 的创建者决定不提供这个功能。)

我找到了下面的代码on the web但是我真的不明白。

// Hide popover on click anywhere on the document except itself
$(document).click(function(e) {
    // Check for click on the popup itself
    $('.popover').click(function() {
        return false; // Do nothing
    });  
    // Clicking on document other than popup then hide the popup
    $('.pop').popover('hide');  
});

让我感到困惑的主要是$('.popover').click(function() { return false; }); 这一行。这行不是为单击事件添加事件处理程序吗?这如何防止对 popover('hide') 的调用隐藏弹出框?

有没有人见过更好的技术?

注意:我知道这个问题的变体以前在这里被问过,但这些问题的答案涉及的代码比上面的代码更复杂。所以我的问题实际上是关于上面的代码

【问题讨论】:

  • @Icarus:谢谢,但这并不能真正回答我的问题。我知道返回 false 会停止进一步处理,但是添加点击处理程序如何改变后面的行的行为?在弹出窗口关闭后,这不会阻止点击工作吗?
  • 该代码完全符合您的描述。每次有人单击文档上的任何位置(包括.popover)时,它都会添加一个完全不执行任何操作的事件侦听器。这只是浪费内存,因为同一元素上可能有许多事件侦听器,对于同一事件,它们最终会相互堆叠
  • @Dogoku:谢谢,但是为什么点击处理程序甚至在调用popover('hide') 时会发挥作用?另外,当方法返回时,新的处理程序是否会被删除?
  • 它应该回答你的问题,至少这一行应该:“从 在 jQuery 事件处理程序中返回 false 实际上与调用 e.preventDefault 和 e.stopPropagation 相同 ”。在您的代码示例中,弹出框单击处理程序中的return false 将停止传播到文档的单击事件处理程序,因此不会隐藏它。

标签: javascript jquery twitter-bootstrap


【解决方案1】:

我做了http://jsfiddle.net/BcczZ/2/,希望能回答你的问题

示例 HTML

<div class="well>
    <a class="btn" data-toggle="popover" data-content="content.">Popover</a>
    <a class="btn btn-danger bad">Bad button</a>
</div>

JS

var $popover = $('[data-toggle=popover]').popover();

//first event handler for bad button
$('.bad').click(function () {
    alert("clicked");
});


$(document).on("click", function (e) {
    var $target = $(e.target),
    var isPopover = $target.is('[data-toggle=popover]'),
        inPopover = $target.closest('.popover').length > 0

    //Does nothing, only prints on console and wastes memory. BAD CODE, REMOVE IT
    $('.bad').click(function () { 
        console.log('clicked');
        return false;
    });

    //hide only if clicked on button or inside popover
    if (!isPopover && !inPopover) $popover.popover('hide');
});

正如我在评论中提到的,事件处理程序不会被覆盖,它们只是堆叠。由于.bad 按钮上已经有一个事件处理程序,它将与任何其他事件处理程序一起被触发

在 jsfiddle 中打开您的控制台,在页面某处按下 5 次(不是弹出按钮),然后单击 bad button,您应该会看到 clicked 打印的次数与您按下的次数相同

希望对你有帮助


附注: 如果你仔细想想,你已经看到了这种情况,尤其是在 jQuery 中。 想想使用多个 jquery 插件的页面中存在的所有$(document).ready(...)。该行只是在文档的ready 事件上注册了一个事件处理程序

【讨论】:

  • 好的,感谢演示。查看我最初发布的代码,这对我来说似乎并不理想,因为我可能会添加一个整天只返回 false 的新处理程序。如果页面没有刷新,它们可能会增长到任意数量。看起来一点也不理想。
  • 只需删除处理bad button 的代码并使用我的其余代码。应该像你想要的那样工作
【解决方案2】:

我刚刚做了一个更基于事件的解决方案。

var $toggle = $('.your-popover-button');
$toggle.popover();

var hidePopover = function() {
    $toggle.popover('hide');
};

$toggle.on('shown', function () {
    var $popover = $toggle.next();
    $popover.on('mousedown', function(e) {
        e.stopPropagation();
    });
    $toggle.on('mousedown', function(e) {
        e.stopPropagation();
    });
    $(document).on('mousedown',hidePopover);
});

$toggle.on('hidden', function () {
    $(document).off('mousedown', hidePopover);
});

【讨论】:

    【解决方案3】:

    简短的回答 将此插入到 bootstrap min.js

    当popout onblur 会隐藏popover
    当弹出多个时,旧的弹出框将被隐藏

    $count=0;$(document).click(function(evt){if($count==0){$count++;}else{$('[data-toggle="popover"]').popover('hide');$count=0;}});$('[data-toggle="popover"]').popover();$('[data-toggle="popover"]').on('click', function(e){$('[data-toggle="popover"]').not(this).popover('hide');$count=0;});
    

    【讨论】:

      【解决方案4】:

      以上解决方案都没有对我 100% 有效,因为我必须在另一个或相同的弹出窗口上单击两次才能再次打开它。我从头开始编写解决方案,简单有效。

         $('[data-toggle="popover"]').popover({
              html:true,
              trigger: "manual",
              animation: false
          });
      
          $(document).on('click','body',function(e){
              $('[data-toggle="popover"]').each(function () {
                  $(this).popover('hide');
              });
      
              if (e.target.hasAttribute('data-toggle') && e.target.getAttribute('data-toggle') === 'popover') {
                  e.preventDefault();
                  $(e.target).popover('show');
              }
              else if (e.target.parentElement.hasAttribute('data-toggle') && e.target.parentElement.getAttribute('data-toggle') === 'popover') {
                  e.preventDefault();
                  $(e.target.parentElement).popover('show');
              }
          });
      

      【讨论】:

        【解决方案5】:

        我的解决方案,适用于 Bootstrap v3 100%

        $('html').on('click', function(e) {
            if(typeof $(e.target).data('original-title') !== 'undefined'){
                 $('[data-original-title]').not(e.target).popover('hide');
            }
        
            if($(e.target).parents().is('[data-original-title]')){
                 $('[data-original-title]').not($(e.target).closest('[data-original-title]')).popover('hide');
            }
        
            if (typeof $(e.target).data('original-title') == 'undefined' &&
        !$(e.target).parents().is('.popover.in') && !$(e.target).parents().is('[data-original-title]')) {
                $('[data-original-title]').popover('hide');
            }
        });
        

        【讨论】:

          猜你喜欢
          • 2015-12-19
          • 2013-11-10
          • 2022-12-31
          • 2021-08-15
          • 2013-01-09
          • 2013-01-07
          • 2013-02-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多