Binding Multiple Events to Reduce Redundancy with Event-Delegation Tooltips
Last 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:
[js]$('').hide().appendTo('body'); var tipTitle = ''; $('#mytable').bind('mouseover', function(event) { var $link = $(event.target).closest('a'); if ($link.length) { var link = $link[0]; tipTitle = link.title; link.title = ''; $('#livetip') .css({ top: event.pageY + 12, left: event.pageX + 12 }) .html('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):
[js]var $liveTip = $('').hide().appendTo('body'); var tipTitle = ''; $('#mytable').bind('mouseover mouseout mousemove', function(event) { var $link = $(event.target).closest('a'); if (!$link.length) { return; } var link = $link[0]; if (event.type == 'mouseover' || event.type == 'mousemove') { $liveTip.css({ top: event.pageY + 12, left: event.pageX + 12 }); } if (event.type == 'mouseover') { tipTitle = link.title; link.title = ''; $liveTip .html('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
$livetip
variable 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
if
block, I made the functionreturn
if 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.title
totipTitle
only iftipTitle
has 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.