Hide context menu on outside click - javascript

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.

Related

Using Parents() on an element which gets reinserted on click

I have created a dropdown functionality using Jquery with one event listener that allows me to close the dropdown when clicked anywhere outside the dropdown container and another event listener which handles the submenu items.
By design the dropdown should stay open even if the submenu items are clicked and should only close if the toggle button is clicked or the user clicks outside the dropdown container.
The problem
Lets say that general.js has the click event listener as follows
$('document').on('click.namespace',function(e){ // do stuff });
Now anotherscript.js has an event listener which handles the actual sub menu clicks
$('#clickbutton').on('click', function(e){
// Remove all html from inside the .dropdown container
// Recreate the html using another js function
$('.container').html(recreatedhtml);
});
The problem occurs when I try to identify who the parent of the submenu button click target is, because I want to know if the click was inside the container or outside.
Since a click on #clickbutton removes html from the container and reinserts it I believe this causes problems for the parents() function therefore the parents('.dropdown') function returns false even though the sub menu item is a descendent of the dropdown class.
Check the target of the event
$(document).on('click.namespace',function(e){
if(!$(e.target).closest(dropdownContainerSelector).length){
// click is not in dropdown container
}
});
Note that document is not a string, it is a global object within window

listening in to keypresses and "click outside" for popovers/particular classes

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.

How does the click() function in jquery work when working with multiple stacked divs?

How does the click() function in jquery work when working with multiple stacked divs?
I have one main div and another div inside of the main div, when i click on the div inside, its also considered a click on the main div, but i dont want that, i want it to only consider a click on the inside div.
<div id="main"><div id="inner"></div></div>
Lets say the main div is a lot larger and the innner div is just a small square, when i click on the inner div(small square) I dont want it to trigger anyting as if i were to click on the main div. How do I maneuver this? Thanks again!
Events bubble up from the one that was clicked, through all its ancestors. Any ancestor that handles that event will have its handler fired.
What you need to do is to call event.stopPropagation() in order to prevent the event from bubbling up to its ancestor elements.
$('#inner').click(function(evt) {
evt.stopPropagation();
// your code
});
http://api.jquery.com/event.stopPropagation/
Another alternative is to return false; at the end of your handler.
$('#inner').click(function(evt) {
// your code
return false;
});
You can test it out here: http://jsfiddle.net/ZpeYr/
$('#inner').click(function() {
alert('clicked inner div'); // do something
});
you can call your inner div using using the css id.

The best way to do :not in jQuery?

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.

Is it possible to have jQuery.click trigger on the top element only?

I'm trying to make a site where the user can click on any element to edit it's CSS. I use the following to add the click function to all <li>, <div> and <ul>.
$('li,div,ul').click(function () {
alert(this.id);
});
The problem is if I click on a <li> element, then I get the alert for that and any element underneath it. (all the containers).
Is it possible to have only the top element trigger when clicked?
You want to stop event propagation, you do this in jQuery by calling the stopPropagation method on the event object.
$('li,div,ul').click(function (e) {
e.stopPropagation();
alert(this.id);
});
I believe you'd want to use stopPropagation(); inside the click function.
It sounds to me like you're looking for .stopPropagation(). Calling stopPropagation will prevent the event from "bubbling" up to parent containers.

Categories