如何通过页面上任何地方(否则)点击关闭Twitter Bootstrap popover?

Tra*_*utt 153 javascript jquery twitter-bootstrap

我目前正在使用Twitter Bootstrap的popovers,就像这样:

$('.popup-marker').popover({
        html: true,
        trigger: 'manual'
    }).click(function(e) {
        $(this).popover('toggle');
        e.preventDefault();
    });
Run Code Online (Sandbox Code Playgroud)

如您所见,它们是手动触发的,然后单击.popup-marker(带有背景图像的div)切换弹出窗口.这很好用,但我也希望能够通过点击页面上任何其他位置来关闭popover(但不能在popover本身!).

我尝试了一些不同的东西,包括以下内容,但没有显示结果:

$('body').click(function(e) {
    $('.popup-marker').popover('hide');
});
Run Code Online (Sandbox Code Playgroud)

如何通过单击页面上的任何其他位置来关闭弹出窗口,但不能单击弹出窗口本身?

Rad*_*gut 102

假设在任何时候只能看到一个弹出窗口,您可以使用一组标记来标记弹出窗口何时可见,然后才隐藏它们.

如果在文档正文中设置事件侦听器,则在单击标有"popup-marker"的元素时将触发该事件侦听器.所以你必须调用stopPropagation()事件对象.单击弹出窗口时应用相同的技巧.

下面是一个可以执行此操作的JavaScript代码.它使用jQuery> = 1.7

jQuery(function() {
    var isVisible = false;

    var hideAllPopovers = function() {
       $('.popup-marker').each(function() {
            $(this).popover('hide');
        });  
    };

    $('.popup-marker').popover({
        html: true,
        trigger: 'manual'
    }).on('click', function(e) {
        // if any other popovers are visible, hide them
        if(isVisible) {
            hideAllPopovers();
        }

        $(this).popover('show');

        // handle clicking on the popover itself
        $('.popover').off('click').on('click', function(e) {
            e.stopPropagation(); // prevent event for bubbling up => will not get caught with document.onclick
        });

        isVisible = true;
        e.stopPropagation();
    });


    $(document).on('click', function(e) {
        hideAllPopovers();
        isVisible = false;
    });
});
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/AFffL/539/

唯一需要注意的是,您无法同时打开2个弹出式窗口.但我觉得这对用户来说会让人感到困惑,无论如何:-)

  • 为什么不在$(this).popover('show')之前运行$('.popup-marker').popover('hide')(隐藏它们全部),这样就不需要任何isVisible和clickedAway变量了? (3认同)

prb*_*ron 73

这更容易:

$('html').click(function(e) {
    $('.popup-marker').popover('hide');
});

$('.popup-marker').popover({
    html: true,
    trigger: 'manual'
}).click(function(e) {
    $(this).popover('toggle');
    e.stopPropagation();
});
Run Code Online (Sandbox Code Playgroud)

  • 希望使用此但由于某种原因没有成功.因为`e.stopPropagation(),所以点击事件永远不会到达`html`;相反,我使用的是`$('.popup-marker').on('show',function(event){$('.popup -marker').filter(function(index,element){return element!= event.target;}).popover('hide');});`也做得很好(不知道是否有)但性能差异) (4认同)
  • 这个问题的一个问题是popover仍然存在,只是隐藏.因此,例如,如果您在弹出窗口中有链接,则可以将光标悬停在以前的位置,并仍然可以将光标更改为这些链接. (2认同)

Mii*_* L. 48

我有类似的需求,发现了这个名为BootstrapX的Twitter Bootstrap Popover的小扩展,叫做BootstrapX - clickover.他在这里也有一些用法示例.基本上它会将popover更改为一个交互式组件,当您单击页面上的其他位置或弹出窗口中的关闭按钮时,该组件将关闭.这也将允许一次打开多个弹出窗口和一堆其他不错的功能.

插件可以在这里找到.

用法示例

<button rel="clickover" data-content="Show something here. 
    <button data-dismiss='clickover'
    >Close Clickover</button>"
>Show clickover</button>
Run Code Online (Sandbox Code Playgroud)

JavaScript的:

// load click overs using 'rel' attribute
$('[rel="clickover"]').clickover();
Run Code Online (Sandbox Code Playgroud)


Ray*_*Air 37

接受的解决方案给了我一些问题(点击打开的popover的'.popup-marker'元素使得popovers随后不起作用).我想出了另一个适合我的解决方案,它非常简单(我正在使用Bootstrap 2.3.1):

$('.popup-marker').popover({
    html: true,
    trigger: 'manual'
}).click(function(e) {
    $('.popup-marker').not(this).popover('hide');
    $(this).popover('toggle');
});
$(document).click(function(e) {
    if (!$(e.target).is('.popup-marker, .popover-title, .popover-content')) {
        $('.popup-marker').popover('hide');
    }
});
Run Code Online (Sandbox Code Playgroud)

更新:此代码也适用于Bootstrap 3!

  • 很好用$ .not! (2认同)
  • 或者更好的`if (!$(e.target).is('.popup-marker') &amp;&amp; $(e.target).closest('.popover').length === 0)` (2认同)

And*_*mko 19

请阅读http://getbootstrap.com/javascript/#popovers上的"在下次点击时关闭"

您可以使用焦点触发器在下一次单击时关闭弹出窗口,但您必须使用<a>标记而不是<button>标记,并且还必须包含tabindex属性...

例:

<a href="#" tabindex="0" class="btn btn-lg btn-danger"
  data-toggle="popover" data-trigger="focus" title="Dismissible popover"
  data-content="And here's some amazing content. It's very engaging. Right?">
  Dismissible popover
</a>
Run Code Online (Sandbox Code Playgroud)

  • 问题表明,如果点击是在popover上,他不希望它解雇.任何地方的任何点击都会解雇它. (2认同)
  • 有关信息,这也适用于`tooltip`,即使它在实际文档中没有明确提及. (2认同)

Dav*_*ver 7

所有现有的答案都相当薄弱,因为它们依赖于捕获所有文档事件,然后查找活动的弹出窗口,或者修改对其的调用.popover().

更好的方法是show.bs.popover在文档的主体上侦听事件,然后做出相应的反应.下面是单击文档或esc按下文档时将关闭弹出框的代码,显示弹出框时的绑定事件侦听器:

function closePopoversOnDocumentEvents() {
  var visiblePopovers = [];

  var $body = $("body");

  function hideVisiblePopovers() {
    $.each(visiblePopovers, function() {
      $(this).popover("hide");
    });
  }

  function onBodyClick(event) {
    if (event.isDefaultPrevented())
      return;

    var $target = $(event.target);
    if ($target.data("bs.popover"))
      return;

    if ($target.parents(".popover").length)
      return;

    hideVisiblePopovers();
  }

  function onBodyKeyup(event) {
    if (event.isDefaultPrevented())
      return;

    if (event.keyCode != 27) // esc
      return;

    hideVisiblePopovers();
    event.preventDefault();
  }

  function onPopoverShow(event) {
    if (!visiblePopovers.length) {
      $body.on("click", onBodyClick);
      $body.on("keyup", onBodyKeyup);
    }
    visiblePopovers.push(event.target);
  }

  function onPopoverHide(event) {
    var target = event.target;
    var index = visiblePopovers.indexOf(target);
    if (index > -1) {
      visiblePopovers.splice(index, 1);
    }
    if (visiblePopovers.length == 0) {
      $body.off("click", onBodyClick);
      $body.off("keyup", onBodyKeyup);
    }
  }

  $body.on("show.bs.popover", onPopoverShow);
  $body.on("hide.bs.popover", onPopoverHide);
}
Run Code Online (Sandbox Code Playgroud)


小智 5

https://github.com/lecar-red/bootstrapx-clickover

它是twitter bootstrap popover的扩展,可以非常简单地解决问题.