is there a way to get the element? i.e:
$('#obj').hover(function() { },function() { /* here, i need to know the element that triggered this out event. */ });
thanks.
It's called ev.target
function (ev) {
var target = ev.target
// target triggered event
}
Of course you may not want the target but rather want the currentTarget
The currentTarget is the element the event handler is bound to.
As for the value of this in the callback. It's generally ev.currentTarget, jQuery uses that, the current DOM4 WD uses ev.target and the current DOM4 ED uses ev.currentTarget. I belief it's generally ev.currentTarget in legacy engines.
Note that if your not using jQuery but using the IE propitiatory event system then ev.srcElement is the equivelant of ev.target
in jQuery event binding, it passed you back an event object that you can access in your function, that object has the control in it, i think its targetElement or something like that ... so change your code to $('#obj').hover(function(ev) { }
and ev.targetElement should be what you're looking for.
Related
Is there a difference between working a property of an element through the event.target vs working it directly?
I don't understand if there's any difference.
const btn = document.querySelector('#btn');
btn.addEventListener('click', function(e) {
console.log(e.target.value);
//vs
console.log(btn.value);
}
Is there a better practice when doing this?
Yes, there is an important difference. The event.target property tells you what element was involved with the creation of the event. For a "click", it's the element that was under the cursor when the "click" happened.
Thus if your HTML looked like:
<button><span>Text</span><img src="something.jpg"></button>
a click on the button content would trigger the event from either the <span> or the <img>, and one of those elements would be the target.
There's another event property, event.currentTarget, that is always a reference to the element to which the event handler is attached. That's probably what you want. Alternatively, if you bind handlers with .addEventListener(), then the value of this when the handler is invoked will be a reference to the same thing as currentTarget.
In your case you're selecting an element by ID. Your reference is the same as the target so there is no difference. A lot of time we use delegation so you might not have reference to the clicked element. Hence we use target from the event object.
Worth also to check target vs currentTarget
I want an element to listen for a custom event that is actually triggered by itself. The custom event could possibly be triggered from a descendant but should then be ignored. It's important that it origins from itself. It also needs to be an event since I might need additional ancestors to listen for the events.
The .on (http://api.jquery.com/on/) method is able to provide this functionality. The selector argument can be used as filter. However this does not work to filter out the listener element itself.
In short:
-The event must be able to bubble
-The trigger and the listener is the same element
-The listener must ignore the custom event if it's triggered by an ancestors
How is this achieved?
Use case as requested
I use the jquery UI dialog widget
$el = $('#dialogDiv');
$el.on('customEvent', $el /* Won't work */, function() {
//Do whatever
});
$el.dialog({
open: function() {
$el.trigger('customEvent');
}
});
.on works fine; to ignore ancestors check e.target:
$el.on('customEvent', function(e) {
if(e.target === this) {
//Do whatever
}
});
The selector that you can pass to .on() is used for the delegate target to match elements that can handle the click event (and it should be a string, not an object).
But in your case that's not necessary because your selector and the delegate target is the same thing, so this should work as expected:
$el.on('customEvent', function(evt) {
//Do whatever
});
To detect if an event came from a descendent you would compare evt.target against the element itself.
Removing the part that doesn't work, will make it work.
$el = $('#dialogDiv');
$el.on('customEvent', function(e) {
//Do whatever
});
$el.dialog({
open: function() {
$el.trigger('customEvent');
}
});
However, you are asking for other features that a normal event might not support. You should look into setting up a jQuery special event. Check this awesome article by Ben Alman.
When it comes to your prerequisites:
An event is always able to bubble unless its propagation is hindered with event.stopPropagation() or event.stopImmediatePropagation()
The trigger and the listener is already on the same element
The listener will not know what triggered it unless you pass some an argument that can identify the element that triggered it and check if it's an ancestor
See test case on jsFiddle.
I want an element to listen for a custom event that is actually triggered by itself. The custom event could possibly be triggered from a descendant but should then be ignored. It's important that it origins from itself. It also needs to be an event since I might need additional ancestors to listen for the events.
The .on (http://api.jquery.com/on/) method is able to provide this functionality. The selector argument can be used as filter. However this does not work to filter out the listener element itself.
In short:
-The event must be able to bubble
-The trigger and the listener is the same element
-The listener must ignore the custom event if it's triggered by an ancestors
How is this achieved?
Use case as requested
I use the jquery UI dialog widget
$el = $('#dialogDiv');
$el.on('customEvent', $el /* Won't work */, function() {
//Do whatever
});
$el.dialog({
open: function() {
$el.trigger('customEvent');
}
});
.on works fine; to ignore ancestors check e.target:
$el.on('customEvent', function(e) {
if(e.target === this) {
//Do whatever
}
});
The selector that you can pass to .on() is used for the delegate target to match elements that can handle the click event (and it should be a string, not an object).
But in your case that's not necessary because your selector and the delegate target is the same thing, so this should work as expected:
$el.on('customEvent', function(evt) {
//Do whatever
});
To detect if an event came from a descendent you would compare evt.target against the element itself.
Removing the part that doesn't work, will make it work.
$el = $('#dialogDiv');
$el.on('customEvent', function(e) {
//Do whatever
});
$el.dialog({
open: function() {
$el.trigger('customEvent');
}
});
However, you are asking for other features that a normal event might not support. You should look into setting up a jQuery special event. Check this awesome article by Ben Alman.
When it comes to your prerequisites:
An event is always able to bubble unless its propagation is hindered with event.stopPropagation() or event.stopImmediatePropagation()
The trigger and the listener is already on the same element
The listener will not know what triggered it unless you pass some an argument that can identify the element that triggered it and check if it's an ancestor
See test case on jsFiddle.
I'm a JS newbie - still learning. I'm looking for a solution similar to this example
for displaying the source link of an image in an alert using onclick. However, I want to apply it to any image on the page, and there are no ID's on any of the images. Perhaps this is an application of the mysterious 'this'? Can anyone help me? Thanks!
No, this has to do with delegate event listeners, and the way events spread across the DOM.
When you click on an element in the page, a click event is generated. For what it matters to your purposes, this event is fired on the element, and it's caught by the function you define with onclick.
But the event also "bubbles up" to the parent, and it's caught by the onclick function defined there, if any. And then to the parent of the parent, and so on.
What you have to do, now, is to catch the event on the root element, which is the document object itself, or maybe the document.body element if you still want to use onclick (which is deprecated).
The event object is passed to the onclick function and it contains the original element that fired the event:
document.body.onclick = function(e) {
var tgt = e.target || e.srcElement;
if (tgt.tagName === "IMG")
alert(tgt.src);
}
(The e.target || e.srcElement part is because in IE<9 the target property is called srcElement.) That's the way you define a delegate event listener. It's not defined on the <img> elements, as you can see, but on their common ancestor.
But since you can define just one click event listener in the traditional way, I'd strongly recommend to use something more modern like the addEventListener method, which lets you add multiple event listeners on the same element for the same event type:
document.body.addEventListener("click", function(e) {
...
});
In Internet Explorer <9 you'll have to use attachEvent, which is quite similar but not the same. For a cross-browser solution, use a common JS framework like jQuery, or Prototype, or whatever.
If I understand your question this is your solution,
var img = document.getElementsByTagName('img');
for(var i=0;i<img.length;i++){
alert(img[i].src);
}
Assuming that there are a large number of elements throughout the site that have an unknown number and type of events bound to them.
If I need to override all of these events with one single bound event, and only that event will fire, what are some recommendations?
I would be binding the event to a click event handler, and I am using jQuery.
Thanks in advance.
You’re looking for jQuery#unbind.
To remove all event handlers on an element or a set of elements, just do:
$('.some-selector').unbind();
To unbind only click handlers, use unbind('click'):
$('.some-selector').unbind('click');
To unbind all click handlers and immediately bind your own handler after that, you can do something like this:
$('.some-selector').unbind('click').click(function(event) {
// Your code goes here
});
Note that this will only work for events bound using jQuery (using .bind or any jQuery method that uses .bind internally). If you want to remove all possible onclick events from a given set of elements, you could use:
$('.some-selector')
.unbind('click') // takes care of jQuery-bound click events
.attr('onclick', '') // clears `onclick` attributes in the HTML
.each(function() { // reset `onclick` event handlers
this.onclick = null;
});
I would like to provide a thought without removing all events all together (just override them).
If your new one single bound event (we call it "click" here) is specific to the element it binds to, then I believe you can ignore any other events simply by stopPropagation() function. Like this
$("specific-selector").on("click", ".specific-class", function (e) {
e.stopPropagation()
// e.stopImmediatePropagation()
/* your code continues ... */
});
It will stop events bubbles up, so your other events won't fire. use stopImmediatePropagation() to prevent other events attached onto the same elements as "click" does.
For example, if "mouseleave" event is also bind to $("specific-selector .specific-class") element, it won't fire, too.
At last, all other events won't fire on this element but your new "click" element.
The unsolved question is, what if other events also use stopPropagation()? ... Then I think the one with best specification wins, so try to avoid complex, too many events is final suggestion.
You can see "Direct and delegated events" on jQuery site for more information.
Looks like this is pretty simple actually:
$('#foo').unbind('click');
$('#foo').bind('click', myNewFunction);
Thanks for your responses though.
Try to use live instead of bind. Then you can easily remove live binding with die from selector which is fast operation and set another live equally fast.
$('selection here').live('..', .....); // multiple invocations
$('selection here').die();
$('selection here').live('click',.....);
DOM is not touched at all. Event condition is evaluated on event occurrence.
But generally if you just want to swap handler functions why not to do it this way:
var ahandler = function(evt) { /* first implementation */ }
$('.selector').bind('click', function(evt) { ahandler(evt); });
//and then if you want to change handlers
ahandler = function(evt) { /* new implementation */ };
This gives absolutely no cost of any changes, rebinding etc.