/** * Hovertip - easy and elegant tooltips * * By Dave Cohen * With ideas and and javascript code borrowed from many folks. * (See URLS in the comments) * * Licensed under GPL. * Requires jQuery.js. , * which may be distributed under a different licence. * * $Date: 2006-09-15 12:49:19 -0700 (Fri, 15 Sep 2006) $ * $Rev: $ * $Id:$ * * This plugin helps you create tooltips. It supports: * * hovertips - these appear under the mouse when mouse is over the target * element. * * clicktips - these appear in the document when the target element is * clicked. * * You may define behaviors for additional types of tooltips. * * There are a variety of ways to add tooltips. Each of the following is * supported: * *

blah blah blah * important term * text that appears. * blah blah blah

* * or, * *

blah blah blah * important term * blah blah blah

*

term definition

the term means...

* * or, * *

blah blah blah * important term * blah blah blah

*

term definition

the term means...

* * * Hooks are available to customize both the behavior of activated tooltips, * and the syntax used to mark them up. * */ //// mouse events //// /** * To make hovertips appear correctly we need the exact mouse position. * These functions make that possible. */ // use globals to track mouse position var hovertipMouseX; var hovertipMouseY; function hovertipMouseUpdate(e) { var mouse = hovertipMouseXY(e); hovertipMouseX = mouse[0]; hovertipMouseY = mouse[1]; } // http://www.howtocreate.co.uk/tutorials/javascript/eventinfo function hovertipMouseXY(e) { if( !e ) { if( window.event ) { //Internet Explorer e = window.event; } else { //total failure, we have no way of referencing the event return; } } if( typeof( e.pageX ) == 'number' ) { //most browsers var xcoord = e.pageX; var ycoord = e.pageY; } else if( typeof( e.clientX ) == 'number' ) { //Internet Explorer and older browsers //other browsers provide this, but follow the pageX/Y branch var xcoord = e.clientX; var ycoord = e.clientY; var badOldBrowser = ( window.navigator.userAgent.indexOf( 'Opera' ) + 1 ) || ( window.ScriptEngine && ScriptEngine().indexOf( 'InScript' ) + 1 ) || ( navigator.vendor == 'KDE' ); if( !badOldBrowser ) { if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) { //IE 4, 5 & 6 (in non-standards compliant mode) xcoord += document.body.scrollLeft; ycoord += document.body.scrollTop; } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) { //IE 6 (in standards compliant mode) xcoord += document.documentElement.scrollLeft; ycoord += document.documentElement.scrollTop; } } } else { //total failure, we have no way of obtaining the mouse coordinates return; } return [xcoord, ycoord]; } //// target selectors //// /** * These selectors find the targets for a given tooltip element. * Several methods are supported. * * You may write your own selector functions to customize. */ /** * For this model: * target term... *
tooltip text
*/ targetSelectById = function(el, config) { var id; var selector; if (id = el.getAttribute('id')) { selector = '*[@'+config.attribute+'=\''+id+'\']'; return $(selector); } }; /** * For this model: * target term... *
tooltip text
*/ targetSelectByTargetAttribute = function(el, config) { target_list = el.getAttribute('target'); if (target_list) { // use for attribute to specify targets target_ids = target_list.split(' '); var selector = '#' + target_ids.join(',#'); return $(selector); } }; /** * For this model: * target termtooltip text */ targetSelectByPrevious = function(el, config) { return $(el.previousSibling); } /** * Make all siblings targets. Experimental. */ targetSelectBySiblings = function(el, config) { return $(el).siblings(); } //// prepare tip elements //// /** * The tooltip element needs special preparation. You may define your own * prepare functions to cusomize the behavior. */ // adds a close link to clicktips clicktipPrepareWithCloseLink = function(o, config) { return o.append("close") .find('a.clicktip_close').click(function(e) { o.hide(); return false; }).end(); }; // ensure that hovertips do not disappear when the mouse is over them. // also position the hovertip as an absolutely positioned child of body. hovertipPrepare = function(o, config) { return o.hover(function() { hovertipHideCancel(this); }, function() { hovertipHideLater(this); }).css('position', 'absolute').each(hovertipPosition); }; // do not modify tooltips when preparing hovertipPrepareNoOp = function(o, config) { return o; } //// manipulate tip elements ///// /** * A variety of functions to modify tooltip elements */ // move tooltips to body, so they are not descended from other absolutely // positioned elements. hovertipPosition = function(i) { document.body.appendChild(this); } hovertipIsVisible = function(el) { return (jQuery.css(el, 'display') != 'none'); } // show the tooltip under the mouse. // Introduce a delay, so tip appears only if cursor rests on target for more than an instant. hovertipShowUnderMouse = function(el) { hovertipHideCancel(el); if (!hovertipIsVisible(el)) { el.ht.showing = // keep reference to timer window.setTimeout(function() { el.ht.tip.css({ 'position':'absolute', 'top': hovertipMouseY + 'px', 'left': hovertipMouseX + 'px'}) .show(); }, el.ht.config.showDelay); } }; // do not hide hovertipHideCancel = function(el) { if (el.ht.hiding) { window.clearTimeout(el.ht.hiding); el.ht.hiding = null; } }; // Hide a tooltip, but only after a delay. // The delay allow the tip to remain when user moves mouse from target to tooltip hovertipHideLater = function(el) { if (el.ht.showing) { window.clearTimeout(el.ht.showing); el.ht.showing = null; } if (el.ht.hiding) { window.clearTimeout(el.ht.hiding); el.ht.hiding = null; } el.ht.hiding = window.setTimeout(function() { if (el.ht.hiding) { // fadeOut, slideUp do not work on Konqueror el.ht.tip.hide(); } }, el.ht.config.hideDelay); }; //// prepare target elements //// /** * As we prepared the tooltip elements, the targets also need preparation. * * You may define your own custom behavior. */ // when clicked on target, toggle visibilty of tooltip clicktipTargetPrepare = function(o, el, config) { return o.addClass(config.attribute + '_target') .click(function() { el.ht.tip.toggle(); return false; }); }; // when hover over target, make tooltip appear hovertipTargetPrepare = function(o, el, config) { return o.addClass(config.attribute + '_target') .hover(function() { // show tip when mouse over target hovertipShowUnderMouse(el); }, function() { // hide the tip // add a delay so user can move mouse from the target to the tip hovertipHideLater(el); }); }; /** * hovertipActivate() is our jQuery plugin function. It turns on hovertip or * clicktip behavior for a set of elements. * * @param config * controls aspects of tooltip behavior. Be sure to define * 'attribute', 'showDelay' and 'hideDelay'. * * @param targetSelect * function finds the targets of a given tooltip element. * * @param tipPrepare * function alters the tooltip to display and behave properly * * @param targetPrepare * function alters the target to display and behave properly. */ jQuery.fn.hovertipActivate = function(config, targetSelect, tipPrepare, targetPrepare) { //alert('activating ' + this.size()); // unhide so jquery show/hide will work. return this.css('display', 'block') .hide() // don't show it until click .each(function() { if (!this.ht) this.ht = new Object(); this.ht.config = config; // find our targets var targets = targetSelect(this, config); if (targets && targets.size()) { if (!this.ht.targets) this.ht.targets = targetPrepare(targets, this, config); else this.ht.targets.add(targetPrepare(targets, this, config)); // listen to mouse move events so we know exatly where to place hovetips targets.mousemove(hovertipMouseUpdate); // prepare the tooltip element // is it bad form to call $(this) here? if (!this.ht.tip) this.ht.tip = tipPrepare($(this), config); } }) ; }; /** * Here's an example ready function which shows how to enable tooltips. * * You can make this considerably shorter by choosing only the markup style(s) * you will use. * * You may also remove the code that wraps hovertips to produce drop-shadow FX * * Invoke this function or one like it from your $(document).ready(). * * Here, we break the action up into several timout callbacks, to avoid * locking up browsers. */ function hovertipInit() { // specify the attribute name we use for our clicktips var clicktipConfig = {'attribute':'clicktip'}; /** * To enable this style of markup (id on tooltip): * target... *
blah blah
*/ window.setTimeout(function() { $('.clicktip').hovertipActivate(clicktipConfig, targetSelectById, clicktipPrepareWithCloseLink, clicktipTargetPrepare); }, 0); /** * To enable this style of markup (id on target): * target... *
blah blah
*/ window.setTimeout(function() { $('.clicktip').hovertipActivate(clicktipConfig, targetSelectByTargetAttribute, clicktipPrepareWithCloseLink, clicktipTargetPrepare); }, 0); // specify our configuration for hovertips, including delay times (millisec) var hovertipConfig = {'attribute':'hovertip', 'showDelay': 300, 'hideDelay': 700}; // use
blah blah
var hovertipSelect = 'div.hovertip'; // OPTIONAL: here we wrap each hovertip to apply special effect. (i.e. drop shadow): $(hovertipSelect).css('display', 'block').addClass('hovertip_wrap3'). wrap("
" + "
").each(function() { // fix class and attributes for newly wrapped elements var tooltip = this.parentNode.parentNode.parentNode; if (this.getAttribute('target')) tooltip.setAttribute('target', this.getAttribute('target')); if (this.getAttribute('id')) { var id = this.getAttribute('id'); this.removeAttribute('id'); tooltip.setAttribute('id', id); } }); hovertipSelect = 'div.hovertip_wrap0'; // end optional FX section /** * To enable this style of markup (id on tooltip): * target... *
blah blah
*/ window.setTimeout(function() { $(hovertipSelect).hovertipActivate(hovertipConfig, targetSelectById, hovertipPrepare, hovertipTargetPrepare); }, 0); /** * To enable this style of markup (id on target): * target... *
blah blah
*/ window.setTimeout(function() { $(hovertipSelect).hovertipActivate(hovertipConfig, targetSelectByTargetAttribute, hovertipPrepare, hovertipTargetPrepare); }, 0); /** * This next section enables this style of markup: * targetblah blah * * With drop shadow effect. * */ var hovertipSpanSelect = 'span.hovertip'; // activate hovertips with wrappers for FX (drop shadow): $(hovertipSpanSelect).css('display', 'block').addClass('hovertip_wrap3'). wrap("" + "").each(function() { // fix class and attributes for newly wrapped elements var tooltip = this.parentNode.parentNode.parentNode; if (this.getAttribute('target')) tooltip.setAttribute('target', this.getAttribute('target')); if (this.getAttribute('id')) { var id = this.getAttribute('id'); this.removeAttribute('id'); tooltip.setAttribute('id', id); } }); hovertipSpanSelect = 'span.hovertip_wrap0'; window.setTimeout(function() { $(hovertipSpanSelect) .hovertipActivate(hovertipConfig, targetSelectByPrevious, hovertipPrepare, hovertipTargetPrepare); }, 0); }