Using JavaScript Event Delegation with JQuery

JavaScriptRecently I have been helping one of our clients to improve the performance of a particular section of their portal that shows in a set of tabs a huge list of items grouped by a set of categories, each item shows in a tool-tip a summary of it’s meaning/purpose… yes, jQuery is involved, and yes!, mouseenter/mouseleave or mouseover/mouseout is Involved too.. and yes… hold on.. JavaScript Event Delegation was involved??… event what??, ok, here we go.

The page looks like the next image:


One of the aspects I wanted to improve was the JavaScript code used to show the tool-tip on each of the items, why?, let’s take a look at the code:

$("my-path a[title]").live("mouseover",function(){
	// calling the plugin to show the tool-tip

Apparently, nothing wrong right?, a normal but old way to bind a mouseover event to an element, in this case to all links that match the jQuery selector  –> $(“my-path a[title]”), wait a minute, to all links??…  ooh no, you mean to all the 500+ links multiplied by 6 tabs, that is 3000+ items!! that is insane!!.

After a moment of shock I was determined to find a better way to handle that JavaScript code. I knew I needed a way to avoid listening to all the items (links) and instead listening only the parent  and when the parent detected a mouseenter/mouseleave event, then be able to determine if the user was in a link and then show up the tooltip; my teammates Iván Santiesteban and José (Pepe) Martínez point me in the right direction, they told me: use JavaScript Event Delegation.

I really recommend to read How JavaScript Event Delegation Works Written by David Walsh, in resume:

“Event delegation allows you to avoid adding event listeners to specific nodes;  instead, the event listener is added to one parent.”

In jQuery you can use .on() or .delegate(), all depends of your jQuery version, I had to use .delegate() since we use jQuery 1.6.x with that client, so, my new code looks like:

$j("#parent").delegate("a", "mouseenter", function(event) {
// more code here...
$j("#parent").delegate("a", "mouseleave", function() {
// more code here...

Now, I just have two listeners instead of 3000+!!. In my code I’m using mouseenter/mouseleave, you can use mouseover/mouseleave also, but be careful! all depends of your HTML and/or of the behavior you expected.

From jQuery .mouseenter() documentation:

“mouseover fires when the pointer moves into the child element as well, while mouseenter fires only when the pointer moves into the bound element.”

The performance of the page was increased dramatically in FF and response much better in IE7/8, still IE 7/8 sucks!.

I really hope you find this information useful.