Binding Multiple Events to Reduce Redundancy with Event-Delegation Tooltips
read 11 commentsLast time I showed how to use event delegation to create a simple tooltip for a huge number of elements without running into the problem of binding an event handler to all of those elements. In this tutorial, I'm going to refine that tooltip script a bit, avoiding some code repetition and fixing a bug that someone pointed out in a comment.
For review, here is the final version of the script from the last post:
- var tipTitle = '';
- if ($link.length) {
- var link = $link[0];
- tipTitle = link.title;
- link.title = '';
- $('#livetip')
- })
- }
- if ($link.length) {
- }
- });
- }
- });
Bind Multiple Events at One Time
As I mentioned last time, this repeats code where it really shouldn't. For example, lines 5, 19, and 24 all check that moused-over element (or one of its ancestors) is a link. One way to reduce the repetition is to bind all three events at the same time (line 4):
- var tipTitle = '';
- if (!$link.length) { return; }
- var link = $link[0];
- });
- }
- tipTitle = link.title;
- link.title = '';
- $liveTip
- }
- if (tipTitle) {
- link.title = tipTitle;
- }
- }
- });
This modification relies on the type property of the event object, checking it to see which of the three event types were triggered and acting accordingly. That way, I can get away with writing the $link and link declarations and the link check one time instead of two or three.
Other changes
Here are a few other changes worth mentioning:
- Line 1 declares the
$livetipvariable while at the same time creating the tooltip div and appending it to the body. Now the script can refer to that variable rather than having to call$('#livetip')each time it is shown, moved, hidden, and so on. - Rather than wrap nearly everything in an
ifblock, I made the functionreturnif there is no link selected. Some people have a philosophical problem with multiple return points in a function, and it can make it hard to decipher and debug code sometimes, but here I think it's okay. - On "mouseout" (lines 23-28), the script is resetting
link.titletotipTitleonly iftipTitlehas a value. This, I'm hoping, fixes the problem reported by Moritz Peters of the tooltip not displaying correctly if you first mouse over a link before the document is ready.
Try the demo or download the zip (or both).
Adding a Delay
Tomorrow—for realz this time—I'll show how to add a short delay on mouseover before showing the tooltip.
P.S. You see the "$" in "$liveTip" and "$link"? There is nothing special about that—no special meaning given to "$" in JavaScript. It's just a convention that some jQuery folks have adopted to remind ourselves that the variable is holding a jQuery object.
Tweet















Yes, the problem is fixed. Very nice.
It didn't occur to me that the problem was just the mouseout event being fired before tipTitle was set. *head->wall* :)
Hello, I tried in IE8 but I had a bug regarding the href link. It does not want to link to #row999.
It works only when I am in compatibility mode (IE7)
Hi Nordes, that is a strange bug, indeed, but it doesn't appear to have anything to do with the script. This page with no JavaScript at all doesn't work either.
Turns out the problem occurs only when the IDs are on <tr> elements. I've moved them to the first <td> element of each row, and it seems to be working now. Thanks to Zach Leatherman for solving this riddle for me!
Who cares for the top most terrorizing (users and the Web) (pseudo-) browser… ???
Hi, could you explain to me the difference between variable link and $link? Why is the dollar sign by variable ($link). Where I would have something to read or learn about it ?
Thank you in advance for your reply
Hi Jirka,
There is nothing special about the "$" in the variable name. It is just a little reminder to me that I'm dealing with a jQuery object. It has become a convention of sorts among some jQuery develpers, while others don't really like it because of its potential to confuse people who are new to JavaScript, perhaps coming from a different programming language that treats "$" in a special way. I suppose your confusion over it is evidence on the side of those who would rather avoid that notation.
I see that you said.
if (!$link.length) { return; }Just to see if the link exists, if the whole script is based off of anchors would it be better to define the selector abit better ?
$('#myTable a')Actually, I'm intentionally not making the selector that specific. I discuss the reasoning behind the design in my previous post. In a nutshell, if there are thousands of links within the table, binding a click handler to all of them can really bog down the browser.
In this example, could .bind() be replaced by .delegate()?
Yes, absolutely. Of course, it couldn't when I wrote the article because .delegate() wasn't in the jQuery API at that point. But good to mention it now. Thanks.