1 |
/* |
2 |
* jQuery Tooltip plugin 1.3 |
3 |
* |
4 |
* http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/ |
5 |
* http://docs.jquery.com/Plugins/Tooltip |
6 |
* |
7 |
* Copyright (c) 2006 - 2008 Jörn Zaefferer |
8 |
* |
9 |
* $Id: jquery.tooltip.js 5741 2008-06-21 15:22:16Z joern.zaefferer $ |
10 |
* |
11 |
* Dual licensed under the MIT and GPL licenses: |
12 |
* http://www.opensource.org/licenses/mit-license.php |
13 |
* http://www.gnu.org/licenses/gpl.html |
14 |
*/ |
15 |
|
16 |
;(function($) { |
17 |
|
18 |
// the tooltip element |
19 |
var helper = {}, |
20 |
// the current tooltipped element |
21 |
current, |
22 |
// the title of the current element, used for restoring |
23 |
title, |
24 |
// timeout id for delayed tooltips |
25 |
tID, |
26 |
// IE 5.5 or 6 |
27 |
IE = $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent), |
28 |
// flag for mouse tracking |
29 |
track = false; |
30 |
|
31 |
$.tooltip = { |
32 |
blocked: false, |
33 |
defaults: { |
34 |
delay: 200, |
35 |
fade: false, |
36 |
showURL: true, |
37 |
extraClass: "", |
38 |
top: 15, |
39 |
left: 15, |
40 |
id: "tooltip" |
41 |
}, |
42 |
block: function() { |
43 |
$.tooltip.blocked = !$.tooltip.blocked; |
44 |
} |
45 |
}; |
46 |
|
47 |
$.fn.extend({ |
48 |
tooltip: function(settings) { |
49 |
settings = $.extend({}, $.tooltip.defaults, settings); |
50 |
createHelper(settings); |
51 |
return this.each(function() { |
52 |
$.data(this, "tooltip", settings); |
53 |
this.tOpacity = helper.parent.css("opacity"); |
54 |
// copy tooltip into its own expando and remove the title |
55 |
this.tooltipText = this.title; |
56 |
$(this).removeAttr("title"); |
57 |
// also remove alt attribute to prevent default tooltip in IE |
58 |
this.alt = ""; |
59 |
}) |
60 |
.mouseover(save) |
61 |
.mouseout(hide) |
62 |
.click(hide); |
63 |
}, |
64 |
fixPNG: IE ? function() { |
65 |
return this.each(function () { |
66 |
var image = $(this).css('backgroundImage'); |
67 |
if (image.match(/^url\(["']?(.*\.png)["']?\)$/i)) { |
68 |
image = RegExp.$1; |
69 |
$(this).css({ |
70 |
'backgroundImage': 'none', |
71 |
'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')" |
72 |
}).each(function () { |
73 |
var position = $(this).css('position'); |
74 |
if (position != 'absolute' && position != 'relative') |
75 |
$(this).css('position', 'relative'); |
76 |
}); |
77 |
} |
78 |
}); |
79 |
} : function() { return this; }, |
80 |
unfixPNG: IE ? function() { |
81 |
return this.each(function () { |
82 |
$(this).css({'filter': '', backgroundImage: ''}); |
83 |
}); |
84 |
} : function() { return this; }, |
85 |
hideWhenEmpty: function() { |
86 |
return this.each(function() { |
87 |
$(this)[ $(this).html() ? "show" : "hide" ](); |
88 |
}); |
89 |
}, |
90 |
url: function() { |
91 |
return this.attr('href') || this.attr('src'); |
92 |
} |
93 |
}); |
94 |
|
95 |
function createHelper(settings) { |
96 |
// there can be only one tooltip helper |
97 |
if( helper.parent ) |
98 |
return; |
99 |
// create the helper, h3 for title, div for url |
100 |
helper.parent = $('<div id="' + settings.id + '"><h3></h3><div class="body"></div><div class="url"></div></div>') |
101 |
// add to document |
102 |
.appendTo(document.body) |
103 |
// hide it at first |
104 |
.hide(); |
105 |
|
106 |
// apply bgiframe if available |
107 |
if ( $.fn.bgiframe ) |
108 |
helper.parent.bgiframe(); |
109 |
|
110 |
// save references to title and url elements |
111 |
helper.title = $('h3', helper.parent); |
112 |
helper.body = $('div.body', helper.parent); |
113 |
helper.url = $('div.url', helper.parent); |
114 |
} |
115 |
|
116 |
function settings(element) { |
117 |
return $.data(element, "tooltip"); |
118 |
} |
119 |
|
120 |
// main event handler to start showing tooltips |
121 |
function handle(event) { |
122 |
// show helper, either with timeout or on instant |
123 |
if( settings(this).delay ) |
124 |
tID = setTimeout(show, settings(this).delay); |
125 |
else |
126 |
show(); |
127 |
|
128 |
// if selected, update the helper position when the mouse moves |
129 |
track = !!settings(this).track; |
130 |
$(document.body).bind('mousemove', update); |
131 |
|
132 |
// update at least once |
133 |
update(event); |
134 |
} |
135 |
|
136 |
// save elements title before the tooltip is displayed |
137 |
function save() { |
138 |
// if this is the current source, or it has no title (occurs with click event), stop |
139 |
if ( $.tooltip.blocked || this == current || (!this.tooltipText && !settings(this).bodyHandler) ) |
140 |
return; |
141 |
|
142 |
// save current |
143 |
current = this; |
144 |
title = this.tooltipText; |
145 |
|
146 |
if ( settings(this).bodyHandler ) { |
147 |
helper.title.hide(); |
148 |
var bodyContent = settings(this).bodyHandler.call(this); |
149 |
if (bodyContent.nodeType || bodyContent.jquery) { |
150 |
helper.body.empty().append(bodyContent) |
151 |
} else { |
152 |
helper.body.html( bodyContent ); |
153 |
} |
154 |
helper.body.show(); |
155 |
} else if ( settings(this).showBody ) { |
156 |
var parts = title.split(settings(this).showBody); |
157 |
helper.title.html(parts.shift()).show(); |
158 |
helper.body.empty(); |
159 |
for(var i = 0, part; (part = parts[i]); i++) { |
160 |
if(i > 0) |
161 |
helper.body.append("<br/>"); |
162 |
helper.body.append(part); |
163 |
} |
164 |
helper.body.hideWhenEmpty(); |
165 |
} else { |
166 |
helper.title.html(title).show(); |
167 |
helper.body.hide(); |
168 |
} |
169 |
|
170 |
// if element has href or src, add and show it, otherwise hide it |
171 |
if( settings(this).showURL && $(this).url() ) |
172 |
helper.url.html( $(this).url().replace('http://', '') ).show(); |
173 |
else |
174 |
helper.url.hide(); |
175 |
|
176 |
// add an optional class for this tip |
177 |
helper.parent.addClass(settings(this).extraClass); |
178 |
|
179 |
// fix PNG background for IE |
180 |
if (settings(this).fixPNG ) |
181 |
helper.parent.fixPNG(); |
182 |
|
183 |
handle.apply(this, arguments); |
184 |
} |
185 |
|
186 |
// delete timeout and show helper |
187 |
function show() { |
188 |
tID = null; |
189 |
if ((!IE || !$.fn.bgiframe) && settings(current).fade) { |
190 |
if (helper.parent.is(":animated")) |
191 |
helper.parent.stop().show().fadeTo(settings(current).fade, current.tOpacity); |
192 |
else |
193 |
helper.parent.is(':visible') ? helper.parent.fadeTo(settings(current).fade, current.tOpacity) : helper.parent.fadeIn(settings(current).fade); |
194 |
} else { |
195 |
helper.parent.show(); |
196 |
} |
197 |
update(); |
198 |
} |
199 |
|
200 |
/** |
201 |
* callback for mousemove |
202 |
* updates the helper position |
203 |
* removes itself when no current element |
204 |
*/ |
205 |
function update(event) { |
206 |
if($.tooltip.blocked) |
207 |
return; |
208 |
|
209 |
if (event && event.target.tagName == "OPTION") { |
210 |
return; |
211 |
} |
212 |
|
213 |
// stop updating when tracking is disabled and the tooltip is visible |
214 |
if ( !track && helper.parent.is(":visible")) { |
215 |
$(document.body).unbind('mousemove', update) |
216 |
} |
217 |
|
218 |
// if no current element is available, remove this listener |
219 |
if( current == null ) { |
220 |
$(document.body).unbind('mousemove', update); |
221 |
return; |
222 |
} |
223 |
|
224 |
// remove position helper classes |
225 |
helper.parent.removeClass("viewport-right").removeClass("viewport-bottom"); |
226 |
|
227 |
var left = helper.parent[0].offsetLeft; |
228 |
var top = helper.parent[0].offsetTop; |
229 |
if (event) { |
230 |
// position the helper 15 pixel to bottom right, starting from mouse position |
231 |
left = event.pageX + settings(current).left; |
232 |
top = event.pageY + settings(current).top; |
233 |
var right='auto'; |
234 |
if (settings(current).positionLeft) { |
235 |
right = $(window).width() - left; |
236 |
left = 'auto'; |
237 |
} |
238 |
helper.parent.css({ |
239 |
left: left, |
240 |
right: right, |
241 |
top: top |
242 |
}); |
243 |
} |
244 |
|
245 |
var v = viewport(), |
246 |
h = helper.parent[0]; |
247 |
// check horizontal position |
248 |
if (v.x + v.cx < h.offsetLeft + h.offsetWidth) { |
249 |
left -= h.offsetWidth + 20 + settings(current).left; |
250 |
helper.parent.css({left: left + 'px'}).addClass("viewport-right"); |
251 |
} |
252 |
// check vertical position |
253 |
if (v.y + v.cy < h.offsetTop + h.offsetHeight) { |
254 |
top -= h.offsetHeight + 20 + settings(current).top; |
255 |
helper.parent.css({top: top + 'px'}).addClass("viewport-bottom"); |
256 |
} |
257 |
} |
258 |
|
259 |
function viewport() { |
260 |
return { |
261 |
x: $(window).scrollLeft(), |
262 |
y: $(window).scrollTop(), |
263 |
cx: $(window).width(), |
264 |
cy: $(window).height() |
265 |
}; |
266 |
} |
267 |
|
268 |
// hide helper and restore added classes and the title |
269 |
function hide(event) { |
270 |
if($.tooltip.blocked) |
271 |
return; |
272 |
// clear timeout if possible |
273 |
if(tID) |
274 |
clearTimeout(tID); |
275 |
// no more current element |
276 |
current = null; |
277 |
|
278 |
var tsettings = settings(this); |
279 |
function complete() { |
280 |
helper.parent.removeClass( tsettings.extraClass ).hide().css("opacity", ""); |
281 |
} |
282 |
if ((!IE || !$.fn.bgiframe) && tsettings.fade) { |
283 |
if (helper.parent.is(':animated')) |
284 |
helper.parent.stop().fadeTo(tsettings.fade, 0, complete); |
285 |
else |
286 |
helper.parent.stop().fadeOut(tsettings.fade, complete); |
287 |
} else |
288 |
complete(); |
289 |
|
290 |
if( settings(this).fixPNG ) |
291 |
helper.parent.unfixPNG(); |
292 |
} |
293 |
|
294 |
})(jQuery); |