click outside div to hide, is hiding when clicked inside - javascript

I'm trying to create a menu where when a div is clicked it opens another div with the contents. I wanted it close when the user clicked anywhere else. That part seems to work, however it also closes when the div itself is clicked.
The user should be able to click inside the div without it closing,
I was using answers from this question as a guide but they were using ordered lists instead of divs, is there an issue with e.target.class ?
Thanks for any help.
$('.trigger').click(function (e) {
e.stopPropagation();
$('.header-menu-container').hide();
$(this).next('.header-menu-container').slideDown();
});
$(document).click(function (e) {
if (e.target.class == 'header-menu-container' || e.target.class == 'header-menu-contents')
return;
$('.header-menu-container').slideUp();
});
Please see here: http://jsfiddle.net/75JaR/3/

Change class to className...
$(document).click(function (e) {
if (e.target.className == 'header-menu-container' || e.target.className == 'header-menu-contents') return;
$('.header-menu-container').slideUp();
});
updated jsfiddle...
Incidentally, if you add any further classes to the container and contents elements then the above code won't work. The following code would be more suitable as it will work no matter how many extra classes you add...
$(document).click(function (e) {
var $this = $(e.target);
if ($this.hasClass("header-menu-container")) return;
if ($this.hasClass("header-menu-contents")) return;
$('.header-menu-container').slideUp();
});

use this instead:
if ( $(e.target).is('.header-menu-container') || $(e.target).is('.header-menu-contents') )

stop the event bubbling up to the document when the div is clicked, then you don't have to do the class check.
http://jsfiddle.net/75JaR/7/
$('.trigger').click(function (e) {
e.stopPropagation();
$('.header-menu-container').hide();
$(this).next('.header-menu-container').click(function(e){
e.stopPropagation();
}).slideDown();
});
$(document).click(function (e) {
$('.header-menu-container').slideUp();
});

Make a click event on the div to stop hiding it once clicked on it.
$('.trigger').click(function (e) {
e.stopPropagation();
$('.header-menu-container').hide();
$(this).next('.header-menu-container').slideDown();
});
$(document).click(function (e) {
if (e.target.class == 'header-menu-container' || e.target.class == 'header-menu-contents') return;
$('.header-menu-container').slideUp();
$('.header-menu-container').click(function(){
return false;
});
});

Related

Close dropdown by clicking outside

I don't quite understand why my script does not working:
$(() => {
let dropdown = $('.passengers-main-dropdown'),
drop = dropdown.siblings('.dropdown-box');
dropdown.on('click', function(){
$(this).addClass('active');
drop.addClass('active');
});
$(document).on('click', function(e){
if(dropdown.is(e.target) || !drop.is(e.target) || drop.has(e.target).length === 0) {
drop.removeClass('active');
dropdown.removeClass('active');
}
});
});
The logic here is: when clicking on element with class .passengers-main-dropdown then dropdown becomes .active. And by clicking on document, algorithm checking for:
Dropdown not being a target of click
.passengers-main-dropdown is a target of click
Any dropdown's child elements are not a target of click
Am I doing wrong? Thanks.
I usually use closest():
$(document).on('click', function(e){
var $tgt = $(e.target);
if($tgt.closest('.passengers-main-dropdown').length
|| !$tgt.closest('.dropdown-box').length) {
drop.removeClass('active');
dropdown.removeClass('active');
}
});

Add/remove class on right click

I'm trying to add a class on right-click of an element and then remove it when anything else on the page is clicked.
I'm using jQuery.
My function is this so far:
$(".classElement").live('mousedown', function(e) {
if( (e.which == 3) ) {
$(".classElement").addClass("active");
}
e.preventDefault();
}).live('contextmenu', function(e){
e.preventDefault();
});
However, this adds the "active" class to all ".classElement" in the doc, rather than the individual one being clicked. I want to only add the class to the element being clicked.
Also, how can I remove the class when anything else is clicked?
You can removClass active on click of body element, but for this you have to stop event propagation when you are clicking on current element.
$(document).on('mousedown','.classElement', function(e) {
e.preventDefault();
if( (e.which == 3) ) {
$(this).addClass("active");
}
e.stopPropagation();
}).on('contextmenu','.classElement', function(e){
e.preventDefault();
});
$(document.body).click(function(){
$(".classElement").removeClass("active");
});
You can use $(this) to target current clicked element, so you can do:
$(this).addClass("active");
instead of:
$(".classElement").addClass("active");
Also, since .live() was removed since version 1.9, you should use .on() instead.
to target specific element:
$(this).addClass("active");
and to remove it when anything else is clicked, add this:
$(window).one("click", function(){
$(this).removeClass("active");
});
This adds a one time only click event listener to the window.
Use this code
$(".classElement").live('contextmenu', function(e){
e.preventDefault();
if( (e.which == 3) ) {
$(this).addClass("active");
}
});
and then remove class on document click
$(document).click(function(){
$(".classElement").removeClass("active");
});

How to close an open collapsed navbar when clicking outside of the navbar element in Bootstrap 3?

How can I close an open collapsed navbar on clicking outside of the navbar element? Currently, the only way to open or close it is by clicking on the navbar-toggle button.
See here for an example and code:
So far, I have tried the following which doesn't seem to work:
jQuery(document).click(function() {
});
jQuery('.navbar').click(function(event) {
jQuery(".navbar-collapse").collapse('hide');
event.stopPropagation();
});
Have a look that:
$(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();
}
});
});
Your fiddle works with that: http://jsfiddle.net/52VtD/5718/
Its a modified version of this answer, which lacks the animation and is also a tiny bit more complicated.
I know, invoking the click() isn't very elegant, but collapse('hide') did not work for me either, and i think the animation is a bit nicer than adding and removing the classes hardly.
The accepted answer doesn't appear to work correctly. It only needs to check if "navbar-collapse" has the "in" class. We can then fire the collapse method as expected by using our reference to the navbar.
$(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');
}
});
Using this works for me.
$(function() {
$(document).click(function (event) {
$('.navbar-collapse').collapse('hide');
});
});
The solution I decided to use was taken from the accepted answer here and from 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');
}
}
});
This hides an opened collapsed nav menu if the user clicks anywhere outside of the .navbar element. Of course clicking on .navbar-toggle still works to close the menu too.
Converted nozzleman's answer for 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();
}
}
);
});
Placed in the ngOnInit().
When the document is loaded, this code waits for click events. If the mobile menu dropdown is open (i.e. the collapsible part of the navbar has the "show" class) and the clicked object (target) is not the mobile menu button (i.e. does not have the "navbar-toggler" class), then we tell the mobile menu button it has been clicked, and the menu closes.
stopPropagation() is not always the best solution. Rather use something like:
jQuery(document.body).on('click', function(ev){
if(jQuery(ev.target).closest('.navbar-collapse').length) return; // Not return false
// Hide navbar
});
I think it's dangerous to assume that you never want to listen to any other event from the .navbar. Which is impossible if you use stopPropagation().
I had a scenario where I had plain text and I didn't want the panel to close if a user clicks on the plain text on accident. The other answers here will close the panel even if you click on the text of an item that isn't a link.
To fix this I added on to Paul Tarr's answer by wrapping the solution in a check to see whether or not the click occurred anywhere inside:
if ($(event.target).parents(".navbar-collapse").length < 1) { }
The full code would become:
$(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');
}
}
});
In this demo fiddle you can see that if you click on a non-link inside of the panel it won't collapse it.
For latest Bootstrap, this is the correct answer.
$(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');
}
});
It reads if .navbar-collapse has the word show in classes (which means menu is opened) and hides the navbar when you click/tap anywhere.
I've added a condition to #nozzleman's answer to check if the tap or click has been made on any element within the menu, and if that's the case, not to collapse it.
$(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();
}
});
});
The following code works for me and the advantage is that on small screens, it does not hide the .collapse when you click on its nav parent with .navbar .navbar-expand classes:
$(document).click(function (e) {
if($('.collapse').hasClass('show') && !$('nav').is(e.target) && $('nav').has(e.target).length === 0){
$('.navbar-toggler').click()
}
})
Vanilla Javascript.
Working on Bootstrap 5.2.
window.onload = function () {
document.addEventListener("click", function (event) {
// if the clicked element isn't child of the navbar, you must close it if is open
if (!event.target.closest("#navbar_id") && document.getElementById("navbarSupportedContent").classList.contains("show")) {
document.getElementById("hamburger_menu_button").click();
}
});
}
https://jsfiddle.net/j4tgpbxz/
You just need to add an id to the navbar element, and then check if the clicked element is a child of that same navbar and the content you want to hide (dropdown) is being shown.
For Bootstrap 4
Bootstrap 4 doesn't have an in class. This is 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')
So basically, unless you click the button or the menu, close the menu.
Note: Strange, on iOS clicking on text doesn't register a click event, nor a mouseup event. Clicking on an image does fire events though.
For Bootstrap 4:
$(document).click(function(event) {
$(event.target).closest(".navbar").length || $(".navbar-collapse.show").length && $(".navbar-collapse.show").collapse("hide")
});
$(document).click(function (event) {
if ($('.navbar-collapse').attr('aria-expanded') == "true") {
$('.navbar-collapse:visible').click();
}
});
$(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");
});
I had some problems with some answers here, and I would like to also be able to close the expanded menu on demand. So I did it with a simple function, and simulating the click.
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();
});
});
Using this method you can close it when clicked outside, but also you can call the closeMenu() at any time from any other function.
I know its quite awhile for the answer. But I think the answer here could helps.
Lets say the condition: if user want to close the navbar when click outside but not when user click any element inside of the navbar
use the event.target and target the element's closest classname whether its has the navbar class or not. If yes which means user is clicking element inside of the navbar and not to close the navbar.
$(function() {
$(document).click(function (event) {
var clickover = $(event.target);
var _opened = $(".navbar-collapse").hasClass("navbar-collapse collapse show");
if (_opened === true && clickover.closest('.navbar').length === 0) {
$(".navbar-collapse").collapse('hide');
}
});
});

in body click div hide, when i click on div also it hide

I want to show a div on link click and hide if click outside the link or div.
login
<div class="login-panel">
<input type="text" id="LoginForm_username" name="LoginForm[username]" class="field" value="username">
<input type="password" id="LoginForm_password" name="LoginForm[password]" class="field" value="password">
<input type="submit" value="Login" class="loginBtn">
</div>
initially div is hidden. and script is
$(document).ready(function() {
$("#login").click(function () {
$("div.login-panel").toggle();
});
$("body").click(function(e){
if(e.target.className == "login" || e.target.className == "login-panel") {
//alert("do't hide");
}
else {
$(".login-panel").hide();
}
});
});
when I click on link div shows and overlaps some other elements, and when I click outside the body it dies.
But the problem is when I click on input box to enter username login-panel div get hides.
why div hide?
any guidance will be appreciated.
http://jsfiddle.net/thirtydot/F4p2x/15/
$(document).ready(function() {
$("#login").click(function(e) {
$(".login-panel").toggle();
e.stopPropagation();
});
$(document).click(function(e) {
if (!$(e.target).is('.login-panel, .login-panel *')) {
$(".login-panel").hide();
}
});
});
You should do it like this:
http://jsfiddle.net/VWENB/1/
$("#login").click(function(e) {
$("div.login-panel").toggle();
e.stopPropagation();
});
$("body").click(function(e) {
if (e.target.className == "field") {
//alert("do't hide");
} else {
$(".login-panel").hide();
}
});​
When you are clicking on a sub-element, your condition (e.target.className) is not applied to your parent element (<div class="login-panel">). But you can use the closest function of jQuery (see here) in order to test if you are in your parent element :
if(e.target.className == "login" || $(e.target).closest(".login-panel").length === 1) {
...
}
PROBLEM is when i click on input box to enter username login-panel div
get hides. why div hide?
Because, you clicked the body too, when clicking in the div. Then both events are triggered. Check out event.stopPropagation() which you may use in the else part of body.onclick.
That because your input lies inside #login div, so if you click inside this div it will hide. So you can use jquery :not selector to specify those excluded elements
$(document).ready(function () {
$("#login,:not('#LoginForm_username'),:not('#LoginForm_password')").click(function () {
$("div.login-panel").toggle();
});
$("body").click(function (e) {
if (e.target.className == "login" || e.target.className == "login-panel") {
//alert("do't hide");
} else {
$(".login-panel").hide();
}
});
});​
DEMO
Here you go:
$(document).ready(function () {
$("#login").click(function () {
$("div.login-panel").toggle();
});
$("body").click(function (e) {
if (e.target.nodeName != "INPUT" && e.target.className!= "login" && e.target.className!= "login-panel") {
$(".login-panel").hide();
}
});
});​
You were using the wrong selector in your if to check if a click on the body wasn't targeting a input element.
Fiddle
Just find mouse when the click event occur,
<script type="text/javascript">
find_mouse = false;
$(document).ready(function()
{
$('.login-panel').hover(function(){
find_mouse=true; // if mouse on login-panel
}, function(){
find_mouse=false; // not on login panel
});
$("body").click(function(){
if(! find_mouse) // if not on login panel
$('.login-panel').hide();
});
});
</script>
As the other saying clicking input cause event triggering in the body so you should check if the sender is child of the login I think below code do the trick;
$("body").click(function (e) {
var $sender = $(e.target);
if ($sender.closest(".login-panel").length) {
return ;
}
$(".login-panel").hide();
});
Edit : update the condition with closest as it is correct function.
Begins with the current element, Travels up the DOM tree until it finds a match for the supplied selector. The returned jQuery object contains zero or one element for each element in the original set.

How can I close a Twitter Bootstrap popover with a click from anywhere (else) on the page?

I'm currently using popovers with Twitter Bootstrap, initiated like this:
$('.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!).
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?
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.
Below is a working JavaScript code that does this. It uses 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/
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 :-)
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();
});
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.
Plugin can be found here.
Usage example
<button rel="clickover" data-content="Show something here.
<button data-dismiss='clickover'
>Close Clickover</button>"
>Show clickover</button>
javascript:
// load click overs using 'rel' attribute
$('[rel="clickover"]').clickover();
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').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!
read "Dismiss on next click"
here 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...
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>
All of the existing answers are fairly weak, as they rely on capturing all document events then finding active popovers, or modifying the call to .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 esc is pressed, only binding event listeners when popovers are shown:
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);
}
https://github.com/lecar-red/bootstrapx-clickover
It's an extension of twitter bootstrap popover and will solve the problem very simply.
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?
Anyways I hope this helps someone!
I give all my popovers anchors the class activate_popover. I activate them all at once onload
$('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
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
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();
});
I would set the focus to the newly created pop-over and remove it on blur. That way it's not needed to check which element of the DOM has been clicked and the pop-over can be clicked, and selected too: it will not lose its focus and will not disappear.
The code:
$('.popup-marker').popover({
html: true,
trigger: 'manual'
}).click(function(e) {
$(this).popover('toggle');
// set the focus on the popover itself
jQuery(".popover").attr("tabindex",-1).focus();
e.preventDefault();
});
// live event, will delete the popover by clicking any part of the page
$('body').on('blur','.popover',function(){
$('.popup-marker').popover('hide');
});
Here is the solution which worked very fine for me, if it can help :
/**
* Add the equals method to the jquery objects
*/
$.fn.equals = function(compareTo) {
if (!compareTo || this.length !== compareTo.length) {
return false;
}
for (var i = 0; i < this.length; ++i) {
if (this[i] !== compareTo[i]) {
return false;
}
}
return true;
};
/**
* Activate popover message for all concerned fields
*/
var popoverOpened = null;
$(function() {
$('span.btn').popover();
$('span.btn').unbind("click");
$('span.btn').bind("click", function(e) {
e.stopPropagation();
if($(this).equals(popoverOpened)) return;
if(popoverOpened !== null) {
popoverOpened.popover("hide");
}
$(this).popover('show');
popoverOpened = $(this);
e.preventDefault();
});
$(document).click(function(e) {
if(popoverOpened !== null) {
popoverOpened.popover("hide");
popoverOpened = null;
}
});
});
Here's my solution, for what it's worth:
// Listen for clicks or touches on the page
$("html").on("click.popover.data-api touchend.popover.data-api", function(e) {
// Loop through each popover on the page
$("[data-toggle=popover]").each(function() {
// Hide this popover if it's visible and if the user clicked outside of it
if ($(this).next('div.popover:visible').length && $(".popover").has(e.target).length === 0) {
$(this).popover("hide");
}
});
});
I had some problem to get it working on bootstrap 2.3.2.
But i sloved it this way:
$(function () {
$(document).mouseup(function (e) {
if(($('.popover').length > 0) && !$(e.target).hasClass('popInfo')) {
$('.popover').each(function(){
$(this).prev('.popInfo').popover('hide');
});
}
});
$('.popInfo').popover({
trigger: 'click',
html: true
});
});
tweaked #David Wolever solution slightly:
function closePopoversOnDocumentEvents() {
var visiblePopovers = [];
var $body = $("body");
function hideVisiblePopovers() {
/* this was giving problems and had a bit of overhead
$.each(visiblePopovers, function() {
$(this).popover("hide");
});
*/
while (visiblePopovers.length !== 0) {
$(visiblePopovers.pop()).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);
}
This question was also asked here and my answer provides not only a way to understand jQuery DOM traversal methods but 2 options for handling the closing of popovers by clicking outside.
Open multiple popovers at once or one popover at a time.
Plus these small code snippets can handle the closing of buttons containing icons!
https://stackoverflow.com/a/14857326/1060487
This one works like a charm and I use it.
It will open the popover when you click and if you click again it will close, also if you click outside of the popover the popover will be closed.
This also works with more than 1 popover.
function hideAllPopovers(){
$('[data-toggle="popover"]').each(function() {
if ($(this).data("showing") == "true"){
$(this).data("showing", "false");
$(this).popover('hide');
}
});
}
$('[data-toggle="popover"]').each(function() {
$(this).popover({
html: true,
trigger: 'manual'
}).click(function(e) {
if ($(this).data("showing") != "true"){
hideAllPopovers();
$(this).data("showing", "true");
$(this).popover('show');
}else{
hideAllPopovers();
}
e.stopPropagation();
});
});
$(document).click(function(e) {
hideAllPopovers();
});
Another solution, it covered the problem I had with clicking descendants of the popover:
$(document).mouseup(function (e) {
// The target is not popover or popover descendants
if (!$(".popover").is(e.target) && 0 === $(".popover").has(e.target).length) {
$("[data-toggle=popover]").popover('hide');
}
});
I do it as below
$("a[rel=popover]").click(function(event){
if(event.which == 1)
{
$thisPopOver = $(this);
$thisPopOver.popover('toggle');
$thisPopOver.parent("li").click(function(event){
event.stopPropagation();
$("html").click(function(){
$thisPopOver.popover('hide');
});
});
}
});
Hope this helps!
If you're trying to use twitter bootstrap popover with pjax, this worked for me:
App.Utils.Popover = {
enableAll: function() {
$('.pk-popover').popover(
{
trigger: 'click',
html : true,
container: 'body',
placement: 'right',
}
);
},
bindDocumentClickEvent: function(documentObj) {
$(documentObj).click(function(event) {
if( !$(event.target).hasClass('pk-popover') ) {
$('.pk-popover').popover('hide');
}
});
}
};
$(document).on('ready pjax:end', function() {
App.Utils.Popover.enableAll();
App.Utils.Popover.bindDocumentClickEvent(this);
});
#RayOnAir, I have same issue with previous solutions. I come close to #RayOnAir solution too. One thing that improved is close already opened popover when click on other popover marker. So my code is:
var clicked_popover_marker = null;
var popover_marker = '#pricing i';
$(popover_marker).popover({
html: true,
trigger: 'manual'
}).click(function (e) {
clicked_popover_marker = this;
$(popover_marker).not(clicked_popover_marker).popover('hide');
$(clicked_popover_marker).popover('toggle');
});
$(document).click(function (e) {
if (e.target != clicked_popover_marker) {
$(popover_marker).popover('hide');
clicked_popover_marker = null;
}
});
I found this to be a modified solution of pbaron's suggestion above, because his solution activated the popover('hide') on all elements with class 'popup-marker'. However, when you're using popover() for html content instead of the data-content, as I'm doing below, any clicks inside that html popup actually activate the popover('hide'), which promptly closes the window. This method below iterates through each .popup-marker element and discovers first if the parent is related to the .popup-marker's id that was clicked, and if so then does not hide it. All other divs are hidden...
$(function(){
$('html').click(function(e) {
// this is my departure from pbaron's code above
// $('.popup-marker').popover('hide');
$('.popup-marker').each(function() {
if ($(e.target).parents().children('.popup-marker').attr('id')!=($(this).attr('id'))) {
$(this).popover('hide');
}
});
});
$('.popup-marker').popover({
html: true,
// this is where I'm setting the html for content from a nearby hidden div with id="html-"+clicked_div_id
content: function() { return $('#html-'+$(this).attr('id')).html(); },
trigger: 'manual'
}).click(function(e) {
$(this).popover('toggle');
e.stopPropagation();
});
});
I came up with this:
My scenario included more popovers on the same page, and hiding them just made them invisible and because of that, clicking on items behind the popover was not possible.
The idea is to mark the specific popover-link as 'active' and then you can simply 'toggle' the active popover. Doing so will close the popover completely.
$('.popover-link').popover({ html : true, container: 'body' })
$('.popover-link').popover().on 'shown.bs.popover', ->
$(this).addClass('toggled')
$('.popover-link').popover().on 'hidden.bs.popover', ->
$(this).removeClass('toggled')
$("body").on "click", (e) ->
$openedPopoverLink = $(".popover-link.toggled")
if $openedPopoverLink.has(e.target).length == 0
$openedPopoverLink.popover "toggle"
$openedPopoverLink.removeClass "toggled"
I was trying to make a simple solution for a simple issue. Above posts are good but so complicated for a simple issue. So i made a simple thing. Just added a close button. Its perfect for me.
$(".popover-link").click(function(){
$(".mypopover").hide();
$(this).parent().find(".mypopover").show();
})
$('.close').click(function(){
$(this).parents('.mypopover').css('display','none');
});
<div class="popover-content">
<i class="fa fa-times close"></i>
<h3 class="popover-title">Title here</h3>
your other content here
</div>
.popover-content {
position:relative;
}
.close {
position:absolute;
color:#CCC;
right:5px;
top:5px;
cursor:pointer;
}
I like this, simple yet effective..
var openPopup;
$('[data-toggle="popover"]').on('click',function(){
if(openPopup){
$(openPopup).popover('hide');
}
openPopup=this;
});
Add btn-popover class to your popover button/link that opens the popover. This code will close the popovers when clicking outside of it.
$('body').on('click', function(event) {
if (!$(event.target).closest('.btn-popover, .popover').length) {
$('.popover').popover('hide');
}
});
An even easier solution, just iterate through all popovers and hide if not this.
$(document).on('click', '.popup-marker', function() {
$(this).popover('toggle')
})
$(document).bind('click touchstart', function(e) {
var target = $(e.target)[0];
$('.popup-marker').each(function () {
// hide any open popovers except for the one we've clicked
if (!$(this).is(target)) {
$(this).popover('hide');
}
});
});
$('.popForm').popover();
$('.conteneurPopForm').on("click",".fermePopover",function(){
$(".popForm").trigger("click");
});
To be clear, just trigger the popover
This should work in Bootstrap 4:
$("#my-popover-trigger").popover({
template: '<div class="popover my-popover-content" role="tooltip"><div class="arrow"></div><div class="popover-body"></div></div>',
trigger: "manual"
})
$(document).click(function(e) {
if ($(e.target).closest($("#my-popover-trigger")).length > 0) {
$("#my-popover-trigger").popover("toggle")
} else if (!$(e.target).closest($(".my-popover-content")).length > 0) {
$("#my-popover-trigger").popover("hide")
}
})
Explanation:
The first section inits the popover as per the docs: https://getbootstrap.com/docs/4.0/components/popovers/
The first "if" in the second section checks whether the clicked element is a descendant of #my-popover-trigger. If that is true, it toggles the popover (it handles the click on the trigger).
The second "if" in the second section checks whether the clicked element is a descendant of the popover content class which was defined in the init template. If it is not this means that the click was not inside the popover content, and the popover can be hidden.
Try data-trigger="focus" instead of "click".
This solved the problem for me.

Categories

Resources