JQuery: Click anywhere other than #element - javascript

Nothing in the recommended questions covers it. I'm trying to initiate an event if a click occurs anywhere in the document other than in one of two specific divs. This is what I'm doing:
$('html:not(#optionsDropdown):not(#settingsButton)').click(function() {
if ($('#settingsCogCheck').val() === '1') {
alert('click');
}
});
It isn't working, though. Any clue as to why?
Thanks!

You can't add a listener to "everything except x", but you can listen on document, and check the element inside the click handler:
$(document).click(function() {
var id = $(this).id;
if (id != 'optionsDropdown' && id != 'settingsButton') {
if ($('#settingsCogCheck').val() === '1') {
alert('click');
}
}
});

Related

Applying a function to all buttons?

Im working on a quick script to apply an alert and redirect message to all anchors and buttons on a page. So far, I have this working for all anchors:
document.querySelector('body')
.addEventListener('click', function (event) {
if
(event.target.tagName === 'A' || event.target.tagName === 'button') {
event.preventDefault();
alert("test");
window.open('http://www.test.com', '_self');
}
});
When i try to apply the same idea to all buttons (see after the || in the script), it does not apply. Am I missing something?
event.target.tagName results are capitalized.
A BUTTON TEXTAREA etc.

JavaScript Event Delegation - Behavior

I'm trying to create web-page, and to improve performance, I decide to use event delegation, instead of direct binding, but I came across with strange behavior of event delegation or I missed something...
Here is structure of my HTML
<div>
<section class="myClass" data-link="section 1">
<h1>Heading 1</h1>
<p>Some text....</p>
</section>
</div>
I want to entire section was clickable, but while clicking h1 or p element in section event.target on that moment is h1 or p and not section, so expression in if statement fails...
function delegate(ele) {
ele.parentNode.addEventListener("click", function (e) {
if (e.target.nodeName.toLowerCase() === "section" && e.target.classList.contains("myClass")) {
console.log("delegate " + e.target.getAttribute("data-link"));
}
}, false);
}
I already have solution with direct binding, but it would be good is achieved in the same result with event delegation.
Here is jsFiddle
function direct(ele) {
[].forEach.call(ele, function (value, index, array) {
value.addEventListener("click", function(e) {
console.log("direct " + value.getAttribute("data-link"));
}, false);
});
}
Thanks in advance!
Once you handled the click, you can walk the visual tree, starting from the target, to find the information you need.
You might seek by type (node name), by tag, ... for the sake of the example, i just seek on element up to get a 'data-link' attribute if i don't find one on the target, but you have many choices here.
Edit : another idea is to use event.currentTarget, to get the element on which you hooked the event.
The updated fiddle will print :
delegate call on h1 or p of section 1
when you click on h1 or p1
and it will print :
delegate section 1
when you click on the whole section.
http://jsfiddle.net/KMJnA/4/
function delegate(ele) {
ele.parentNode.addEventListener("click", delegateHandler, false);
}
function delegateHandler (e) {
var target = e.target;
var attribute = target.getAttribute("data-link");
// if target has no attribute
// seek it on its parent
if (!attribute) {
attribute = target.parentNode.getAttribute("data-link");
}
if ( target.classList.contains("myClass") ) {
console.log("delegate " + attribute);
}
else console.log('delegate call on h1 or p of ' + attribute);
}
Rq : i didn't get why you hook the event on the parent of the element, might be simpler not to do it. :-)
I found the solution with CSS pointer-events
jsFiddle with CSS
.myClass * {
pointer-events: none;
}
or with JavaScript
jsFiddle with JavaScript
(function () {
"use strict";
var ele = document.querySelector(".myClass").parentNode;
delegate(ele);
function delegate(ele) {
ele.addEventListener("click", function (e) {
var target = e.target;
while (!(target.nodeName.toLowerCase() === "section" && target.classList.contains("myClass"))) {
target = target.parentNode;
if (target === ele) {
break;
}
}
if (target.nodeName.toLowerCase() === "section" && target.classList.contains("myClass")) {
console.log("delegate " + target.getAttribute("data-link"));
}
});
}
}());
Add the event listener to ele instead of ele.parentNode, and use this instead of e.target.
Demo
function delegate(ele) {
ele.addEventListener("click", function (e) {
if (this.nodeName.toLowerCase() === "section" && this.classList.contains("myClass")) {
console.log("delegate " + this.getAttribute("data-link"));
}
}, false);
}
Be aware that e.target is the element the event was dispatched on. But in your case you don't want that, you want the element which has the event handler, so use this (or ele).

jQuery separate dblclick events inside and outside of a div element

I'm developing a local site for content creation, and I'd like to use javascript's double click functionality.
I'd like to rotate through full screen background images when the user double clicks outside of the divs with names/ids bigwrapper or bigwrapper2. When the user clicks #bigwrapper or #bigwrapper2, I'd like it to .toggle(); each one to hide/show one or the other.
Here's my updated code (thanks lordvlad):
$(function() {
$( "#bigwrapper" ).draggable();
$( "#bigwrapper2" ).draggable();
var SacramentoBG = ['nightcap.jpg','Tower_Bridge_Sacramento_edit.jpg'],
counter =0;
$('html').dblclick(function (event) {
if (event.target.id != "bigwrapper" && event.target.id != "bigwrapper2") {
counter = (counter+1) % SacramentoBG.length;
$('html').css('background-image', "url("+SacramentoBG[counter]+")");
} else {
$("#bigwrapper").toggle();
$("#bigwrapper2").toggle();
}
});
});
UPDATE: The solution below to add 'event' inside the function partially helped, as the backgrounds rotate properly, however the #bigwrappers aren't toggling as intended (the else condition). See: http://artfuladvection.com/project/NOAA/ndfdGraph/bloom.php Ideas?
Thanks!
that's because the dblclick function doesn't know about the event variable. try this
$('html').dblclick(function (event) {
The complete answer that worked for me was that I needed to stop excluding specific classnames/ids and instead exclude entire element tags. Alternatively, I could just use if (event.target.TagName == 'BODY') {}
$('body').dblclick(function (event) {
if (event.target.tagName != 'DIV' && event.target.tagName != 'IMG' && event.target.tagName != 'TABLE' && event.target.tagName != 'HR' && event.target.tagName != 'SMALL' ) {
counter = (counter+1) % SacramentoBG.length;
$('html').css('background-image', "url("+SacramentoBG[counter]+")");
} else {
$("#bigwrapper").toggle();
$("#bigwrapper2").toggle();
}
});

Can I toggle popup after a click event with a mouseout event?

I'm using twitter bootstrap to display popovers with a click event. I'm requesting the info with the click event but I want to hide the popover after it looses focus so the user isn't required to click it again. Is this possible?
Basically I want to show the popover with a click event but then when the launch point looses focus from the mouse the popover is hidden.
Here is a link to the popover doc from twitter-bootstrap: http://twitter.github.com/bootstrap/javascript.html#popovers
This is what I'm currently doing:
jQuery:
$('.knownissue').on('click', function() {
var el = $(this);
if (el.data('showissue') == 'true') {
el.popover('toggle');
el.data('showissue', 'false');
return;
}
$.post('functions/get_known_issues.php', function(data) {
if (data.st) {
el.attr('data-content', data.issue);
el.popover('toggle');
el.data('showissue', 'true');
}
}, "json");
});
Any thoughts?
The following should work.
$('.knownissue').mouseleave(function() {
$(this).popover('hide');
});
Here is a custom jQuery event I call 'clickoutside'. It gets fired if and only if you click the mouse outside of the target element. It could easily be adapted for other event types (mousemove, keydown, etc). In your case, when fired it could close your modal.
(function ($) {
var count = 0;
$.fn.clickoutside = function (handler) {
// If the source element does not have an ID, give it one, so we can reference it
var self = $(this);
var id = self.attr('id');
if (id === '') {
id = 'clickoutside' + count++;
self.attr('id', id);
}
// Watch for the event everywhere
$('html').click(function (e) {
var source = $(e.target);
// ... but, stop it from propagating if it is inside the target
// element. The result being only events outside the target
// propagate to the top.
if (source.attr('id') == id || source.parents('#' + id).length > 0) {
return;
}
handler.call(this, e);
})
};
})(jQuery);
$('#targetElement').clickoutside(function(){
});
EDIT: Example JSFiddle.

only writing "return false" once to handle clicking on many links

Instead of writing return false; many times is there a way to set a collection of links such that if any of them are clicked the click function would return false;? I'd still like to have most links return true so showing code that would return true vs. return false would be particularly appreciated.
The goal is writing less code. I'd also like to know if this is a bad idea for reason I can't understand.
The simpliest method is binding one event listener to the document, and checking for the target: http://jsfiddle.net/gKZ7q/
document.addEventListener('click', function(e) {
if (e.target.nodeName.toUpperCase() === 'A') e.preventDefault();
}, false);
For anchors with nested elements, you have to add an additional loop:
var targ = e.target;
do {
if (targ.nodeName.toUpperCase() === 'A') {
e.preventDefault();
break;
}
} while ((targ = targ.parentNode) !== document.documentElement);
// document.body should be fine. Using document.documentElement in case
// that a fool places an anchor outside the <body>
Links can also be triggered through a key event.

Categories