Just the weekly tutorials.

How to Create a Mouse Hover Tooltip with jQuery

Although my jQuery tutorial book explains plugin creation in detail, this tutorial is completely unique, nor has it been published anywhere else.

Welcome to the first tutorial in the year 2013. I want to kick it off with an example that will demonstrate "Creation of a jQuery Plugin". The idea is simple. We are going to create tool tips using CSS styles and attach them to a number of chosen HTML elements.

A "tool tip" is a message that appears in a small rectangle when you hover over an element with the mouse pointer. The tool tip becomes visible when the mouse is over an element that has the tool tip attached. And it disappears when the mouse leaves the element.

However, while within the area of the element the tool tip must smoothly follow the mouse pointer. In order to achieve this bit of functionality we will have to learn how to track mouse position using jQuery.

Our goal is to be able to name and attach such a tool tip to an HTML element of our choice, or a set of multiple elements.

tool tips are part of User Interface design. They greatly improve usability of your navigation bar or custom-made buttons by providing extra meaning to the user as to what each button or menu option does after it is clicked. Or by offering miscellaneous description of an element.

Let's start by determining what our plugin will accomplish:

The plugin should be easy to use. We want to select HTML elements using the regular jQuery selector such as $("div") or $("img#id") and provide the tool tip text.

Let's name our plugin "tooltip" and have it take one parameter -- the tool tip text itself:

$("div").tooltip("Hovering over a div"); $("img#owl").tooltip("I am an owl.");

Note: of course running this code without first creating the plugin "tool tip" will not produce any results. It's not part of the jQuery framework. And that's the whole point of writing plugins -- to extend the functionality of jQuery. This way you can also share your work with others. Your plugin can be downloaded by anyone else and they can use in their own projects without writing much code.

Ideally after running the code displayed above, all <DIV> elements should have a tool tip that will display the message "Hovering over a div" when the mouse is moved into the area of the selected <DIV> elements. And in the same way, the image whose id is #owl will display the tool tip "I am an owl." on the mouse over event.

It looks like it could be a simple, yet versatile tool tip plugin. Let's create it.

The HTML and CSS

First, we will need to design the tool tip in HTML. The tool tip element itself is very easy. It consists of an empty DIV element and nothing more. The tool tip <DIV> will be populated with text as the mouse hovers over various elements. It will also follow the mouse cursor.

<div id = "tooltip"></div>

That was easy. Notice that this will be the universal tool tip <DIV> used for all elements. This is because we can only display one tool tip at a time. This is also why this div will be originally set to display:none. This way it is hidden by default when the page loads. The plugin code we will write later on will take care of the tool tip's state and position (following the mouse.)

Notice that we will set display:inline to make it visible, not display:block. This allows us to have a tool tip that will auto-scale to the width of the custom text entered into it. As a side-note, if at this time you have on idea what the difference is between inline and block styles I strongly suggest you look that up now. This will help you understand how HTML elements are affected by their display style.

Now let's add rounded corners and a shadow to our tool tip HTML using CSS. Very basic stuff. Let's give the background color a slightly yellow tint. Yours of course can be any other color:

#tooltip { width: auto; font-family: Arial; font-size: 14px; color: gray; background: #FFFFEE; /* Slightly yellow background */ border-radius: 5px; /* Rounded corners */ box-shadow: 5px 5px 10px #DDD; /* tool tip shadow */ z-index: 2147483647; /* Highest value available */ }

Dealing with Large z-index:

Notice that the z-index is set to a very high number. The tool tip is different from any other UI element in that it must be the topmost element at any given moment. As a rule, tool tips are never displayed below any other element, so we set the z-index to a high number.

The maximum value for z-index in most browsers is 2147483647, but we don't need to go that far. When this value is exceeded, most browsers stop at the maximum value. However, Firefox 3 will reset the value to 0, and it may not produce the desired result. Be careful. An earlier version of Safari (3) stops at 16777271.

Even when working with many elements, keep your z-index within reasonable values to avoid browser limitations. I keep mine between 1 to 100,000. Long numbers can be hard to read. Simply choose what the highest z-index across your entire application should be.

However...when working with a plugin, we must assume that it can be used in a foreign application, not written by us. What if the authors of that application use high z-index (for whatever reasons) that go beyond 100,000? Therefore, when writing a custom plugin that deals with element layers (such as our tool tip plugin) we need to ensure to set z-index to the highest possible value 2147483647.

The Target Element div#target

The examples below will walk you through building your own plugin. For the sake of simplicity, I will work with an imaginary "div#target" element. But later in the last section...and within the actual plugin we will hook the code up to the elements selected by our jQuery script.

Tracking the Mouse Movement

Before we jump into the code that enables toggling the tool tip on and off when the mouse enters or leaves the element (to which a tool tip has been attached) let's first take a look at how we can make the tool tip follow the mouse cursor.

One way of tracking the x/y position of the mouse pointer over an element would be to attach the mousemove event to the target element:

$("div#target").mousemove(function(event) { // Our custom code... var x = event.pageX; // get mouse X position relative to the page (screen) var y = event.pageY; // get mouse Y position // You don't really want to use straight x/y values from the event data // You want to place the tool tip slightly away from the cursor x = x + 32; // move it to the right from the cursor y = y - 16; // move it up /* Reset the x/y position of the tool tip element */ $("#tooltip).css( {left: x, top: y} ); });

If you think that this code should be just copy and pasted into your website to be plugged in like a lego block. . . stop right there. It's not worth learning jQuery if this is your approach.

The event parameter is the data that passed from our Operating System to the browser, and finally to your application. And finally, into the custom code we will write, so we can work with that data. But what is stored in there?

The event data we will receive varies depending on the type of the event we are working with (in this case it is mousemove.)

In the case of mousemove event, the event data will contain the mouse x and y position. Exactly what we need. We can use it to identify the current mouse position during the execution of this event.

The mousemove is a jQuery method (like many others: css, animate, fadeIn, fadeOut, etc.) In this cause the method mousemove is used to attach a JavaScript event to the HTML element selected as div#target.

The code function() { ... } is an inline, anonymous (nameless) function. Between its brackets you will place the code which will modify the selected (in this example) element div#target.

This is the proper way of thinking about this. Never copy and paste code that you don't understand.

Using "on" and "off" jQuery Methods

The example above utilizes the "legacy" code that will still work, but there are better ways.

The latest and future versions of jQuery suggest that the (relatively) new methods .on and .off should be used to attach events to elements.

So, instead of

$("div#target").mousemove(function() { /* custom code */ });

Let's write it as

$("div#target").on("mousemove", function() { /* custom code */ });

And, in the future, to deactivate the event

$("div#target").off("mousemove"); // don't have to specify anonymous function

And just for fun. What if we wanted to deactivate any and all events that were ever attached to an HTML element div#target? Simply skip the parameters:

$("div#target").off(); // remove absolutely all events attached to this element

MouseOver and MouseOut Mouse Events

In the previous section we covered the mousemove (the equivalent of onMouseMove in native JavaScript) event. It helped us with making the tool tip follow the mouse cursor. But we don't need to move the tool tip with the mouse all of the time.

The tool tip is not always visible on the screen. Only when the targeted elements are hovered. Therefore we need a way of knowing three more things:

One thing you should know about events is that you need to turn them off (stop listening to) when they are unnecessary. Imagine tracking the mouse position when the tool tip is not even visible? Even though we don't really have to write the code to add this detail, it is good if we do.

Every time we attach any kind of an event to any HTML element we take up computer memory doing that. By turning an event off (stopping listening to the event) we release computer memory. It is your responsibility as a programmer to do this.

You see, mousemove event is really only needed when the tool tip is visible. Therefore we can enable it when the tool tip is shown, and disable it when it is hidden.

As discussed in the previous section, we can use .on and .off methods to attach and remove event listeners. Let's add the following two events to the target element. And let's also combine the mousemove with mouseover and mouseout events. This will take care of releasing memory allocated for processing mousemove event when the tool tip becomes invisible.

// Mouse enters the target element $("div#target").on("mouseover", function() { // Make the tool tip visible $("#tooltip).css("display", "inline"); // Start listening to the mousemove event, memory is allocated for it $("div#target").on("mousemove", function(event) { var x = event.pageX; // get mouse X position relative to the page (screen) var y = event.pageY; // get mouse Y position x = x + 32; // move it to the right from the cursor y = y - 16; // move it up $("#tooltip).css( {left: x, top: y} ); }); }); // Mouse leaves the target element $("div#target").off("mouseout", function() { // Hide the tool tip $("#tooltip).css("display", "none"); // Stop listening to the mousemove event, memory is released $("this").off("mousemove"); });

Not all events must be released. Some events are designed to be active during the lifetime of your application. The events mouseover and mouseout are such events in this example. They are always active. The memory will be released when the user closes the browser tab your application is in, automatically.

Building the Tool Tip Plugin: Putting It All Together.

On page 169 of my jQuery PDF Tutorial E-Book I explain how, in order to create a jQuery plugin, all we need to do is to extend the functionality of the main jQuery object ($ or jQuery) using either the "fn" or "prototype" property (which are one and the same) with our own method.

This is the barebone construction method for creating plugins. Let's create one and name it "tooltip":

$.fn.tooltip = function(tool_tip_text) { /* Plugin code will be written here.. This is the place where magic will happen. */ var selected_elements = this; }

Within the plugin the this object will refer to one or more (an array of) elements that were selected using the jQuery selector $("div#target"). This is the part that selects the element we want to apply the tool tip to.

Note that the code above will create a plugin that can be executed as:

$("div#target").tooltip("Target Div");

This will attach the tool tip with the text "Target Div" to element target#div. But what will go into the custom code section scoped by the anonymous function? Well that is the code we have to write.

Let's take everything we learned in this tutorial and put it together into a working plugin:

$.fn.tooltip = function(tool_tip_text) { // Mouse enters the target element $(this).on("mouseover", function() { // Make the tool tip visible $("#tooltip).css("display", "inline"); // Start listening to the mousemove event, memory is allocated for it $(this).on("mousemove", function(event) { var x = event.pageX; // get mouse X position relative to the page (screen) var y = event.pageY; // get mouse Y position x = x + 32; // move it to the right from the cursor y = y - 16; // move it up $("#tooltip).css( {left: x, top: y} ); }); }); // Mouse leaves the target element $(this).off("mouseout", function() { // Hide the tool tip $("#tooltip).css("display", "none"); // Stop listening to the mousemove event, memory is released $(this).off("mousemove"); }); // And finally... hide tool tip on mouse out $(this).on("mouseout", function() { // Hide the tool tip $("#tooltip).css("display", "none"); } }

The only thing that changed was moving away from the imaginary div#target that we used earlier... and replacing it with the "this" object. Within the plugin the "this" object will refer to selected elements. That's why we now apply the code to the "this" object instead.

To learn more about jQuery check out my tutorial book which is available from the homepage on this site. And here is the demo...

Mouseover Tool Tip Demo

The live working demo of the plugin.

www.mobilejquery.net/demo/demo-1-tool tip.html

Just the weekly tutorials.