I have this function:
this.div.click( function(e) {
...
});
I would like to listen for double clicks outside this element. I know that we can use blur() for clicks outside an element. But I would like to handle only double click events. What's the best way to do this?
You can use the .dblclick() event to listen to the double-click at the body level, and then use it's target attribute and .contains() to see if the click occurred within the div.
Something like this:
// div to check if dbl click did _not_ originate from
var mydiv = jQuery("#mydiv").get(0);
// listen to body for double clicks
$("body").dblclick(function(e) {
// if click target does not fall within #mydiv
if (mydiv !== e.target && $.contains(mydiv, e.target) !== true) {
console.log("outside of mydiv");
}
});
Here is a jsbin demo.
There is another way to do this, by modifying e.originalEvent:
$( "#mydiv" ).dblclick(function(e) {
e.originalEvent.inside = true;
});
$( "body" ).dblclick(function(e) {
if( e.originalEvent.inside ) {
console.log('inside');
} else {
console.log('outside');
};
});
I have updated Johnatan's Bin. Think it should be faster.
Related
I have a listener which runs when I click on document.
document.addEventListener('click', print);
function print(element)
{
doSomething();
}
It creates div id=panel, where I print some information.
When I run the print function I would like to detect whether I clicked outside of the div#panel (The panel exists when I click second time).
I wish not to use the mouseout event listener because I think it is redundant to use listener for mouse movements when the event click is already fired.
How to detect when I clicked out of div#panel?
You can check the target of jQuery's click event, which element it was:
$(document).click(function(e) {
var target = $(e.target);
if( !target.is("#panel") && target.closest("#panel").length === 0 ) {
// click was not on or inside #panel
}
});
Your event handler gets passed an event object, not an element. Since you are listening for the click event, the event will be of type MouseEvent and that event object will have a target property which you can use to check if the target element matches your desired element.
function handler(event) {
if (event.target == document.getElementById("panel")) {
// Do stuff
}
}
document.addEventListener('click', handler);
Edit: I intentionally gave the vanilla JS answer since your own code fragments don't use jQuery. But jQuery wouldn't change anything as its event handling API is almost just a thin wrapper over JS.
I am just using event from the click. Here it is
var elem=document.getElementById("elem");
var rects=elem.getBoundingClientRect();//get the bounds of the element
document.addEventListener('click', print);
function print(e)
{
//check if click position is inside or outside target element
if(e.pageX<= rects.left +rects.width && e.pageX>= rects.left && e.pageY<= rects.top +rects.height && e.pageY>= rects.top){
console.log("Inside element");
}
else{
console.log("Outside element");
}
}
JS Bin link : https://jsbin.com/pepilehigo/edit?html,js,console,output
A different approach, using only javascript is:
function print(evt) {
if (!(evt.target.tagName == 'DIV' && evt.target.classList.contains('myDiv'))) {
var div = document.createElement('div');
div.classList.add('myDiv');
div.textContent="new div";
document.body.appendChild(div);
}
}
window.onload = function() {
document.addEventListener('click', print);
}
.myDiv {
border:1px solid green;
}
This code doesn't hide the box div which was supposed to be hidden when I press the Esc key.
function Boxup(elementN, event){
$("#"+elementN).css({
"display":"block",
"top":event.pageY+"px" ,
"left":event.pageX+"px"
})
}
function hideCurrentPopup(ele){
$(ele).parent().hide();
}
$(this).keyup(function(event) {
if (event.which == 27) {
disablePopup();
}
});
Am I missing something?
From your code I cannot exactly tell what's this referring to in this line:
$(this).keyup(function(event) {
cause it this refers to a "textarea" or "input" it will trigger the event if that element has focus, otherwise you're looking for keyup events registered by document
but here's what you can try.
function Boxup(elementN, event){
$("#"+elementN).css({
display : "block",
top : event.pageY , // px are not needed as they are default unit in jQ
left : event.pageX
})
}
function hideCurrentPopup(ele){ // note your function name and the argument!
$(ele).parent().hide(); // (do you need .parent()? I don't know
} // without seeing any HTML sample)
$(document).keyup(function(event) { // document is probably the selector you want
if (event.which == 27) {
hideCurrentPopup("#hereYourPopupID"); // try alike
}
});
P.S: Make sure that by using $(some Selector here).keyup(function(event) { you're not preventing in any case a keyup event to bubble up the DOM tree to reach the documentElement
but very simply, I'd like to prevent the touchmove event on the body element but leave it enabled for another element. I can disable fine... but I'm not sure how to re-enable it somewhere else!
I imagine that the below theoretically works because return true is the opposite of preventDefault, but it doesn't work for me. Might be 'cause $altNav element is in $bod?
JS:
$bod.bind('touchmove', function(event){
event.preventDefault();
});
$altNav.bind('touchmove', function(event){
return true;
});
I'm not sure what lib you're actually using, but I'll asume jQuery (I'll also post the same code in browser-native-js if you're using something other than jQ)
$bod.delegate('*', 'touchstart',function(e)
{
if ($(this) !== $altNav)
{
e.preventDefault();
//and /or
return false;
}
//current event target is $altNav, handle accordingly
});
That should take care of everything. The callback here deals with all touchmove events, and invokes the preventDefault method every time the event was triggered on an element other than $altNav.
In std browser-js, this code looks something like:
document.body.addEventListener('touchmove',function(e)
{
e = e || window.event;
var target = e.target || e.srcElement;
//in case $altNav is a class:
if (!target.className.match(/\baltNav\b/))
{
e.returnValue = false;
e.cancelBubble = true;
if (e.preventDefault)
{
e.preventDefault();
e.stopPropagation();
}
return false;//or return e, doesn't matter
}
//target is a reference to an $altNav element here, e is the event object, go mad
},false);
Now, if $altNav is an element with a particular id, just replace the target.className.match() thing with target.id === 'altNav' and so on...
Good luck, hope this helps
Use a custom CSS class and test for it in the document handler, eg:
<div>
This div and its parents cannot be scrolled.
<div class="touch-moveable">
This div and its children can.
</div>
</div>
then:
jQuery( document ).on( 'touchmove', function( ev )
{
if (!jQuery( ev.target ).parents().hasClass( 'touch-moveable' ))
{
ev.preventDefault();
}
});
http://tinyurl.com/mo6vwrq
you can add a argument,like this
$bod.bind('touchmove', function(event,enable){
if(enable){
event.preventDefault();
}
});
Here's a fiddle illustrating the problem. I am adding a jQuery one binding on the click of one element to the 'html' element. I am not expecting the 'one' event handler to fire until the next click, but it fires on the click that adds the binding. This seems to not be a problem if it is a more specific element that the 'one' event handler is added to, but it happens when I use 'html' or 'body' as the element, which is what I want to do.
This doesn't make sense to me, I'd think the first click would add the one for the next click and it wouldn't fire on the click on the link.
By the way, my actual problem could probably be solved in a better way, but I came across this and was curious why it didn't work as I expected.
Code:
html:
<div id='hello'>hello</div>
<a class="title" href="#">this example</a> is a test
js:
$(function() {
$('a.title').click(function() {
var htmlClickBind = function (e) {
console.log('clicked on html, e.target = ' + e.target);
console.log(e.target == '');
if (!$(e.target).is('a') ) {
console.log('cleared click event');
}
else {
$('html').one('click', htmlClickBind);
}
};
$('html').one('click', htmlClickBind);
});
});
The click event on the a.target element bubbles up to the html element, where your (just-added) handler sees it.
To prevent this, use event.stopPropgation in your a.target click handler (or return false, which does stopPropagation and preventDefault).
Updated code (see the comments): Live copy
$(function() {
// Accept the event arg ----v
$('a.title').click(function(e) {
// Stop propagation
e.stopPropagation();
var htmlClickBind = function (e) {
console.log('clicked on html, e.target = ' + e.target);
console.log(e.target == '');
if (!$(e.target).is('a') ) {
console.log('cleared click event');
}
else {
$('html').one('click', htmlClickBind);
}
};
$('html').one('click', htmlClickBind);
});
});
I have the following function to open an overlay menu:
$('.context-switch').click(function() {
$(".context-switch-menu").toggle();
});
To hide the menu, I would like the user to be able to click on any area outside ".context-switch-menu"
I am trying with :not() but with no success..
$('body').click(function(e) {
if ($(e.target).hasClass('context-switch')) {
return;
}
$(".context-switch-menu").hide();
});
$('.context-switch').click(function() {
$(".context-switch-menu").toggle();
return false;
});
The reason this can be difficult is because of event bubbling.
You can try something like this:
$('.context-switch').click(function(e) {
e.stopPropagation();
$(".context-switch-menu").toggle();
});
$(".context-switch-menu").click(function(e){
e.stopPropagation();
});
$("body").click(function(e){
$(".context-switch-menu").hide();
});
The e.stopPropagation() prevents the click event from bubbling to the body handlers. Without it, any click to .context-switch or .context-switch-menu would also trigger the body event handler, which you don't want, as it would nullify the effect of the .context-switch click half the time. (ie, if the state is hidden, and then you click to show, the event would bubble and trigger the body handler that would then hide the .context-switch-menu again.)
Without testing, would something like this work?:
$('.context-switch').click(function() {
$(".context-switch-menu").show();
});
$(document).click(function() {
$(".context-switch-menu").hide();
});
Instead of using document, 'html' or 'body' may work as well.
$(document).on('click', function(e) {
if (e.target.className !='context-switch-menu') {
$(".context-switch-menu").hide();
}
});
Just an idea here, based on what what others have suggested in the past:
$(document).click(function(e){
//this should give you the clicked element's id attribute
var elem = $(e.target).attr('classname');
if(elem !== 'context-switch-menu'){
$('.context-switch-menu').slideUp('slow');
//or however you want to hide it
}
});
try this, we don't want to call a function when you clicked on the element itself, and not when we click inside the element. That's why we need 2 checks.
You want to use e.target which is the element you clicked.
$("html").click(function(e){
if( !$(e.target).is(".context-switch-menu") &&
$(e.target).closest(".context-switch-menu").length == 0
)
{
alert("CLICKED OUTSIDE");
}
});
Live fiddle: http://jsfiddle.net/Xc25K/1/