I have a menu in jQuery when you click on a link it opens up, but I want it so when you click somewhere else, anywhere else that is not the menu, it becomes hidden.
At the moment I'm binding a click event to
$(':not(#the_menu)')
But this seems like I'm binding a click event to the entire minus the menu, is there a more efficient way of doing something like this?
The best way to do this is with bubbling capture, like this:
$(document).click(function() {
//close menu
})
$("#the_menu").click(function(e) {
e.stopPropagation();
});
How this works is every click bubbles (unless you stop it, usually by return false; or event.stopPopagation()), so whatever you click bubbles all the way up to DOM...if a click does that, we close the menu. If it came from inside the menu, we stop the bubble...so the click doesn't bubble up, triggering a close. This approach uses only 2 event handlers instead of 1 on everything but the menu, so very lightweight :)
Attach event to document's body ($(body)). Also attach another event to #the_menu that's block event propagation:
$(document.body).click(function() {
//close menu if opened
});
$("#the_menu").click(function(e) {
//code heere
e.stopPropagation();
});
How about binding the menu display to hovering over the element in which it is contained?
$("#parentId").hover(
function() { //!! on hovering in
$("#targetId").attr("display","block") ;
} ,
function() { //!! on hovering out
$("#targetId").attr("display","none") ;
}
) ;
If it fits your goal, this seems easier to maintain.
Related
I have a context menu that appears when you right click inside the <div>, and it only goes away if the user click left click inside the <div> again.
How do i hide it when a user click anywhere on the page?
my fiddle
change these two functions to the following:
_onPageClick: function(e) {
e.stopPropagation()
if (this.refs.contextMenu.getDOMNode() !== e.target){
this.contextMenu.setState({contextMenuLocation: ''});
}
},
componentDidMount: function(){
this.contextMenu = this.refs.contextMenu;
document.addEventListener('click', this._onPageClick)
},
all we have to do is to move _onPageClick from the wrapper div to a listener on the document. the above code will close the menu if the user clicks anywhere that is not inside the context menu. if you want it to close if the user clicks the context menu as well, then change _onPageClick to:
_onPageClick: function(e) {
e.stopPropagation()
this.contextMenu.setState({contextMenuLocation: ''});
}
(also, the wrapper div should no longer have the onClick handler)
http://jsfiddle.net/yikevinqu/eeu9unhm/1/
Check out Ben Alman's clickoutside jQuery plugin. Even if you are not using jQuery, you can review his mechanism for catching these click events as they bubble up.
http://benalman.com/projects/jquery-outside-events-plugin/
All click events get bubbled up through the DOM, so if you click an inner element, if you don't event.stopPropagation(), it will bubble up to the parent element. So just catch the click on the parent element (can even be document to hide your context menu).
Check out my fiddle for a pure JS example: http://jsfiddle.net/jsc8zLaj/
There's actually an existing React mixin on npm you can use for this:
https://github.com/Pomax/react-onclickoutside
Since mixins have fallen out of favour now, you may want to implement it as a wrapper component instead, but this is an excellent starting point.
I am implementing popovers, since the existing libraries are not flexible enough. I want to set any div with a class .popover and it shows the behaviors:
destroy on escape key
destroy when clicks outside borders
Both are events, and both need to apply on elements classed as .popover. To destroy popovers on escape:
$(document).keyup(function(e) {
if (e.keyCode == 27) {
popovers = $(".popover");
//destroy popovers
}
});
But I am stuck with how to listen in to mouse clicks globally and determining if they happened outside of a .popover.
SO answers mention having a global click listener that destroys all .popovers and adding a click listener to each popover that halts event propagation to the global listener.
But I want to define it only once globally, not once for every single popover I make. How do I do that?
$('body').click(function(e) {
if(!$(e.target).hasClass("popover")) {
//if element does not have a ".popover" class => it's outside
$(".popover").remove();
}
});
where e.target is the element you clicked on
You can create a div covering the whole page with z-index -1.
On popover you can bring it to front
Register popover closing onclick event on that div
On popover close, bring it back behind all elements.
I have a button that when clicked will popup a menu to the right of the button. This menu is a rather large UL of list items. The page that this menu is on contains lots of other elements.
Once the menu pops up, a user can click an option on the menu and the menu will disappear (menu.hide()).
However, it feels wierd not being able to get rid of the menu any other way. I like the idea of "if the user clicks on anything but the menu, the menu will hide." But i hate doing a "clickoutside" event that binds events to everything but the menu.
Another option is "mouseout" but "mouseout" always gets fired too early, because the mouse has to travel across the screen to get to the menu.
Any ideas on what event I can bind to the menu, so the user can get rid of it naturally, and at will? (not just when he clicks an option)
You can bind one event to the body when the menu is open. Use the click event to determine if the click occurred outside of the menu. If outside of the menu, hide the menu and remove the bind.
// binding function
closeMe = function(e) {
var $target = $(e.target);
// click is not inside the menu
if(!$target.hasClass('menu') && $target.parents('.menu').length !== 1) {
// hide menu
menu.hide();
// unbind events
$('body').unbind('mousedown.menuhide', closeMe);
}
};
// show menu
menu.show(function() {
// bind menu hide event
$('body').bind('mousedown.menuhide', closeMe);
});
Very easy, just use something like this
$('html').click(function() {
menu.close();
});
$('#menu').click(function(e){
e.stopPropagation();
// do stuff
// maybe some nice animation or w/e
menu.close();
});
I implemented this to my site from an earlier question but for some reason on Firefox and IE the drop-down box scrolls up by itself. I can't figure out why!
Just click News Feed and as the box drops down, it automatically drops up. It's supposed to drop down and if I click on newfeed again or outside, it's supposed to drop up. But it doesn't do that, it just springs back up.
I am using the JavaScript. What is going on here?
$('#bottom').click(function() {
$('#content').slideDown();
});
$(document).click(function(e) {
if (e.target.id !='bottom') {
$('#content').slideUp();
}
});
Change your #bottom event handler a bit to prevent the bubbling of the click event all the way up to the document:
//it is important to declare the `event` variable as a parameter of this anonymous function so it can be accessed inside the function
$('#bottom').click(function(event) {
event.stopPropagation();
$('#content').slideDown();
});
What's happening with your code is that the event handler for the #bottom element is being triggered, then after that the event handler for clicking on the document fires since the click event bubbles up the DOM. event.stopPropagation() will stop the event from bubbling.
Docs for event.stopPropagation(): http://api.jquery.com/event.stoppropagation/
I have a 'li' that pops down when I click on a 'link' via jquery's 'click'.
Does anyone know of a clean way to do something along the lines of 'offclick'? As in, when I click off of the element, it would hide the pop down?
Thanks!
Matt
You would want to assign a click listener to the window and also assign the click listener to your link. Inside the link click listener, you'll want to stop the event propagation so it doesn't travel up the DOM tree and fire your window's click listener.
Something like this should do the trick:
$(window).click(function(){
$('li#my_li').slideUp();
});
$('a#my_link').click(function(event){
try
{
event.stopPropagation();
}
catch(err)
{
// IE does it this way
window.event.cancelBubble=true;
}
$('li#my_li').slideDown();
});
I guess you could look at blur, which is called when the element looses focus:
ref: http://api.jquery.com/blur/
You can use blur or focusout depending on your needs