I am a software developer currently based in London, England with a keen interest in all kinds of things to do with technology.

Issues with the Event object interface in JQuery's implementation of event delegation

authorRichard Hunter date createdMay 29 2016 04:30 PM
Event delegation in Jquery doesn't conform properly to the pattern. Here I examine the issue and propose a solution.

This article contains a critique of JQuery's implementation of event delegation, specifically regarding its implementation of the event object which is passed to event handlers registered via the on() method.

Event delegation(henceforth 'ED') is when you attach an event handler to an ancestor element(a delegate) which receives events of a specified type and handles them on behalf of its child elements (the delegators). The idea is that this cuts down on the number of registered handler functions required (giving a performance boost) and helps to reduce code complexity.

In addition to the terms 'delegate' and 'delegator' I will also use the term 'physical element' to refer to the element on which an event initially occurs upon. This may be the same as the delegator element but not NECESSARILY so. For example we may wish to listen to click events on a list element but the list element itself may contain numerous html elements on which the actual event occurs. Discussions on event delegation are not helped by the lack of any standard terminology and the foregoing terms are all my own.

Lets look at the following code example

	<div id='delegate'>
		<div>
			<div id='delegator'>
				<button id='physical'>
					press me
				</button>
			</div>
		</div>
	</div>

	
		$('#delegate').on('click', '#delegator', function (event) {
			console.log('event target id:',        event.target.id);
			console.log('event currentTarget id:', event.currentTarget.id);

		});

We attach an event handler using on() to the delegate element; here the root of the html snippet. The selector string specifies the delegator element on which we want to run the handler when the event bubbles up to it. The button represents our physical element which the user will click upon.

All our handler does is console out some information regarding the target and currentTarget properties of the event object which is passed to the handler.

When user clicks on the omega element the console logs are as follows:

event target id: physical
event currentTarget id: delegator


Target points to the physical element and currentTarget points to the delegator element, but we are not told about the delegator element. I find this behaviour surprising: It seems to go against the pattern of event delegation where there is a direct relationship between a delegator and a delegate. It seems to me that the physical element is not part of this abstraction and should be regarded as an implementation detail.

Nor is it hard to imagine how this lack of knowledge of the delegate could cause problems: Supposing we wished to create a list and use ED to handle clicks on the list elements. We would want to know the list element that was clicked on, but we would probably also find it useful to have the list element itself, and this event object would not tell us. At the same time, do we really care about the physical element that was clicked on if it's not the same as our delegator? If we did, we would have been better making that our delegator.

(By the way, if you think that you might get the delegate element through the 'this' keyword you'd be wrong: it also points to the delegator element.)

A better implementation would be for target to point to delegator element and currentTarget to point to the delegate, and, if we really, really wanted to access the physical element, this could also be included as well within the event object.

In fact jquery's event object does include a property called originalEvent and the delegate element can be accessed through this. This prevents a broken implementation but it's not the nicest.

Conclusion

Of course, working code is the most important thing and there's nothing intrinsically broken about the on() method and however wrong I might find its behaviour ( and many may find fault with my interpretation of the event delegation pattern), it is very clearly documented. Generally speaking though I do like my interfaces to be intuitive and to follow conventional patterns, and since it's unlikely that Jquery will change their implementation any time soon, I have created my own for my own personal utility library . As well as implementing the event interface in the way suggested above, it includes an originalEvent property (inspired by jquery) which allows you to access the physical element if you really need it.