How to dismiss a Twitter Bootstrap popover by clicking outside?
Solution 1:
Update: A slightly more robust solution: http://jsfiddle.net/mattdlockyer/C5GBU/72/
For buttons containing text only:
$('body').on('click', function (e) {
//did not click a popover toggle or popover
if ($(e.target).data('toggle') !== 'popover'
&& $(e.target).parents('.popover.in').length === 0) {
$('[data-toggle="popover"]').popover('hide');
}
});
For buttons containing icons use (this code has a bug in Bootstrap 3.3.6, see the fix below in this answer)
$('body').on('click', function (e) {
//did not click a popover toggle, or icon in popover toggle, or popover
if ($(e.target).data('toggle') !== 'popover'
&& $(e.target).parents('[data-toggle="popover"]').length === 0
&& $(e.target).parents('.popover.in').length === 0) {
$('[data-toggle="popover"]').popover('hide');
}
});
For JS Generated Popovers Use '[data-original-title]'
in place of '[data-toggle="popover"]'
Caveat: The solution above allows multiple popovers to be open at once.
One popover at a time please:
Update: Bootstrap 3.0.x, see code or fiddle http://jsfiddle.net/mattdlockyer/C5GBU/2/
$('body').on('click', function (e) {
$('[data-toggle="popover"]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
$(this).popover('hide');
}
});
});
This handles closing of popovers already open and not clicked on or their links have not been clicked.
Update: Bootstrap 3.3.6, see fiddle
Fixes issue where after closing, takes 2 clicks to re-open
$(document).on('click', function (e) {
$('[data-toggle="popover"],[data-original-title]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
(($(this).popover('hide').data('bs.popover')||{}).inState||{}).click = false // fix for BS 3.3.6
}
});
});
Update: Using the conditional of the previous improvement, this solution was achieved. Fix the problem of double click and ghost popover:
$(document).on("shown.bs.popover",'[data-toggle="popover"]', function(){
$(this).attr('someattr','1');
});
$(document).on("hidden.bs.popover",'[data-toggle="popover"]', function(){
$(this).attr('someattr','0');
});
$(document).on('click', function (e) {
$('[data-toggle="popover"],[data-original-title]').each(function () {
//the 'is' for buttons that trigger popups
//the 'has' for icons within a button that triggers a popup
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
if($(this).attr('someattr')=="1"){
$(this).popover("toggle");
}
}
});
});
Solution 2:
$('html').on('mouseup', function(e) {
if(!$(e.target).closest('.popover').length) {
$('.popover').each(function(){
$(this.previousSibling).popover('hide');
});
}
});
This closes all popovers if you click anywhere except on a popover
UPDATE for Bootstrap 4.1
$("html").on("mouseup", function (e) {
var l = $(e.target);
if (l[0].className.indexOf("popover") == -1) {
$(".popover").each(function () {
$(this).popover("hide");
});
}
});
Solution 3:
Most simple, most fail safe version, works with any bootstrap version.
Demo: http://jsfiddle.net/guya/24mmM/
Demo 2: Not dismissing when clicking inside the popover content http://jsfiddle.net/guya/fjZja/
Demo 3: Multiple popovers: http://jsfiddle.net/guya/6YCjW/
Simply calling this line will dismiss all popovers:
$('[data-original-title]').popover('hide');
Dismiss all popovers when clicking outside with this code:
$('html').on('click', function(e) {
if (typeof $(e.target).data('original-title') == 'undefined') {
$('[data-original-title]').popover('hide');
}
});
The snippet above attach a click event on the body. When the user click on a popover, it'll behave as normal. When the user click on something that is not a popover it'll close all popovers.
It'll also work with popovers that are initiated with Javascript, as opposed to some other examples that will not work. (see the demo)
If you don't want to dismiss when clicking inside the popover content, use this code (see link to 2nd demo):
$('html').on('click', function(e) {
if (typeof $(e.target).data('original-title') == 'undefined' && !$(e.target).parents().is('.popover.in')) {
$('[data-original-title]').popover('hide');
}
});