Click everywhere but here event
EDIT: There were a couple of problems in this old, old answer.
*Also: Marking Community Wiki (no points for me) because errors
N calls for N uses of the directive. This probably isn't desirable for uses within the same scope with matching expressions.
NOTHING WAS TEARING DOWN THE EVENT HANDLERS!!!! BAD! BAD! BAD!
Updated answer
Here's a new plunker with those issues fixed ... there are likely other things that individual application developers will run into. This is just an example of how to handle this problem.app.factory('clickAnywhereButHereService', function($document){
var tracker = [];
return function($scope, expr) {
var i, t, len;
for(i = 0, len = tracker.length; i < len; i++) {
t = tracker[i];
if(t.expr === expr && t.scope === $scope) {
return t;
}
}
var handler = function() {
$scope.$apply(expr);
};
$document.on('click', handler);
// IMPORTANT! Tear down this event handler when the scope is destroyed.
$scope.$on('$destroy', function(){
$document.off('click', handler);
});
t = { scope: $scope, expr: expr };
tracker.push(t);
return t;
};
});
app.directive('clickAnywhereButHere', function($document, clickAnywhereButHereService){
return {
restrict: 'A',
link: function(scope, elem, attr, ctrl) {
var handler = function(e) {
e.stopPropagation();
};
elem.on('click', handler);
scope.$on('$destroy', function(){
elem.off('click', handler);
});
clickAnywhereButHereService(scope, attr.clickAnywhereButHere);
}
};
});
Original answer (with fixes for teardown of event handlers)
You were close with the one answer you've found, but I've put together a plunk for you to show you what it was missing.app.directive('clickAnywhereButHere', function($document){
return {
restrict: 'A',
link: function(scope, elem, attr, ctrl) {
var elemClickHandler = function(e) {
e.stopPropagation();
};
var docClickHandler = function() {
scope.$apply(attr.clickAnywhereButHere);
};
elem.on('click', elemClickHandler);
$document.on('click', docClickHandler);
// teardown the event handlers when the scope is destroyed.
scope.$on('$destroy', function() {
elem.off('click', elemClickHandler);
$document.off('click', docClickHandler);
});
}
}
})
HTML<a click-anywhere-but-here="clickedSomewhereElse()"
ng-click="clickedHere()">Don't Click Me!</a>
JQuery: click everywhere but some element
$(document).click(function(e) {
if ( $(e.target).closest('#menu').length === 0 ) {
// cancel highlighting
}
});
An alternative solution would be to call
stopPropagation()
at the end of the #menu click handler and element click handlers. That way, if a click event bubbles to the document object, you know that neither the menu nor the elements were clicked and you can safely cancel the highlighting: $('#menu').click(function(e) {
// do stuff
e.stopPropagation();
});
$('.element').click(function(e) {
//do stuff
e.stopPropagation();
});
$(document).click(function() {
// cancel highlighting
});
Event on a click everywhere on the page outside of the specific div
Attach a click event to the document to hide the div:
$(document).click(function(e) {
$('#somediv').hide();
});
Attach a click event to the div to stop clicks on it from propagating to the document:$('#somediv').click(function(e) {
e.stopPropagation();
});
How do I handle a click anywhere in the page, even when a certain element stops the propagation?
Events in modern DOM implementations have two phases, capturing and bubbling. The capturing phase is the first phase, flowing from the defaultView
of the document to the event target, followed by the bubbling phase, flowing from the event target back to the defaultView
. For more information, see http://www.w3.org/TR/DOM-Level-3-Events/#event-flow.
To handle the capturing phase of an event, you need to set the third argument for addEventListener
to true
:
document.body.addEventListener('click', fn, true);
Sadly, as Wesley mentioned, the capturing phase of an event cannot be handled reliably, or at all, in older browsers.One possible solution is to handle the mouseup
event instead, since event order for clicks is:
- mousedown
- mouseup
- click
mouseup
event, then this is one way (and, arguably, a better way) to go. Another thing to note is that many, if not most (if not all), UI menus disappear on mouse down. JQuery : Click Everywhere But Some Element?
Since you mentioned you have event.stopPropagation()
at different sections of the page on click event so document.click
will not work to hide the textbox.
Why don't you use document.mousedown
? It will work fine.
$(document).mousedown(function(){
$('textboxSelector').hide();
});
Make sure you stop the mousedown
event propagation from textbox
and its containing div
. jQuery click anywhere in the page except on 1 div
You can apply click
on body
of document and cancel click
processing if the click
event is generated by div with id menu_content
, This will bind event to single element and saving binding of click
with every element except menu_content
$('body').click(function(evt){
if(evt.target.id == "menu_content")
return;
//For descendants of menu_content being clicked, remove this check if you do not want to put constraint on descendants.
if($(evt.target).closest('#menu_content').length)
return;
//Do processing of click event here for every element except with id menu_content
});
Angular.js closing with click anywhere but on the element
The way I've tackled things like this before is using inheritedData
to communicate to the click handler whether it's in or out of the thing:
In the custom directive for the thing, add a data variable to the element, using jqLite data, say
element.data('myThing',true)
. If you want to distinguish between multiple instances of the the thing, you might need to use some uniquely generated key.In the same custom directive, in a click event handler on document.body, you can check
angular.element(event.target).inheritedData('myThing')
app.directive('thing', function($document,$window) {
return {
restrict: 'E',
template: '<div><span>Inner thing</span></div>',
replace: true,
link: function(scope,element) {
element.data('thing',true);
angular.element($document[0].body).on('click',function(e) {
var inThing = angular.element(e.target).inheritedData('thing');
if (inThing) {
$window.alert('in');
} else {
$window.alert('out');
}
})
}
}
});
and can be seen in this Plunker http://plnkr.co/edit/bRDLcLoesM7Z0BIxKxYu?p=preview How do I hide an element on a click event anywhere outside of the element?
If I understand, you want to hide a div when you click anywhere but the div, and if you do click while over the div, then it should NOT close. You can do that with this code:
$(document).click(function() {
alert("me");
});
$(".myDiv").click(function(e) {
e.stopPropagation(); // This is the preferred method.
return false; // This should not be used unless you do not want
// any click events registering inside the div
});
This binds the click to the entire page, but if you click on the div in question, it will cancel the click event. Javascript: Click anywhere in body except the one element inside it
You need to stopPropagation
to the outer element.
Here's a simple illustration: http://jsfiddle.net/5mhqrhwk/3/
var body = document.getElementById('wrapper');
var except = document.getElementById('except');
body.addEventListener("click", function () {
alert("wrapper");
}, false);
except.addEventListener("click", function (ev) {
alert("except");
ev.stopPropagation(); //this is important! If removed, you'll get both alerts
}, false);
HTML:<div id="wrapper">
<center>
<div id="except"></div>
</center>
</div>
Related Topics
Node.Js Piping the Same Readable Stream into Multiple (Writable) Targets
Bootstrap: Open Another Modal in Modal
How to Validate Google Recaptcha V2 Using JavaScript/Jquery
Why Firefox Says That Window.Event Is Undefined? (Call Function with Added Event Listener)
Using Filesystem in Node.Js with Async/Await
What Is the JavaScript Mime Type for the Type Attribute of a Script Tag
Return Index of Greatest Value in an Array
JavaScript Array Concat Not Working. Why
How to Send Images to Node Js with Axios
How to Export Socket.Io into Other Modules in Nodejs
How to Change the Pop-Up Position of the Jquery Datepicker Control
Splicing a JavaScript Array from Within the Callback Passed to Foreach
Get the Current Year in JavaScript
What's the Purpose of Starting Semi Colon at Beginning of JavaScript
Arrow VS Classic Method in Es6 Class
Different Result for Yyyy-Mm-Dd and Yyyy/Mm/Dd in JavaScript When Passed to "New Date"