123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- /**
- * Hovertip - easy and elegant tooltips
- *
- * By Dave Cohen <http://dave-cohen.com>
- * With ideas and and javascript code borrowed from many folks.
- * (See URLS in the comments)
- *
- * Licensed under GPL.
- * Requires jQuery.js. <http://jquery.com>,
- * 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:
- *
- * <p>blah blah blah
- * <span>important term</span>
- * <span class="tooltip">text that appears.</span>
- * blah blah blah</p>
- *
- * or,
- *
- * <p>blah blah blah
- * <span hovertip="termdefinition">important term</span>
- * blah blah blah</p>
- * <div id="termdefinition" class="hovertip"><h1>term definition</h1><p>the term means...</p></div>
- *
- * or,
- *
- * <p>blah blah blah
- * <span id="term">important term</span>
- * blah blah blah</p>
- * <div target="term" class="hovertip"><h1>term definition</h1><p>the term means...</p></div>
- *
- *
- * 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:
- * <span hovertip="ht1">target term</span>...
- * <div class="hovertip" id="ht1">tooltip text</div>
- */
- targetSelectById = function(el, config) {
- var id;
- var selector;
- if (id = el.getAttribute('id')) {
- selector = '*[@'+config.attribute+'=\''+id+'\']';
- return $(selector);
- }
- };
- /**
- * For this model:
- * <span id="ht1">target term</span>...
- * <div class="hovertip" target="ht1">tooltip text</div>
- */
- 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:
- * <span>target term</span><span class="hovertip">tooltip text</span>
- */
- 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("<a class='clicktip_close'><span>close</span></a>")
- .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):
- * <span clicktip="foo">target</span>...
- * <div id="foo" class="clicktip">blah blah</div>
- */
- window.setTimeout(function() {
- $('.clicktip').hovertipActivate(clicktipConfig,
- targetSelectById,
- clicktipPrepareWithCloseLink,
- clicktipTargetPrepare);
- }, 0);
-
- /**
- * To enable this style of markup (id on target):
- * <span id="foo">target</span>...
- * <div target="foo" class="clicktip">blah blah</div>
- */
- 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 <div class='hovertip'>blah blah</div>
- 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("<div class='hovertip_wrap0'><div class='hovertip_wrap1'><div class='hovertip_wrap2'>" +
- "</div></div></div>").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):
- * <span hovertip="foo">target</span>...
- * <div id="foo" class="hovertip">blah blah</div>
- */
- window.setTimeout(function() {
- $(hovertipSelect).hovertipActivate(hovertipConfig,
- targetSelectById,
- hovertipPrepare,
- hovertipTargetPrepare);
- }, 0);
- /**
- * To enable this style of markup (id on target):
- * <span id="foo">target</span>...
- * <div target="foo" class="hovertip">blah blah</div>
- */
- window.setTimeout(function() {
- $(hovertipSelect).hovertipActivate(hovertipConfig,
- targetSelectByTargetAttribute,
- hovertipPrepare,
- hovertipTargetPrepare);
- }, 0);
-
- /**
- * This next section enables this style of markup:
- * <foo><span>target</span><span class="hovertip">blah blah</span></foo>
- *
- * With drop shadow effect.
- *
- */
- var hovertipSpanSelect = 'span.hovertip';
- // activate hovertips with wrappers for FX (drop shadow):
- $(hovertipSpanSelect).css('display', 'block').addClass('hovertip_wrap3').
- wrap("<span class='hovertip_wrap0'><span class='hovertip_wrap1'><span class='hovertip_wrap2'>" +
- "</span></span></span>").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);
- }
|