[jQuery] [tooltip] Passing the mouseover event to the bodyhandler

[jQuery] [tooltip] Passing the mouseover event to the bodyhandler


Hi,
I made a small adjustment to the jQuery Tooltip plugin from
bassistance. The mouseover event is now passed to the bodyhandler,
this makes it easy to use event delegation of bubbling. You an for
example attach a tooltip to a TR instead of adding it to all TDs in
the TR.
The old way:
$('#mytable > tr.myclass > td').tooltip({
bodyHandler: function() {
var id = $(this).attr("id");
return CreateTooltip(id);
},
track: true
});
The new way:
$('#mytable > tr.myclass').tooltip({
bodyHandler: function(e) {
var id = $(e.target).attr("id");
return CreateTooltip(id);
},
track: true
});
Maybe Jörn Zaefferer can add this to a next release of the tooltip.
Regards,
Jochen
The code:
/*
* jQuery Tooltip plugin 1.3
*
* http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
* http://docs.jquery.com/Plugins/Tooltip
*
* Copyright (c) 2006 - 2008 Jörn Zaefferer
*
* $Id: jquery.tooltip.js 5741 2008-06-21 15:22:16Z joern.zaefferer $
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Changes by Jochen Jonckheere (c) 2009
* - Passing the mouseover event to the bodyhandler
*/
; (function($) {
// the tooltip element
var helper = {},
// the current tooltipped element
        current,
// the title of the current element, used for restoring
        title,
// timeout id for delayed tooltips
        tID,
// IE 5.5 or 6
        IE = $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent),
// flag for mouse tracking
        track = false;
$.tooltip = {
blocked: false,
defaults: {
delay: 200,
fade: false,
showURL: true,
extraClass: "",
top: 15,
left: 15,
id: "tooltip"
},
block: function() {
$.tooltip.blocked = !$.tooltip.blocked;
}
};
$.fn.extend({
tooltip: function(settings) {
settings = $.extend({}, $.tooltip.defaults, settings);
createHelper(settings);
return this.each(function() {
$.data(this, "tooltip", settings);
this.tOpacity = helper.parent.css("opacity");
// copy tooltip into its own expando and remove the
title
this.tooltipText = this.title;
$(this).removeAttr("title");
// also remove alt attribute to prevent default
tooltip in IE
this.alt = "";
})
                .mouseover(save)
                .mouseout(hide)
                .click(hide);
},
fixPNG: IE ? function() {
return this.each(function() {
var image = $(this).css('backgroundImage');
if (image.match(/^url\(["']?(.*\.png)["']?\)$/i)) {
image = RegExp.$1;
$(this).css({
'backgroundImage': 'none',
'filter':
"progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,
sizingMethod=crop, src='" + image + "')"
}).each(function() {
var position = $(this).css('position');
if (position != 'absolute' && position !=
'relative')
$(this).css('position', 'relative');
});
}
});
} : function() { return this; },
unfixPNG: IE ? function() {
return this.each(function() {
$(this).css({ 'filter': '', backgroundImage: '' });
});
} : function() { return this; },
hideWhenEmpty: function() {
return this.each(function() {
$(this)[$(this).html() ? "show" : "hide"]();
});
},
url: function() {
return this.attr('href') || this.attr('src');
}
});
function createHelper(settings) {
// there can be only one tooltip helper
if (helper.parent)
return;
// create the helper, h3 for title, div for url
helper.parent = $('<div id="' + settings.id + '"><h3></h3><div
class="body"></div><div class="url"></div></div>')
// add to document
            .appendTo(document.body)
// hide it at first
            .hide();
// apply bgiframe if available
if ($.fn.bgiframe)
helper.parent.bgiframe();
// save references to title and url elements
helper.title = $('h3', helper.parent);
helper.body = $('div.body', helper.parent);
helper.url = $('div.url', helper.parent);
}
function settings(element) {
return $.data(element, "tooltip");
}
// main event handler to start showing tooltips
function handle(event) {
// show helper, either with timeout or on instant
if (settings(this).delay)
tID = setTimeout(show, settings(this).delay);
else
show();
// if selected, update the helper position when the mouse
moves
track = !!settings(this).track;
$(document.body).bind('mousemove', update);
// update at least once
update(event);
}
// save elements title before the tooltip is displayed
function save(event) {
// if this is the current source, or it has no title (occurs
with click event), stop
if ($.tooltip.blocked || this == current || (!this.tooltipText
&& !settings(this).bodyHandler))
return;
// save current
current = this;
title = this.tooltipText;
if (settings(this).bodyHandler) {
helper.title.hide();
var bodyContent = settings(this).bodyHandler.call(this,
event);
if (bodyContent.nodeType || bodyContent.jquery) {
helper.body.empty().append(bodyContent)
} else {
helper.body.html(bodyContent);
}
helper.body.show();
} else if (settings(this).showBody) {
var parts = title.split(settings(this).showBody);
helper.title.html(parts.shift()).show();
helper.body.empty();
for (var i = 0, part; (part = parts[i]); i++) {
if (i > 0)
helper.body.append("<br/>");
helper.body.append(part);
}
helper.body.hideWhenEmpty();
} else {
helper.title.html(title).show();
helper.body.hide();
}
// if element has href or src, add and show it, otherwise hide
it
if (settings(this).showURL && $(this).url())
helper.url.html($(this).url().replace('http://', '')).show
();
else
helper.url.hide();
// add an optional class for this tip
helper.parent.addClass(settings(this).extraClass);
// fix PNG background for IE
if (settings(this).fixPNG)
helper.parent.fixPNG();
handle.apply(this, arguments);
}
// delete timeout and show helper
function show() {
tID = null;
if ((!IE || !$.fn.bgiframe) && settings(current).fade) {
if (helper.parent.is(":animated"))
helper.parent.stop().show().fadeTo(settings
(current).fade, current.tOpacity);
else
helper.parent.is(':visible') ? helper.parent.fadeTo
(settings(current).fade, current.tOpacity) : helper.parent.fadeIn
(settings(current).fade);
} else {
helper.parent.show();
}
update();
}
/**
* callback for mousemove
* updates the helper position
* removes itself when no current element
*/
function update(event) {
if ($.tooltip.blocked)
return;
if (event && event.target.tagName == "OPTION") {
return;
}
// stop updating when tracking is disabled and the tooltip is
visible
if (!track && helper.parent.is(":visible")) {
$(document.body).unbind('mousemove', update)
}
// if no current element is available, remove this listener
if (current == null) {
$(document.body).unbind('mousemove', update);
return;
}
// remove position helper classes
helper.parent.removeClass("viewport-right").removeClass
("viewport-bottom");
var left = helper.parent[0].offsetLeft;
var top = helper.parent[0].offsetTop;
if (event) {
// position the helper 15 pixel to bottom right, starting
from mouse position
left = event.pageX + settings(current).left;
top = event.pageY + settings(current).top;
var right = 'auto';
if (settings(current).positionLeft) {
right = $(window).width() - left;
left = 'auto';
}
helper.parent.css({
left: left,
right: right,
top: top
});
}
var v = viewport(),
            h = helper.parent[0];
// check horizontal position
if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
left -= h.offsetWidth + 20 + settings(current).left;
helper.parent.css({ left: left + 'px' }).addClass
("viewport-right");
}
// check vertical position
if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
top -= h.offsetHeight + 20 + settings(current).top;
helper.parent.css({ top: top + 'px' }).addClass("viewport-
bottom");
}
}
function viewport() {
return {
x: $(window).scrollLeft(),
y: $(window).scrollTop(),
cx: $(window).width(),
cy: $(window).height()
};
}
// hide helper and restore added classes and the title
function hide(event) {
if ($.tooltip.blocked)
return;
// clear timeout if possible
if (tID)
clearTimeout(tID);
// no more current element
current = null;
var tsettings = settings(this);
function complete() {
helper.parent.removeClass(tsettings.extraClass).hide().css
("opacity", "");
}
if ((!IE || !$.fn.bgiframe) && tsettings.fade) {
if (helper.parent.is(':animated'))
helper.parent.stop().fadeTo(tsettings.fade, 0,
complete);
else
helper.parent.stop().fadeOut(tsettings.fade,
complete);
} else
complete();
if (settings(this).fixPNG)
helper.parent.unfixPNG();
}
})(jQuery);