Opened 6 years ago

Closed 6 years ago

#17145 closed defect (invalid)

event.target is the lowest leaf during event delegation using dojo/on

Reported by: rwadkins Owned by: Kris Zyp
Priority: undecided Milestone: tbd
Component: Events Version: 1.9.0
Keywords: Cc:
Blocked By: Blocking:

Description

When we use dojo/on to delegate an event to a higher node in the dom, we're noticing that event.target represents the lowest leaf in the tree that fired the event. There doesn't seem to be a reference to the element that we selected with our selector. Looking at the source for dojo/on seems to confirm this:

		return function(target, listener) {
			// if the selector is function, use it to select the node, otherwise use the matches method
			var matchesTarget = typeof selector == "function" ? {
				matches : selector
			} : this, bubble = eventType.bubble;
			function select(eventTarget) {
				// see if we have a valid matchesTarget or default to dojo.query
				matchesTarget = matchesTarget && matchesTarget.matches ? matchesTarget : dojo.query;
				// there is a selector, so make sure it matches
				while (!matchesTarget.matches(eventTarget, selector, target)) {
					if (eventTarget == target || children === false || !(eventTarget = eventTarget.parentNode) || eventTarget.nodeType != 1) { // intentional assignment
						return;
					}
				}
				return eventTarget;
			}
			if (bubble) {
				// the event type doesn't naturally bubble, but has a bubbling form, use that, and give it the selector so it can perform the select itself
				return on(target, bubble(select), listener);
			}
			// standard event delegation
			return on(target, eventType, function(event) {
				// call select to see if we match
				var eventTarget = select(event.target);
				// if it matches we call the listener
				return eventTarget && listener.call(eventTarget, event);
			});
		};  

It appears that the listener is getting called with the "eventTarget" (the one I actually care about) as the execution context, but the "event" argument contains no reference to it. Please see this jsFiddle for an example (http://jsfiddle.net/gfUKZ/). While it's possible to get the object using "this" in the listener, we can't use hitch to bind the listener to our module.

I believe that event.target should equal eventTarget in this instance.

Change History (5)

comment:1 in reply to:  description Changed 6 years ago by bill

Replying to rwadkins:

When we use dojo/on to delegate an event to a higher node in the dom, we're noticing that event.target represents the lowest leaf in the tree that fired the event.

This is how events work. Try something like

document.body.addEventListener("click", ...)

and check evt.target (while clicking on a subnode of <body>)

It appears that the listener is getting called with the "eventTarget" (the one I actually care about) as the execution context, but the "event" argument contains no reference to it. Please see this jsFiddle for an example (http://jsfiddle.net/gfUKZ/). While it's possible to get the object using "this" in the listener, we can't use hitch to bind the listener to our module.

Instead of doing this:

on(d, "li:click", lang.hitch(foo, "bar"))

you should be doing:

on(d, "li:click", function(evt){
    foo.bar(evt, this);
});

Presumably this ticket should be closed since the code is working as designed and documented.

comment:2 Changed 6 years ago by rwadkins

What we're doiong is

on(d, "li:click", lang.hitch(this, "bar"));

which doesn't translate well to

on(d, "li:click", function(evt){
    this.bar(evt, this); //obviously this doesn't have a bar method in this context
});

I'm not sure why the hitch pattern isn't supported by delegation.

comment:3 Changed 6 years ago by rwadkins

it would even be supportable if evt had a property called eventTarget that contained a reference to the element matching the selector.

Although, IMO, target is more accurate.

Last edited 6 years ago by rwadkins (previous) (diff)

comment:4 Changed 6 years ago by bill

Just do this:

var _this = this;
on(d, "li:click", function(evt){ _this.bar(evt, this); });

You could alternately do this:

var bar = lang.hitch(this, "bar");
on(d, "li:click", function(evt){ bar(evt, this); });

comment:5 Changed 6 years ago by bill

Resolution: invalid
Status: newclosed
Note: See TracTickets for help on using tickets.