This example demonstrates a lightweight and flexible setup for display of tooltips.
This displays the tooltip adjacent to the cursor
and takes advantage of the shim capabilities of Overlay
,
allowing the tooltip to properly display over select
elements in IE.
- Tooltips cover elements in IE.
Simple Tooltips
The Tooltip Markup
We just need a div
for the tooltip, and some elements that want to
have tooltips.
<div id="tooltip"></div> <ul class="list"> <li class="wrench"><img src="../assets/overlay/img/wrench.png"/></li> <li class="calipers"><img src="../assets/overlay/img/calipers.png"/></li> <li class="drill"><img src="../assets/overlay/img/drill.png"/></li> <li class="ohm"><img src="../assets/overlay/img/ohm.png"/></li> <li class="level"><img src="../assets/overlay/img/level.png"/></li> </ul>
Setting Up the YUI Instance
We'll use the Overlay
module to provide shimming for correctly covering
<select>
elements in IE. We'll use Event
for its onmouseleave
event, and
widget-anim
as a plugin to provide the fade-in for the tooltip.
YUI().use('overlay', 'event', 'widget-anim', function (Y) { // code will go here. });
Declare some variables
These variables include an array of strings for various tooltips.
If a DOM element has a class matching one of the name
values in the tipText
array,
it will display the corresponding text value in its tooltip when the cursor moves
over it.
var waitingToShow = false, // array for text to be displayed in tooltips tipText = [ {'name': 'wrench', 'text': "Avoid dropping on toe."}, {'name': 'calipers', 'text': 'Dial calipers: +- .001,<br>human hair .004'}, {'name': 'drill', 'text': 'Variable-speed and cordless too.'}, {'name': 'ohm', 'text': 'Never test microwaves with a volt-ohm meter.'}, {'name': 'level', 'text': 'Unreliable in zero gravity conditions.'} // the array continues... ];
Instantiating The Tooltip
To create an overlay instance for the tooltip,
we use the overlay constructor Y.Overlay
, specifying the source node
as the selector of the tooltip element.
var tooltip = new Y.Overlay({ srcNode: "#tooltip", visible: false }).plug(Y.Plugin.WidgetAnim); tooltip.anim.get('animHide').set('duration', 0.01); tooltip.anim.get('animShow').set('duration', 0.3); tooltip.render();
Event Handlers
Create event handlers for the mouse events and place them above the listeners code.
// handler that positions and shows the tooltip var onMousemove = function (e) { var i; if (tooltip.get('visible') === false) { // while it's still hidden, move the tooltip adjacent to the cursor Y.one('#tooltip').setStyle('opacity', '0'); tooltip.move([(e.pageX + 10), (e.pageY + 20)]); } if (waitingToShow === false) { // wait half a second, then show tooltip setTimeout(function(){ Y.one('#tooltip').setStyle('opacity', '1'); tooltip.show(); }, 500); // while waiting to show tooltip, don't let other // mousemoves try to show tooltip too. waitingToShow = true; // loop through the tipText array looking for a match between // the class name and the array literal `name` for (i = 0; i < tipText.length; i += 1) { if (e.currentTarget.hasClass(tipText[i].name)) { // found a match, so set the content in the tooltip's body tooltip.setStdModContent('body', tipText[i].text); break; } } } } // handler that hides the tooltip var onMouseleave = function (e) { // this check prevents hiding the tooltip // when the cursor moves over the tooltip itself if ((e.relatedTarget) && (e.relatedTarget.hasClass('yui3-widget-bd') === false)) { tooltip.hide(); waitingToShow = false; } }
Event Listeners
Add listeners for mousemove
and mouseout
events
to whatever elements you want to have tooltips.
Using mousemove
instead of mouseover
, and using a delay
in the transition
makes the tooltip fade in adjacent to the cursor.
See event delegation for efficient
event subscribing to multiple elements.
Y.delegate('mousemove', onMousemove, '.lists', 'li'); Y.delegate('mouseleave', onMouseleave, '.lists', 'li'); Y.one('#tooltip').on('mouseleave', onMouseleave);
This example demonstrates how you can use the existing Overlay component to create a one-off Tooltip for your page. If you plan to re-use the Tooltip on multiple pages, or in a variety of use cases, it's a good idea to encapsulate all the code which makes a tooltip work into a reusable Widget class. The example, Creating a Simple Tooltip Widget with Extensions, shows how you can create a reusable, flexible Tooltip class.
Complete Example Source
<style> .example .lists { margin: 10px auto; /*center in viewport*/ } .example .list { -moz-padding-start: 0; -webkit-padding-start: 0; width: 300px; margin: 0; } .example #tooltip .yui3-widget-bd{ text-align: left; max-width: 15em; *width: 10em; background-color: #FFF6D5; border: solid 1px #aa8; padding: 0.2em 0.5em 0.3em; -moz-border-radius: 2px; -webkit-border-radius: 2px; -moz-box-shadow: 3px 3px 5px rgba(0,0,0,0.2); -webkit-box-shadow: 3px 3px 5px rgba(0,0,0,0.2); } .example .list li{ list-style: none; margin: 0 0 20px; border: 1px solid #C9C9C9; width: 300px; } .example .list img{ vertical-align: bottom; } .example .list .select{ padding: 1.5em 0 0.5em; text-indent: 0.5em; background-color: #F7DBB2; } </style> <body class="yui3-skin-sam"> <div id="tooltip"></div> <div class="yui3-g lists"> <div class="yui3-u-1-2"> <!-- see CSS Grids --> <ul class="list"> <li class="wrench"><img src="../assets/overlay/img/wrench.png"></li> <li class="calipers"><img src="../assets/overlay/img/calipers.png"/></li> <li class="drill"><img src="../assets/overlay/img/drill.png"/></li> <li class="ohm"><img src="../assets/overlay/img/ohm.png"/></li> <li class="level"><img src="../assets/overlay/img/level.png"/></li> </ul> </div> <div class="yui3-u"> <ul class="list"> <li class="endwrench"><img src="../assets/overlay/img/endwrench.png"/></li> <li class="knife"><img src="../assets/overlay/img/knife.png"/></li> <li class="scissors"><img src="../assets/overlay/img/scissors.png"/></li> <li class="screwdriver"><img src="../assets/overlay/img/screwdriver.png"/></li> <li class="tape"><img src="../assets/overlay/img/tape.png"/></li> <li class="select">Tooltips cover <select><option>select</option></select> elements in IE.</li> </ul> </div> </div> <script> YUI().use('overlay', 'event', 'widget-anim', function (Y) { var waitingToShow = false, // array for text to be displayed in tooltips tipText = [ {'name': 'wrench', 'text': "Avoid dropping on toe."}, {'name': 'calipers', 'text': 'Dial calipers: +- .001,<br>human hair .004'}, {'name': 'drill', 'text': 'Variable-speed and cordless too.'}, {'name': 'ohm', 'text': 'Never test microwaves with a volt-ohm meter.'}, {'name': 'level', 'text': 'Unreliable in zero gravity conditions.'}, {'name': 'endwrench', 'text': '11/16 box-end wrench A.K.A spanner - (British)'}, {'name': 'knife', 'text': 'Wants to roll off table and stick in foot.'}, {'name': 'scissors', 'text': "Don't run with these."}, {'name': 'screwdriver', 'text': 'Not intended for garden weeding.'}, {'name': 'tape', 'text': 'Remove before cutting.'}, {'name': 'select', 'text': 'Covering select'} ]; var tooltip = new Y.Overlay({ srcNode: "#tooltip", visible: false }).plug(Y.Plugin.WidgetAnim); tooltip.anim.get('animHide').set('duration', 0.01); tooltip.anim.get('animShow').set('duration', 0.3); tooltip.render(); // handler that positions and shows the tooltip var onMousemove = function (e) { var i; if (tooltip.get('visible') === false) { // while it's still hidden, move the tooltip adjacent to the cursor Y.one('#tooltip').setStyle('opacity', '0'); tooltip.move([(e.pageX + 10), (e.pageY + 20)]); } if (waitingToShow === false) { // wait half a second, then show tooltip setTimeout(function(){ Y.one('#tooltip').setStyle('opacity', '1'); tooltip.show(); }, 500); // while waiting to show tooltip, don't let other // mousemoves try to show tooltip too. waitingToShow = true; // loop through the tipText array looking for a match between // the class name and the array literal `name` for (i = 0; i < tipText.length; i += 1) { if (e.currentTarget.hasClass(tipText[i].name)) { // found a match, so set the content in the tooltip's body tooltip.setStdModContent('body', tipText[i].text); break; } } } } // handler that hides the tooltip var onMouseleave = function (e) { // this check prevents hiding the tooltip // when the cursor moves over the tooltip itself if ((e.relatedTarget) && (e.relatedTarget.hasClass('yui3-widget-bd') === false)) { tooltip.hide(); waitingToShow = false; } } Y.delegate('mousemove', onMousemove, '.lists', 'li'); Y.delegate('mouseleave', onMouseleave, '.lists', 'li'); Y.one('#tooltip').on('mouseleave', onMouseleave); }); </script> </body>