Javascript 如何通过从页面上的任何地方(其他地方)单击来关闭 Twitter Bootstrap 弹出窗口?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8947749/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I close a Twitter Bootstrap popover with a click from anywhere (else) on the page?
提问by Travis Northcutt
I'm currently using popovers with Twitter Bootstrap, initiated like this:
我目前正在使用带有 Twitter Bootstrap 的弹出框,如下所示:
$('.popup-marker').popover({
html: true,
trigger: 'manual'
}).click(function(e) {
$(this).popover('toggle');
e.preventDefault();
});
As you can see, they're triggered manually, and clicking on .popup-marker (which is a div with a background image) toggles a popover. This works great, but I'd like to also be able to close the popover with a click anywhere else on the page (but not on the popover itself!).
如您所见,它们是手动触发的,单击 .popup-marker(带有背景图像的 div)会切换弹出框。这很好用,但我也希望能够通过点击页面上的任何其他地方(但不是在弹出框本身上!)来关闭弹出框。
I've tried a few different things, including the following, but with no results to show for it:
我尝试了一些不同的事情,包括以下内容,但没有显示结果:
$('body').click(function(e) {
$('.popup-marker').popover('hide');
});
How can I close the popover with a click anywhere else on the page, but not with a click onthe popover itself?
如何通过单击页面上的其他任何位置而不是单击弹出框本身来关闭弹出框?
采纳答案by Radu Cugut
Presuming that only one popover can be visible at any time, you can use a set of flags to mark when there's a popover visible, and only then hide them.
假设任何时候只有一个弹出窗口可见,您可以使用一组标志来标记何时有一个弹出窗口可见,然后才隐藏它们。
If you set the event listener on the document body, it will trigger when you click the element marked with 'popup-marker'. So you'll have to call stopPropagation()
on the event object. And apply the same trick when clicking on the popover itself.
如果你在文档正文上设置了事件监听器,它会在你点击标有'popup-marker'的元素时触发。所以你必须调用stopPropagation()
事件对象。并在单击弹出窗口本身时应用相同的技巧。
Below is a working JavaScript code that does this. It uses jQuery >= 1.7
下面是执行此操作的有效 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;
});
});
http://jsfiddle.net/AFffL/539/
http://jsfiddle.net/AFffL/539/
The only caveat is that you won't be able to open 2 popovers at the same time. But I think that would be confusing for the user, anyway :-)
唯一需要注意的是,您将无法同时打开 2 个弹出窗口。但我认为这会让用户感到困惑,无论如何:-)
回答by prbaron
This is even easier :
这更容易:
$('html').click(function(e) {
$('.popup-marker').popover('hide');
});
$('.popup-marker').popover({
html: true,
trigger: 'manual'
}).click(function(e) {
$(this).popover('toggle');
e.stopPropagation();
});
回答by Miika L.
I had a similar need, and found this great little extension of the Twitter Bootstrap Popover by Lee Carmichael, called BootstrapX - clickover. He also has some usage examples here. Basically it will change the popover into an interactive component which will close when you click elsewhere on the page, or on a close button within the popover. This will also allow multiple popovers open at once and a bunch of other nice features.
我有类似的需求,并发现了 Lee Carmichael 的 Twitter Bootstrap Popover 的这个很棒的小扩展,称为 BootstrapX - clickover。他在这里也有一些使用示例。基本上它会将弹出窗口更改为一个交互式组件,当您单击页面上的其他地方或弹出窗口中的关闭按钮时,该组件将关闭。这也将允许同时打开多个弹出窗口和一堆其他不错的功能。
Usage example
使用示例
<button rel="clickover" data-content="Show something here.
<button data-dismiss='clickover'
>Close Clickover</button>"
>Show clickover</button>
javascript:
javascript:
// load click overs using 'rel' attribute
$('[rel="clickover"]').clickover();
回答by RayOnAir
The accepted solution gave me some issues (clicking on the '.popup-marker' element of the opened popover made the popovers not work afterwards). I came up with this other solution that works perfectly for me and it's quite simple (I'm using Bootstrap 2.3.1):
接受的解决方案给了我一些问题(单击打开的弹出框的“.popup-marker”元素使弹出框之后无法工作)。我想出了另一个非常适合我的解决方案,它非常简单(我使用的是 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');
}
});
UPDATE: This code works with Bootstrap 3 as well!
更新:此代码也适用于 Bootstrap 3!
回答by Andrej Sramko
read "Dismiss on next click" here http://getbootstrap.com/javascript/#popovers
在这里阅读“在下次点击时关闭” http://getbootstrap.com/javascript/#popovers
You can use the focus trigger to dismiss popovers on the next click, but you have to use use the <a>
tag, not the <button>
tag, and you also must include a tabindex
attribute...
您可以使用焦点触发器在下次点击时关闭弹出窗口,但您必须使用<a>
标签,而不是<button>
标签,并且您还必须包含一个tabindex
属性...
Example:
例子:
<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>
回答by David Wolever
All of the existing answers are fairly weak, as they rely on capturing alldocument events then finding active popovers, or modifying the call to .popover()
.
所有现有的答案都相当薄弱,因为它们依赖于捕获所有文档事件,然后找到活动的弹出框,或修改对.popover()
.
A much better approach is to listen for show.bs.popover
events on the document's body then react accordingly. Below is code which will close popovers when the document is clicked or escis pressed, onlybinding event listeners when popovers are shown:
更好的方法是侦听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);
}
回答by Ibrahim
https://github.com/lecar-red/bootstrapx-clickover
https://github.com/lecar-red/bootstrapx-clickover
It's an extension of twitter bootstrap popover and will solve the problem very simply.
它是 twitter bootstrap popover 的扩展,可以非常简单地解决问题。
回答by moollaza
For some reason none of the other solutions here worked for me. However, after a lot of troubleshooting, I finally arrived at this method which works perfectly (for me at least).
出于某种原因,这里的其他解决方案都不适合我。然而,经过大量的故障排除后,我终于找到了这个完美的方法(至少对我来说)。
$('html').click(function(e) {
if( !$(e.target).parents().hasClass('popover') ) {
$('#popover_parent').popover('destroy');
}
});
In my case I was adding a popover to a table and absolutely positioning it above/below the td
that was clicked. The table selection was handled by jQuery-UI Selectable so I'm not sure if that was interfering. However whenever I clicked inside the popover my click handler which targeted $('.popover')
never worked and the event handling was always delegated to the $(html)
click handler. I'm fairly new to JS so perhaps I'm just missing something?
就我而言,我正在向表格中添加一个弹出框,并将其绝对定位td
在点击的上方/下方。表选择是由 jQuery-UI Selectable 处理的,所以我不确定这是否有干扰。但是,每当我在弹出窗口中单击时,我的目标单击处理程序都$('.popover')
无法工作,并且事件处理始终委托给$(html)
单击处理程序。我对 JS 还很陌生,所以也许我只是错过了一些东西?
Anyways I hope this helps someone!
无论如何,我希望这对某人有所帮助!
回答by Bert-Jan Steerneman
I give all my popovers anchors the class activate_popover
. I activate them all at once onload
我给我所有的弹出框锚类activate_popover
。我在加载时一次性激活它们
$('body').popover({selector: '.activate-popover', html : true, container: 'body'})
$('body').popover({selector: '.activate-popover', html : true, container: 'body'})
to get the click away functionality working I use (in coffee script):
为了让我使用的点击功能正常工作(在咖啡脚本中):
$(document).on('click', (e) ->
clickedOnActivate = ($(e.target).parents().hasClass("activate-popover") || $(e.target).hasClass("activate-popover"))
clickedAway = !($(e.target).parents().hasClass("popover") || $(e.target).hasClass("popover"))
if clickedAway && !clickedOnActivate
$(".popover.in").prev().popover('hide')
if clickedOnActivate
$(".popover.in").prev().each () ->
if !$(this).is($(e.target).closest('.activate-popover'))
$(this).popover('hide')
)
Which works perfectly fine with bootstrap 2.3.1
与引导程序 2.3.1 完美配合
回答by Roshdy
Even though there are a lot of solutions here, i'd like to propose mine as well, i don't know if there is some solution up there that solves it all, but i tried 3 of them and they had issues, like clicking on the popover it self makes it hide, others that if i had another popover buttons clicked both/multiple popovers would still appear (like in the selected solution), How ever, This one fixed it all
即使这里有很多解决方案,我也想提出我的解决方案,我不知道那里是否有一些解决方案可以解决所有问题,但是我尝试了其中的 3 个,但它们遇到了问题,例如单击在弹出窗口上它自己隐藏,其他人如果我有另一个弹出窗口按钮点击两个/多个弹出窗口仍然会出现(就像在选定的解决方案中一样),但是,这个解决了所有问题
var curr_popover_btn = null;
// Hide popovers function
function hide_popovers(e)
{
var container = $(".popover.in");
if (!container.is(e.target) // if the target of the click isn't the container...
&& container.has(e.target).length === 0) // ... nor a descendant of the container
{
if( curr_popover_btn != null )
{
$(curr_popover_btn).popover('hide');
curr_popover_btn = null;
}
container.hide();
}
}
// Hide popovers when out of focus
$('html').click(function(e) {
hide_popovers(e);
});
$('.popover-marker').popover({
trigger: 'manual'
}).click(function(e) {
hide_popovers(e);
var $popover_btns = $('.popover-marker');
curr_popover_btn = this;
var $other_popover_btns = jQuery.grep($($popover_btns), function(popover_btn){
return ( popover_btn !== curr_popover_btn );
});
$($other_popover_btns).popover('hide');
$(this).popover('toggle');
e.stopPropagation();
});