I've added a click event as follows and would like to check if the target has a specific parent.
$(document).click(function(event){
// Check here if target has specific parent for example -> #parent
});
How can this be done?
There's a .parent() dom traversal method for this.
according to Pointy's crystal ball, you probably want to do something like this:
$(document).click(function(event) {
if ($(event.target).parents('.selector').length > 0) {
}
});
I'm not sure why are you set click handler on document, maybe looking for event delegation and the .on()?
I believe this also works.. AFAIK jQuery events use the the literal element instead of a jQuery object when calling events. Basically this should be your normal DOM element with normal JavaScript properties.
$(document).click(function(event)
{
let myparent = $(this.parentNode); //jquery obj
let parent = $(this.parentNode)[0]; //plain DOM obj
let myself = $(this); //jquery obj;
let $elf = this; //plain DOM obj
});
Note: sometimes using 'self' as a variable is bad/causes conflicts with certain libraries so i used $elf. The $ in $elf is not special; not a jQuery convention or anything like that.
$(document).click(function(event){
var $parent = $(this).parent();
// test parent examples
if($parent.hasClass('someclass')) { // do something }
if($parent.prop('id') == 'someid')) { // do something }
// or checking if this is a decendant of any parent
var $closest = $(this).closest('someclass');
if($closest.length > 0 ) { // do something }
$closest = $(this).closest('#someid');
if($closest.length > 0 ) { // do something }
});
I have reliably used this in the past:
var target = $( event.target )
This will give you a reference to the jQuery object for the element that had the event invoked. You could use this same approach and see if the parent is "#parent", something like this:
var target = $( event.target )
if (target.parent().attr('id') == "#parent") {
//do something
}
Related
Is there a way to add some kind of listener for a type of html element? For example if i wanna call a function when the user clicks any p element
the easiest answer would be using addEventListener() if you want a specific html tag just like what i wanted in my question then you'll find the answer there ill paraphrase it here too
add this
<script>
document.addEventListener("click", function(e){
//your desired nodeName like : DIV , SPAN , LI etc
if(e.target && e.target.nodeName== 'DIV')
//add a function below to trigger
{alert('bingo')}
});
</script>
to the end of your document
by the way don't forget to use uppercase nodeNames or just put a toLowerCase() before it. cheers :)
Add the event listener to the window / document / document.body and check the type of the element and the types of its parents because if you have a <span> inside a <p>, clicking the span won't trigger the click in the paragraph.
document.addEventListener("click", function (eventArgs) {
var target = eventArgs.target;
var elementToLookFor = "p";
while (target !== null) {
if (target.tagName.toLowerCase() === elementToLookFor) {
// Do magic stuff with the paragraph
console.log(target);
}
target = target.parentElement;
}
});
This technique is called "event delegation."
Edit: Note that you cannot early return from the loop above. If your have nested paragraphs, i.e.
<p>
Hey,
<p>there!</p>
</p>
Having an early return will only call your event handler for the inner paragraph, whereas you said that you'd like the handler to be invoked on every paragraph which is why you need to traverse all the ancestors of the element.
I assume that you are looking for code along these lines:
var paras = document.getElementsByTagName("p");
// Loop through elements.
for(var i = 0; i < paras.length; i++) {
// Add listener.
paras[i].addEventListener("click",
function() {
// Execute function.
}, false);
}
I'd just select all the elements on the page and add eventListeners on them like so:
function addListeners(elementType, eventType, callback) {
Array.prototype.slice.call(document.querySelectorAll(elementType)).forEach(function (el, i) {
el.addEventListener(eventType, callback, false);
});
}
Above we use querySelectorAll to pick all the wanted elements, convert it to an Array (if you use es6, you can use Array.from) and then we loop through the array and add listeners with the wanted callback.
Here's an example: https://jsfiddle.net/a7en4d4s/
Look at this JSFiddle, and see if it works for you
<span>Click Yes</span><br/><br/>
<span>Click No</span><br/><br/>
<a>Clicked: <b id="result"></b></a>
<script>
$("span").click(function(){
var a = $(this).html();
$("#result").html(a);
});
</script>
I'm new to JavaScript and am unsure how to do the following:
I've got two links with the same css "class" but different "name" attributes. I need to perform different functions to each one individually when clicked using unobtrusive Javascript. Is there anyway to do this?
Example code:
<a class="ClassName" name="link1">Link 1</a>
<a class="ClassName" name="link2">Link 2</a>
Lets say I need to output "This is link 1" to the console when I click link 1. And "this is link 2" when Link 2 is clicked.
Attach an event handler to the elements, and just check the name and do whatever you'd like
var elems = document.querySelectorAll('.ClassName');
for (var i=elems.length; i--;) {
elems[i].addEventListener('click', fn, false);
}
function fn() {
if ( this.name == 'link1' ) {
console.log('This is link1');
} else if ( this.name == 'link2' ) {
console.log('This is link2');
}
}
FIDDLE
You can do like in this JS Fiddle Demo , its pretty simple:
JS:
var anchorTags = document.querySelectorAll('.ClassName');
for (var i = 0; i < anchorTags.length; i++) {
anchorTags[i].onclick = function() {
alert(this.innerHTML);
}
}
Hope this helps.
It's not very performant but you can use name selectors. .className[name=link1] however, if you have multiple links the best way to handle something like this is to use event delegation. It's really easy if you have access to jquery
I would do something like
parent.on('click', '.ClassName', function(event) {
var button = $(this),
name = button.attr(name);
switch(name):
case link1
case link2
...
});
this way you don't have to assign individual events to the different links. You could also do something like this without event delegation if you really wanted to it would just be changing it to
var links = $('.ClassName');
links.on('click', function() {
...
});
Keep in mind that the latter will attach an eventHandler to each link.
If you don't have jQuery you can still do this you just need to grab the elements differently and handle attachEvent vs addEventHandler. Also, applying the delegation will require delving into the event.currentTarget object.
something like:
var parent = document.getElementById('parentid');
parent.addEventListener('click', function(event) {
if (event.currentTarget.getAttribute('class')indexOf('ClassName') > -1) {
... do stuff w/ that link here
}
});
I am trying to detect whether a target element is either a child element, or the same element, that I have as an object reference.
I am using the following logic:
$("html").on("mousewheel.scroll DOMMouseScroll.scroll",function(e){
e.preventDefault();
var $scrollableElement = $(".foo").eq(0);
var $target = $(e.target);
if ($target == $scrollableElement
|| $target.parents($scrollableElement).length) {
alert("scroll");
}
});
However "scroll" is alerted even when scrolling over an element which is neither .foo or a child of .foo.
In my JsFiddle example, scroll over the .bar element, and "scroll" is still alerted:
http://jsfiddle.net/Lf3d2/
Why is this? Is it possible to use jQuery object references as the selector of .parents()?
Try .closest() instead of .parents()
$(function () {
var $scrollableElement = $(".foo").eq(0);
$("html").on("mousewheel.scroll DOMMouseScroll.scroll", function (e) {
e.preventDefault();
var $target = $(e.target);
if ($target.closest($scrollableElement).length) {
console.log("scroll");
}
});
});
Demo: Fiddle
If you have a look at the syntax of .parents(), it does not take a jQuery object as a parameter. The only allowed syntax is .parents( [selector ] )
As #A.Wolff asked why don't bind the event to .foo instead
Demo: Fiddle
In a simple example, I try to make delegate for first-level children of an element. The problem comes when the child elements have children. The mouse event consider the clicked element (regardless of level).
My solution is to cycle until reaching the first-level child; but I wonder if this is the best method to do so.
Isn't there a method for directly returning the first-level children upon delegate click?
JS
window.onload=function(){
document.getElementById('test').addEventListener('click', function(e){
console.log(e.target);alert(e.target.id);
}, false);
}
HTML
<div id="test">
First
<b>Second</b>
Third
Fourth
<div id="div">Division</div>
<div id="div2"><span>Division</span></div>
</div>
If it's only the first level elements you're after, you could check if the parentNode of the clicked element is the root, no further traversing needed. Otherwise you'll need to traverse up to the first child of the root. Something like:
// level0 is the root
level0.addEventListener('click', function(e) {
var from = e.target || e.srcElement;
from = from.parentNode === level0 ? from : findFirst(level0,from);
/** do things **/
}, false);
// traverse up to first child of [root]
function findFirst(root,el){
while(true){
el = el.parentNode;
if (el && el.parentNode === root){
return el;
}
}
return null;
}
Here is a fork of your jsfiddle, using the above.
using only javascript you can use a recursive function that will find the first parent element with an id:
function findParentWithId(element){
if(element.id){
return element;
}
return findParentWithId(element.parentNode);
}
and then, use it with the target element of the event
document.getElementById('test').addEventListener('click', function(e){
console.log(findParentWithId(e.target));alert(findParentWithId(e.target).id);
}, false);
I'm not sure what's beeing ask here. Events do Bubble by default (which is actually not true, by default they would traverse top->down) because its most common to call .addEventListener with false as third argument.
You can stop most events from further bubbling up, by calling eventObject.stopPropagation() on the node where you want to stop it.
If you want to "prefilter" only the first-level children, you shouldn't use delegation at all, but query with .querySelectorAll like
[].forEach.call( document.querySelectorAll('#test > *'), function( node ) {
node.addEventListener('click', function( event ) {
alert( this.id );
}, false);
});
That would bind click event listeners on all direct children from #test.
See that in action: http://jsfiddle.net/8Xmn4/
Getting a reference to all first level children of a node is simple:
window.onload=function(){
document.getElementById('test').addEventListener('click', function(e){
return document.getElementById('test').children;
}, false);
}
this outputs, on Firebug format:
[a#first #, a#second #, a#third #, a#fourth #, div#div, div#div]
Obviously, it returns the children with their respective children, but the first level reference remains.
jQuery(':first-child') use this jquery to get the first child
How can I do that?
event.target returns a HTML object,
and my element is a jQuery object.
Is there a better way to find out if event.target = my_jquery_object, besides comparing IDs or classes?
I want to make sure that it's the same object, not just a element with a similar class...
I tried with $(event.target) !== the_element and it fails
the_element is defined at the begining as $('.something', $(this))
What I am trying to do is to make a box close when the user clicks outside of it, but with the condition that the click wasn't made on the link that opened the box in the first place.
So I have this:
$(document).click(function(event){
if(($(event.target).parents().index(box) == -1)
&& box.is(':visible')){
close();
}
});
And I want to add another condition that verifies that the click wasn't made on the link that opened the box.
This works, but I don't like it:
if($(event.target).attr('id') != the_element)
:)
You can get the actual DOM element from the jQuery using .get(0) or simply the_element[0]. It would probably be better to check with jQuery, though.
if (the_element.is(event.target))
{
...
}
Using your example:
$(document).click(function(event){
if (the_element.is(event.target)) {
return false;
}
if(($(event.target).parents().index(box) == -1)
&& box.is(':visible')){
close();
}
});
Try -
if(event.target === the_element[0])
the_element[0] should unwrap your jQuery object and return a 'normal' DOM object, you can then compare it against the DOM object returned by event.target.
Maybe I'm wrong, but it looks like nobody understood the question?... I also want to know how to GET JQUERY OBJECT on which I used listener function from the EVENT.TARGET, but not a DOM node for a jquery object!!))
So... I found not a very handy, but working solution:
var elem = $('<input type="text" class="input" />');
elem.focus( $.proxy( function( e )
{
this.onInpFocus( e, elem );
}, this ) );
And modified the listener's callback method to receive 2 arguments:
onInpFocus : function( e, inp )
Instead of using simple way like:
elem.focus( $.proxy( this.onInpFocus, this ) );
Actually, I found another way, much more handy one :)
Just need to use the data argument:
Data to be passed to the handler in event.data when an event is
triggered.
Now my code looks like this:
var inp = $('<input type="text" />');
inp.focus( { j : inp } , $.proxy( this.onInpFocus, this ) );
//and the handler method
onInpFocus : function( e )
{
var inp = e.data.j;
...
}