I have created a simple div demonstration below, that will display none once click.
<div id="three" onclick="toggle2(event);return false;" style="background:#303; color:#FFF;">
function toggle2(e) {
var textx = (e.target) ? e.target : e.srcElement;
textx.style.display = "none";
console.log(e.target);
}
my question is what is the difference if I replace
<div id="three" onclick="toggle2(event);return false;" style="background:#303; color:#FFF;">
with
<div id="three" onclick="toggle2(this);return false;" style="background:#303; color:#FFF;">
both of them work fine for my example abovee.....
It may well be that they are exactly the same. This depends on the HTML. In this case, this will always be the div element. this refers to the element where the event is captured. event.target, however, points to the element where the event originated.
If the element has no children, they will always be the same. If, however, you had something like this:
<div id="three" onclick="toggle2(event);return false;" style="background:#303; color:#FFF;">
<span>Line 1</span>
Line 2
</div>
then they may be different. A click on Line 1 will cause event.target to be the span element, so only that element will be hidden.
Unless you specifically want to point to the element where the event originated, it's more intuitive to use this.
You usually use e.target when "e" is the event like a click passed in parameter.
When you pass this as a parameter, this is the reference to the DOM node in which there is the javascript method. So here, "this" references the div.
And as you have a click event on your div, when you click on it, it is considered as an event, that's why this and e.target both work.
Moreover, "this" will always refer to you div, whereas "e.target" will reference an element you clicked in the div.
I think isn't necessary to pass this as argument on onclick event, you can use this direct to the function.
The event refers to the event currently being fired. Now in a browser the events are bubbled up from the element on which the event is fired to its parent until it reaches the document root. More at: What is event bubbling and capturing?
In your example, the event points to the click event and the event.target is the div and this refers to the div itself. If you add a child element to the div and click on the element then the event.target will point to the child element and this will still refer to the div.
Related
I am implementing html5 drag and drop (for the first time). I have the following ng-repeat where the drop target is the outer div:
<div ng-repeat="chapter in chapters" class="chapter " ondrop="drop_handler(event);" ondragover="dragover_handler(event);">
<div><bold>{{chapter.title}}</bold></div>
<div>{{chapter.text}}</div>
</div>
However the dragover event is fired also for the inner elements (as event.target).
In my dragover_handler() I need to get hold of the outer div so that I can, for example, set a background-color. How can I achieve this?
I could do this by specifying a ondragover for each inner element and then selecting the outer div, but that is really ugly as it needs the ondragover attr for each inner element.
This can be achieved by using node.addEventListener('dragover', handler_func, true) instead of element attribute.
The 3rd function to addEventListener turns on event capturing and this allows events fired from child elements to be sent to specified handler_func.
JavaScript
function productBox(event){
event.stopPropagation();
console.log(event.target);
}
var product = document.getElementsByClassName('product');
for (var g = 0, length = product.length; g < length; g++){
console.log('here');
product[g].addEventListener('click',productBox);
}
HTML
<div class="product">
<div class="productContent">
<img src="file:///C|/Users/Jacob/Downloads/12939681_1597112303636437_733183642_n.png" />
</div>
<div class="productName">
Here
</div>
<div class="productDescription">
</div>
So the problem lies in the fact that when the product element is clicked, event.target returns the actual child element of the event listener. For example, i click a "product" and it'll return productContent, productName or productDescription as the target, when actually what i want is the "product" element and then to do a .childNodes and find the image within that.
Please note jQuery is not an option, it is 30kb of stuff i won't use as this is a static html page with barely any javascript.
I've thought perhaps,
doing a check if the element is 'product' if not, take the parent and check if it's a 'product', if not go to that parent and so on. Then find the img tag within that. But i feel like that is a long winded work around.
Any thoughts?
To get the element to which the handler is bound, you can use this within the handler.
As #DaveNewton pointed out, the event object has a .currentTarget property that can be used as well. This is nice because you can have functions that have a manually bound this using .bind() or you may be using the new arrow functions, which have a this defined by its original environment, making it impossible to get the bound element that way.
You can use parentElement property of the target.
function productBox(event){
var target = event.target;
var parent = target.parentElement;//parent of "target"
//Rest of your code
}
I asked a similar question: if you have a element.click(function(){}) and the element has two or multiple siblings. If the event trigger is attached to the parent and not the target, this post popped up and is actually irrelevant to my question so I decided to post my search here for someone else.
I used this method:
if (target.closest('.NEftune').attr('rel') != undefined){
/*do something here*/
}
The closest method in jQuery and JavaScript starts from the clicked target and then bubbles up until it finds an attribute you looking for. In my case the event was attached to an Element with the class (.NEftune) and by adding an extra attribute I could determine if I was inside the container (.NEftune) which has an image inside.
I know it's a bit late, but the simplest solution to get the actual target to which the event handler was attached to is to use the event currentTarget property.
This will avoid unnecessary further DOM check and works out of the box on all modern browsers.
Event.currentTarget on MDN
The currentTarget read-only property of the Event interface identifies the current target for the event, as the event traverses the DOM. It always refers to the element to which the event handler has been attached, as opposed to Event.target, which identifies the element on which the event occurred and which may be its descendant.
I am not able to trigger event on element I clone/insert to the DOM.
Check the fiddle here.
HTML:
<div class="A">[THIS IS DIV A]</div>
<div class="B">CLICK TO CLONE DIV A</div>
jQuery:
$('.A').on("click",null,function() {
alert('DIV A CLICK');
});
$('.B').on("click",null,function() {
$('.A').clone().insertAfter('.A');
});
If I click on a cloned DIV A, nothing happens.
How can I trigger event on cloned element?
There are two solutions I propose.
Firstly, and the better option in this case, would be to add the true argument to clone(), for example in this case it would be:
$('.A').clone(true).insertAfter('.A');
As first argument of clone() represents:
"A Boolean indicating whether event handlers and data should be copied
along with the elements. The default value is false." - jQuery API section for clone().
This means all bound events will be kept on each cloned element.
jsFiddle here.
The second option, probably not the way to go for this example, would be to use on()'s event delegation feature:
"Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time." - jQuery API section for on().
In this case:
$(document).on("click", ".A", function() { ...
Now, every new element with the class .A will be have this click event attached to it, even cloned elements.
jsFiddle here.
Are the docs for jQuery's on() function incorrect (or unclear)? Consider this code:
<div>
<span>
<div>
<input type="button" value="click me!" />
</div>
</span>
</div>
$(document).on("click", function() {
console.log(this.toString());
});
The docs state
selector A selector string to filter the descendants of the selected
elements that trigger the event. If the selector is null or omitted,
the event is always triggered when it reaches the selected element.
Clicking the button only causes one console.log for the document itself, while $(document).on("click", "*", function()... causes many.
I know the Stack Overflow community isn't responsible for the jQuery docs, but shouldn't they say that when the selector is omitted, the event is only triggered when it reaches the selected element? Or is there something about event delegation I'm not understanding correctly?
Complete fiddle
There is no event delegation when you leave the selector out. From the docs:
If selector is omitted or is null, the event handler is referred to as
direct or directly-bound. The handler is called every time an event
occurs on the selected elements, whether it occurs directly on the
element or bubbles from a descendant (inner) element.
When a selector is provided, the event handler is referred to as
delegated. The handler is not called when the event occurs directly on
the bound element, but only for descendants (inner elements) that
match the selector. jQuery bubbles the event from the event target up
to the element where the handler is attached (i.e., innermost to
outermost element) and runs the handler for any elements along that
path matching the selector.
Basically .on is doing the jQuery thing -- it is overloaded to do completely different things depending on arguments. Personally I prefer .delegate for delegation, and .bind for normal events, as they are much clearer and I hope they don't get removed in later versions.
Personally I think it's clear enough. When the selector is omitted the event is triggered when it reaches the selected element. The word "always" doesn't really change the meaning in my opinion. The event will always be triggered when it reaches the selected element (note that if something like stopPropagation is called, the event will not reach the selected element and therefore won't be triggered).
When a selector is present, the event is triggered when it reaches the selected element having originated from an element matching the selector.
When you use the universal selector * every single element between the event target and the selected element will trigger the event.
As you stated in your comment, on provides all the functionality you need to bind events in jQuery 1.7+:
As of jQuery 1.7, the .on() method provides all functionality required
for attaching event handlers.
Here's a question about binding click events with jQuery that I'm trying to make sense of.
Say I have a block element I bind a click to, with a paragraph tag inside of it:
<div id="testClick" style="width:200px; height:100px'>
<p>test click</p>
</div>
and I bind a click to the div:
$('#testClick').bind('click', function(e){
//with parent div (via e.target), do something
});
Now, if I click on the text inside the p tag, e.target = the p element, and if I click on the div (around, not on the text) e.target = the div element. So e.target = the object clicked on - i.e. the event is also bound to any children of the element specified.
This is to be expected, but I need operate on the parent div. and using e.target is not a reliable way of getting a reference to the div, because depending where within the div the click occurs e.target returns a different element. If I use e.target.parent to get a reference to the div, this fails when the click occurs in the div around the text.
Is there no simple way to get e.target to always and only return the exact element to which the click was initially bound?
(For example, in actionScript there is a property "mouseChildren" that prevents events from firing on children of bound elements)
(Consider all above pseudo code)
this will reference the element to which the handler is bound.
$('#testClick').bind('click', function(e){
alert( this.id );
});
DEMO: http://jsfiddle.net/yX499/
What happens is that the event bubbles up from the most deeply element clicked all the way to the document root.
If it encounters an element along the way with a handler bound for the type of event that occurred, it invokes that handler.
e.target will always reference that deeply nested element, but this will reference the element to which the handler is bound, so if the event finds 2 elements with an appropriate handler bound on the way up to the root, e.target will not change in the 2 handlers, but this will be different based on the bound element.
Use this. jQuery calls your callback with this set for your convience:
$('#testClick').bind('click', function(e){
$(this).doStuff();
});