Rev 3553 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3553 | bpr | 1 | /* This notice must be untouched at all times. |
2 | Copyright (c) 2002-2008 Walter Zorn. All rights reserved. |
||
3 | |||
4 | wz_tooltip.js v. 5.3 |
||
5 | |||
6 | The latest version is available at |
||
7 | http://www.walterzorn.com |
||
8 | or http://www.devira.com |
||
9 | or http://www.walterzorn.de |
||
10 | |||
11 | Created 1.12.2002 by Walter Zorn (Web: http://www.walterzorn.com ) |
||
12 | Last modified: 7.10.2008 |
||
13 | |||
14 | Easy-to-use cross-browser tooltips. |
||
15 | Just include the script at the beginning of the <body> section, and invoke |
||
16 | Tip('Tooltip text') to show and UnTip() to hide the tooltip, from the desired |
||
17 | HTML eventhandlers. Example: |
||
18 | <a onmouseover="Tip('Some text')" onmouseout="UnTip()" href="index.htm">My home page</a> |
||
19 | No container DIV required. |
||
20 | By default, width and height of tooltips are automatically adapted to content. |
||
21 | Is even capable of dynamically converting arbitrary HTML elements to tooltips |
||
22 | by calling TagToTip('ID_of_HTML_element_to_be_converted') instead of Tip(), |
||
23 | which means you can put important, search-engine-relevant stuff into tooltips. |
||
24 | Appearance & behaviour of tooltips can be individually configured |
||
25 | via commands passed to Tip() or TagToTip(). |
||
26 | |||
27 | Tab Width: 4 |
||
28 | LICENSE: LGPL |
||
29 | |||
30 | This library is free software; you can redistribute it and/or |
||
31 | modify it under the terms of the GNU Lesser General Public |
||
32 | License (LGPL) as published by the Free Software Foundation; either |
||
33 | version 2.1 of the License, or (at your option) any later version. |
||
34 | |||
35 | This library is distributed in the hope that it will be useful, |
||
36 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
37 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
38 | |||
39 | For more details on the GNU Lesser General Public License, |
||
40 | see http://www.gnu.org/copyleft/lesser.html |
||
41 | */ |
||
42 | |||
43 | var config = new Object(); |
||
44 | |||
45 | |||
46 | //=================== GLOBAL TOOPTIP CONFIGURATION =========================// |
||
47 | var tt_Debug = true // false or true - recommended: false once you release your page to the public |
||
48 | var tt_Enabled = true // Allows to (temporarily) suppress tooltips, e.g. by providing the user with a button that sets this global variable to false |
||
49 | var TagsToTip = true // false or true - if true, HTML elements to be converted to tooltips via TagToTip() are automatically hidden; |
||
50 | // if false, you should hide those HTML elements yourself |
||
51 | |||
52 | // For each of the following config variables there exists a command, which is |
||
53 | // just the variablename in uppercase, to be passed to Tip() or TagToTip() to |
||
54 | // configure tooltips individually. Individual commands override global |
||
55 | // configuration. Order of commands is arbitrary. |
||
56 | // Example: onmouseover="Tip('Tooltip text', LEFT, true, BGCOLOR, '#FF9900', FADEIN, 400)" |
||
57 | |||
58 | config. Above = false // false or true - tooltip above mousepointer |
||
59 | config. BgColor = '#E2E7FF' // Background colour (HTML colour value, in quotes) |
||
60 | config. BgImg = '' // Path to background image, none if empty string '' |
||
61 | config. BorderColor = '#003099' |
||
62 | config. BorderStyle = 'solid' // Any permitted CSS value, but I recommend 'solid', 'dotted' or 'dashed' |
||
63 | config. BorderWidth = 1 |
||
64 | config. CenterMouse = false // false or true - center the tip horizontally below (or above) the mousepointer |
||
65 | config. ClickClose = false // false or true - close tooltip if the user clicks somewhere |
||
66 | config. ClickSticky = false // false or true - make tooltip sticky if user left-clicks on the hovered element while the tooltip is active |
||
3556 | bpr | 67 | config. CloseBtn = true // false or true - closebutton in titlebar |
3553 | bpr | 68 | config. CloseBtnColors = ['#990000', '#FFFFFF', '#DD3333', '#FFFFFF'] // [Background, text, hovered background, hovered text] - use empty strings '' to inherit title colours |
69 | config. CloseBtnText = ' X ' // Close button text (may also be an image tag) |
||
70 | config. CopyContent = true // When converting a HTML element to a tooltip, copy only the element's content, rather than converting the element by its own |
||
71 | config. Delay = 400 // Time span in ms until tooltip shows up |
||
72 | config. Duration = 0 // Time span in ms after which the tooltip disappears; 0 for infinite duration, < 0 for delay in ms _after_ the onmouseout until the tooltip disappears |
||
73 | config. Exclusive = false // false or true - no other tooltip can appear until the current one has actively been closed |
||
74 | config. FadeIn = 100 // Fade-in duration in ms, e.g. 400; 0 for no animation |
||
75 | config. FadeOut = 100 |
||
76 | config. FadeInterval = 30 // Duration of each fade step in ms (recommended: 30) - shorter is smoother but causes more CPU-load |
||
77 | config. Fix = null // Fixated position, two modes. Mode 1: x- an y-coordinates in brackets, e.g. [210, 480]. Mode 2: Show tooltip at a position related to an HTML element: [ID of HTML element, x-offset, y-offset from HTML element], e.g. ['SomeID', 10, 30]. Value null (default) for no fixated positioning. |
||
78 | config. FollowMouse = false // false or true - tooltip follows the mouse |
||
79 | config. FontColor = '#000044' |
||
80 | config. FontFace = 'Verdana,Geneva,sans-serif' |
||
81 | config. FontSize = '8pt' // E.g. '9pt' or '12px' - unit is mandatory |
||
82 | config. FontWeight = 'normal' // 'normal' or 'bold'; |
||
83 | config. Height = 0 // Tooltip height; 0 for automatic adaption to tooltip content, < 0 (e.g. -100) for a maximum for automatic adaption |
||
84 | config. JumpHorz = false // false or true - jump horizontally to other side of mouse if tooltip would extend past clientarea boundary |
||
85 | config. JumpVert = true // false or true - jump vertically " |
||
86 | config. Left = false // false or true - tooltip on the left of the mouse |
||
87 | config. OffsetX = 14 // Horizontal offset of left-top corner from mousepointer |
||
88 | config. OffsetY = 8 // Vertical offset |
||
89 | config. Opacity = 100 // Integer between 0 and 100 - opacity of tooltip in percent |
||
90 | config. Padding = 20 // Spacing between border and content |
||
91 | config. Shadow = false // false or true |
||
92 | config. ShadowColor = '#C0C0C0' |
||
93 | config. ShadowWidth = 5 |
||
3556 | bpr | 94 | config. Sticky = true // false or true - fixate tip, ie. don't follow the mouse and don't hide on mouseout |
3553 | bpr | 95 | config. TextAlign = 'left' // 'left', 'right' or 'justify' |
96 | config. Title = '' // Default title text applied to all tips (no default title: empty string '') |
||
97 | config. TitleAlign = 'center' // 'left' or 'right' - text alignment inside the title bar |
||
98 | config. TitleBgColor = '' // If empty string '', BorderColor will be used |
||
99 | config. TitleFontColor = '#FFFFFF' // Color of title text - if '', BgColor (of tooltip body) will be used |
||
100 | config. TitleFontFace = '' // If '' use FontFace (boldified) |
||
101 | config. TitleFontSize = '' // If '' use FontSize |
||
102 | config. TitlePadding = 2 |
||
103 | config. Width = 0 // Tooltip width; 0 for automatic adaption to tooltip content; < -1 (e.g. -240) for a maximum width for that automatic adaption; |
||
104 | // -1: tooltip width confined to the width required for the titlebar |
||
105 | //======= END OF TOOLTIP CONFIG, DO NOT CHANGE ANYTHING BELOW ==============// |
||
106 | |||
107 | |||
108 | |||
109 | |||
110 | //===================== PUBLIC =============================================// |
||
111 | function Tip() |
||
112 | { |
||
113 | tt_Tip(arguments, null); |
||
114 | } |
||
115 | function TagToTip() |
||
116 | { |
||
117 | var t2t = tt_GetElt(arguments[0]); |
||
118 | if(t2t) |
||
119 | tt_Tip(arguments, t2t); |
||
120 | } |
||
121 | function UnTip() |
||
122 | { |
||
123 | tt_OpReHref(); |
||
124 | if(tt_aV[DURATION] < 0 && (tt_iState & 0x2)) |
||
125 | tt_tDurt.Timer("tt_HideInit()", -tt_aV[DURATION], true); |
||
126 | else if(!(tt_aV[STICKY] && (tt_iState & 0x2))) |
||
127 | tt_HideInit(); |
||
128 | } |
||
129 | |||
130 | //================== PUBLIC PLUGIN API =====================================// |
||
131 | // Extension eventhandlers currently supported: |
||
132 | // OnLoadConfig, OnCreateContentString, OnSubDivsCreated, OnShow, OnMoveBefore, |
||
133 | // OnMoveAfter, OnHideInit, OnHide, OnKill |
||
134 | |||
135 | var tt_aElt = new Array(10), // Container DIV, outer title & body DIVs, inner title & body TDs, closebutton SPAN, shadow DIVs, and IFRAME to cover windowed elements in IE |
||
136 | tt_aV = new Array(), // Caches and enumerates config data for currently active tooltip |
||
137 | tt_sContent, // Inner tooltip text or HTML |
||
138 | tt_t2t, tt_t2tDad, // Tag converted to tip, and its DOM parent element |
||
139 | tt_scrlX = 0, tt_scrlY = 0, |
||
140 | tt_musX, tt_musY, |
||
141 | tt_over, |
||
142 | tt_x, tt_y, tt_w, tt_h; // Position, width and height of currently displayed tooltip |
||
143 | |||
144 | function tt_Extension() |
||
145 | { |
||
146 | tt_ExtCmdEnum(); |
||
147 | tt_aExt[tt_aExt.length] = this; |
||
148 | return this; |
||
149 | } |
||
150 | function tt_SetTipPos(x, y) |
||
151 | { |
||
152 | var css = tt_aElt[0].style; |
||
153 | |||
154 | tt_x = x; |
||
155 | tt_y = y; |
||
156 | css.left = x + "px"; |
||
157 | css.top = y + "px"; |
||
158 | if(tt_ie56) |
||
159 | { |
||
160 | var ifrm = tt_aElt[tt_aElt.length - 1]; |
||
161 | if(ifrm) |
||
162 | { |
||
163 | ifrm.style.left = css.left; |
||
164 | ifrm.style.top = css.top; |
||
165 | } |
||
166 | } |
||
167 | } |
||
168 | function tt_HideInit() |
||
169 | { |
||
170 | if(tt_iState) |
||
171 | { |
||
172 | tt_ExtCallFncs(0, "HideInit"); |
||
173 | tt_iState &= ~(0x4 | 0x8); |
||
174 | if(tt_flagOpa && tt_aV[FADEOUT]) |
||
175 | { |
||
176 | tt_tFade.EndTimer(); |
||
177 | if(tt_opa) |
||
178 | { |
||
179 | var n = Math.round(tt_aV[FADEOUT] / (tt_aV[FADEINTERVAL] * (tt_aV[OPACITY] / tt_opa))); |
||
180 | tt_Fade(tt_opa, tt_opa, 0, n); |
||
181 | return; |
||
182 | } |
||
183 | } |
||
184 | tt_tHide.Timer("tt_Hide();", 1, false); |
||
185 | } |
||
186 | } |
||
187 | function tt_Hide() |
||
188 | { |
||
189 | if(tt_db && tt_iState) |
||
190 | { |
||
191 | tt_OpReHref(); |
||
192 | if(tt_iState & 0x2) |
||
193 | { |
||
194 | tt_aElt[0].style.visibility = "hidden"; |
||
195 | tt_ExtCallFncs(0, "Hide"); |
||
196 | } |
||
197 | tt_tShow.EndTimer(); |
||
198 | tt_tHide.EndTimer(); |
||
199 | tt_tDurt.EndTimer(); |
||
200 | tt_tFade.EndTimer(); |
||
201 | if(!tt_op && !tt_ie) |
||
202 | { |
||
203 | tt_tWaitMov.EndTimer(); |
||
204 | tt_bWait = false; |
||
205 | } |
||
206 | if(tt_aV[CLICKCLOSE] || tt_aV[CLICKSTICKY]) |
||
207 | tt_RemEvtFnc(document, "mouseup", tt_OnLClick); |
||
208 | tt_ExtCallFncs(0, "Kill"); |
||
209 | // In case of a TagToTip tip, hide converted DOM node and |
||
210 | // re-insert it into DOM |
||
211 | if(tt_t2t && !tt_aV[COPYCONTENT]) |
||
212 | tt_UnEl2Tip(); |
||
213 | tt_iState = 0; |
||
214 | tt_over = null; |
||
215 | tt_ResetMainDiv(); |
||
216 | if(tt_aElt[tt_aElt.length - 1]) |
||
217 | tt_aElt[tt_aElt.length - 1].style.display = "none"; |
||
218 | } |
||
219 | } |
||
220 | function tt_GetElt(id) |
||
221 | { |
||
222 | return(document.getElementById ? document.getElementById(id) |
||
223 | : document.all ? document.all[id] |
||
224 | : null); |
||
225 | } |
||
226 | function tt_GetDivW(el) |
||
227 | { |
||
228 | return(el ? (el.offsetWidth || el.style.pixelWidth || 0) : 0); |
||
229 | } |
||
230 | function tt_GetDivH(el) |
||
231 | { |
||
232 | return(el ? (el.offsetHeight || el.style.pixelHeight || 0) : 0); |
||
233 | } |
||
234 | function tt_GetScrollX() |
||
235 | { |
||
236 | return(window.pageXOffset || (tt_db ? (tt_db.scrollLeft || 0) : 0)); |
||
237 | } |
||
238 | function tt_GetScrollY() |
||
239 | { |
||
240 | return(window.pageYOffset || (tt_db ? (tt_db.scrollTop || 0) : 0)); |
||
241 | } |
||
242 | function tt_GetClientW() |
||
243 | { |
||
244 | return tt_GetWndCliSiz("Width"); |
||
245 | } |
||
246 | function tt_GetClientH() |
||
247 | { |
||
248 | return tt_GetWndCliSiz("Height"); |
||
249 | } |
||
250 | function tt_GetEvtX(e) |
||
251 | { |
||
252 | return (e ? ((typeof(e.pageX) != tt_u) ? e.pageX : (e.clientX + tt_scrlX)) : 0); |
||
253 | } |
||
254 | function tt_GetEvtY(e) |
||
255 | { |
||
256 | return (e ? ((typeof(e.pageY) != tt_u) ? e.pageY : (e.clientY + tt_scrlY)) : 0); |
||
257 | } |
||
258 | function tt_AddEvtFnc(el, sEvt, PFnc) |
||
259 | { |
||
260 | if(el) |
||
261 | { |
||
262 | if(el.addEventListener) |
||
263 | el.addEventListener(sEvt, PFnc, false); |
||
264 | else |
||
265 | el.attachEvent("on" + sEvt, PFnc); |
||
266 | } |
||
267 | } |
||
268 | function tt_RemEvtFnc(el, sEvt, PFnc) |
||
269 | { |
||
270 | if(el) |
||
271 | { |
||
272 | if(el.removeEventListener) |
||
273 | el.removeEventListener(sEvt, PFnc, false); |
||
274 | else |
||
275 | el.detachEvent("on" + sEvt, PFnc); |
||
276 | } |
||
277 | } |
||
278 | function tt_GetDad(el) |
||
279 | { |
||
280 | return(el.parentNode || el.parentElement || el.offsetParent); |
||
281 | } |
||
282 | function tt_MovDomNode(el, dadFrom, dadTo) |
||
283 | { |
||
284 | if(dadFrom) |
||
285 | dadFrom.removeChild(el); |
||
286 | if(dadTo) |
||
287 | dadTo.appendChild(el); |
||
288 | } |
||
289 | |||
290 | //====================== PRIVATE ===========================================// |
||
291 | var tt_aExt = new Array(), // Array of extension objects |
||
292 | |||
293 | tt_db, tt_op, tt_ie, tt_ie56, tt_bBoxOld, // Browser flags |
||
294 | tt_body, |
||
295 | tt_ovr_, // HTML element the mouse is currently over |
||
296 | tt_flagOpa, // Opacity support: 1=IE, 2=Khtml, 3=KHTML, 4=Moz, 5=W3C |
||
297 | tt_maxPosX, tt_maxPosY, |
||
298 | tt_iState = 0, // Tooltip active |= 1, shown |= 2, move with mouse |= 4, exclusive |= 8 |
||
299 | tt_opa, // Currently applied opacity |
||
300 | tt_bJmpVert, tt_bJmpHorz,// Tip temporarily on other side of mouse |
||
301 | tt_elDeHref, // The tag from which we've removed the href attribute |
||
302 | // Timer |
||
303 | tt_tShow = new Number(0), tt_tHide = new Number(0), tt_tDurt = new Number(0), |
||
304 | tt_tFade = new Number(0), tt_tWaitMov = new Number(0), |
||
305 | tt_bWait = false, |
||
306 | tt_u = "undefined"; |
||
307 | |||
308 | |||
309 | function tt_Init() |
||
310 | { |
||
311 | tt_MkCmdEnum(); |
||
312 | // Send old browsers instantly to hell |
||
313 | if(!tt_Browser() || !tt_MkMainDiv()) |
||
314 | return; |
||
315 | // Levy 06/11/2008: Important! IE doesn't fire an onscroll when a page |
||
316 | // refresh is made, so we need to recalc page positions on init. |
||
317 | tt_OnScrl(); |
||
318 | tt_IsW3cBox(); |
||
319 | tt_OpaSupport(); |
||
320 | tt_AddEvtFnc(window, "scroll", tt_OnScrl); |
||
321 | // IE doesn't fire onscroll event when switching to fullscreen; |
||
322 | // fix suggested by Yoav Karpeles 14.2.2008 |
||
323 | tt_AddEvtFnc(window, "resize", tt_OnScrl); |
||
324 | tt_AddEvtFnc(document, "mousemove", tt_Move); |
||
325 | // In Debug mode we search for TagToTip() calls in order to notify |
||
326 | // the user if they've forgotten to set the TagsToTip config flag |
||
327 | if(TagsToTip || tt_Debug) |
||
328 | tt_SetOnloadFnc(); |
||
329 | // Ensure the tip be hidden when the page unloads |
||
330 | tt_AddEvtFnc(window, "unload", tt_Hide); |
||
331 | } |
||
332 | // Creates command names by translating config variable names to upper case |
||
333 | function tt_MkCmdEnum() |
||
334 | { |
||
335 | var n = 0; |
||
336 | for(var i in config) |
||
337 | eval("window." + i.toString().toUpperCase() + " = " + n++); |
||
338 | tt_aV.length = n; |
||
339 | } |
||
340 | function tt_Browser() |
||
341 | { |
||
342 | var n, nv, n6, w3c; |
||
343 | |||
344 | n = navigator.userAgent.toLowerCase(), |
||
345 | nv = navigator.appVersion; |
||
346 | tt_op = (document.defaultView && typeof(eval("w" + "indow" + "." + "o" + "p" + "er" + "a")) != tt_u); |
||
347 | tt_ie = n.indexOf("msie") != -1 && document.all && !tt_op; |
||
348 | if(tt_ie) |
||
349 | { |
||
350 | var ieOld = (!document.compatMode || document.compatMode == "BackCompat"); |
||
351 | tt_db = !ieOld ? document.documentElement : (document.body || null); |
||
352 | if(tt_db) |
||
353 | tt_ie56 = parseFloat(nv.substring(nv.indexOf("MSIE") + 5)) >= 5.5 |
||
354 | && typeof document.body.style.maxHeight == tt_u; |
||
355 | } |
||
356 | else |
||
357 | { |
||
358 | tt_db = document.documentElement || document.body || |
||
359 | (document.getElementsByTagName ? document.getElementsByTagName("body")[0] |
||
360 | : null); |
||
361 | if(!tt_op) |
||
362 | { |
||
363 | n6 = document.defaultView && typeof document.defaultView.getComputedStyle != tt_u; |
||
364 | w3c = !n6 && document.getElementById; |
||
365 | } |
||
366 | } |
||
367 | tt_body = (document.getElementsByTagName ? document.getElementsByTagName("body")[0] |
||
368 | : (document.body || null)); |
||
369 | if(tt_ie || n6 || tt_op || w3c) |
||
370 | { |
||
371 | if(tt_body && tt_db) |
||
372 | { |
||
373 | if(document.attachEvent || document.addEventListener) |
||
374 | return true; |
||
375 | } |
||
376 | else |
||
377 | tt_Err("wz_tooltip.js must be included INSIDE the body section," |
||
378 | + " immediately after the opening <body> tag.", false); |
||
379 | } |
||
380 | tt_db = null; |
||
381 | return false; |
||
382 | } |
||
383 | function tt_MkMainDiv() |
||
384 | { |
||
385 | // Create the tooltip DIV |
||
386 | if(tt_body.insertAdjacentHTML) |
||
387 | tt_body.insertAdjacentHTML("afterBegin", tt_MkMainDivHtm()); |
||
388 | else if(typeof tt_body.innerHTML != tt_u && document.createElement && tt_body.appendChild) |
||
389 | tt_body.appendChild(tt_MkMainDivDom()); |
||
390 | if(window.tt_GetMainDivRefs /* FireFox Alzheimer */ && tt_GetMainDivRefs()) |
||
391 | return true; |
||
392 | tt_db = null; |
||
393 | return false; |
||
394 | } |
||
395 | function tt_MkMainDivHtm() |
||
396 | { |
||
397 | return( |
||
398 | '<div id="WzTtDiV"></div>' + |
||
399 | (tt_ie56 ? ('<iframe id="WzTtIfRm" src="javascript:false" scrolling="no" frameborder="0" style="filter:Alpha(opacity=0);position:absolute;top:0px;left:0px;display:none;"></iframe>') |
||
400 | : '') |
||
401 | ); |
||
402 | } |
||
403 | function tt_MkMainDivDom() |
||
404 | { |
||
405 | var el = document.createElement("div"); |
||
406 | if(el) |
||
407 | el.id = "WzTtDiV"; |
||
408 | return el; |
||
409 | } |
||
410 | function tt_GetMainDivRefs() |
||
411 | { |
||
412 | tt_aElt[0] = tt_GetElt("WzTtDiV"); |
||
413 | if(tt_ie56 && tt_aElt[0]) |
||
414 | { |
||
415 | tt_aElt[tt_aElt.length - 1] = tt_GetElt("WzTtIfRm"); |
||
416 | if(!tt_aElt[tt_aElt.length - 1]) |
||
417 | tt_aElt[0] = null; |
||
418 | } |
||
419 | if(tt_aElt[0]) |
||
420 | { |
||
421 | var css = tt_aElt[0].style; |
||
422 | |||
423 | css.visibility = "hidden"; |
||
424 | css.position = "absolute"; |
||
425 | css.overflow = "hidden"; |
||
426 | return true; |
||
427 | } |
||
428 | return false; |
||
429 | } |
||
430 | function tt_ResetMainDiv() |
||
431 | { |
||
432 | tt_SetTipPos(0, 0); |
||
433 | tt_aElt[0].innerHTML = ""; |
||
434 | tt_aElt[0].style.width = "0px"; |
||
435 | tt_h = 0; |
||
436 | } |
||
437 | function tt_IsW3cBox() |
||
438 | { |
||
439 | var css = tt_aElt[0].style; |
||
440 | |||
441 | css.padding = "10px"; |
||
442 | css.width = "40px"; |
||
443 | tt_bBoxOld = (tt_GetDivW(tt_aElt[0]) == 40); |
||
444 | css.padding = "0px"; |
||
445 | tt_ResetMainDiv(); |
||
446 | } |
||
447 | function tt_OpaSupport() |
||
448 | { |
||
449 | var css = tt_body.style; |
||
450 | |||
451 | tt_flagOpa = (typeof(css.KhtmlOpacity) != tt_u) ? 2 |
||
452 | : (typeof(css.KHTMLOpacity) != tt_u) ? 3 |
||
453 | : (typeof(css.MozOpacity) != tt_u) ? 4 |
||
454 | : (typeof(css.opacity) != tt_u) ? 5 |
||
455 | : (typeof(css.filter) != tt_u) ? 1 |
||
456 | : 0; |
||
457 | } |
||
458 | // Ported from http://dean.edwards.name/weblog/2006/06/again/ |
||
459 | // (Dean Edwards et al.) |
||
460 | function tt_SetOnloadFnc() |
||
461 | { |
||
462 | tt_AddEvtFnc(document, "DOMContentLoaded", tt_HideSrcTags); |
||
463 | tt_AddEvtFnc(window, "load", tt_HideSrcTags); |
||
464 | if(tt_body.attachEvent) |
||
465 | tt_body.attachEvent("onreadystatechange", |
||
466 | function() { |
||
467 | if(tt_body.readyState == "complete") |
||
468 | tt_HideSrcTags(); |
||
469 | } ); |
||
470 | if(/WebKit|KHTML/i.test(navigator.userAgent)) |
||
471 | { |
||
472 | var t = setInterval(function() { |
||
473 | if(/loaded|complete/.test(document.readyState)) |
||
474 | { |
||
475 | clearInterval(t); |
||
476 | tt_HideSrcTags(); |
||
477 | } |
||
478 | }, 10); |
||
479 | } |
||
480 | } |
||
481 | function tt_HideSrcTags() |
||
482 | { |
||
483 | if(!window.tt_HideSrcTags || window.tt_HideSrcTags.done) |
||
484 | return; |
||
485 | window.tt_HideSrcTags.done = true; |
||
486 | if(!tt_HideSrcTagsRecurs(tt_body)) |
||
487 | tt_Err("There are HTML elements to be converted to tooltips.\nIf you" |
||
488 | + " want these HTML elements to be automatically hidden, you" |
||
489 | + " must edit wz_tooltip.js, and set TagsToTip in the global" |
||
490 | + " tooltip configuration to true.", true); |
||
491 | } |
||
492 | function tt_HideSrcTagsRecurs(dad) |
||
493 | { |
||
494 | var ovr, asT2t; |
||
495 | // Walk the DOM tree for tags that have an onmouseover or onclick attribute |
||
496 | // containing a TagToTip('...') call. |
||
497 | // (.childNodes first since .children is bugous in Safari) |
||
498 | var a = dad.childNodes || dad.children || null; |
||
499 | |||
500 | for(var i = a ? a.length : 0; i;) |
||
501 | {--i; |
||
502 | if(!tt_HideSrcTagsRecurs(a[i])) |
||
503 | return false; |
||
504 | ovr = a[i].getAttribute ? (a[i].getAttribute("onmouseover") || a[i].getAttribute("onclick")) |
||
505 | : (typeof a[i].onmouseover == "function") ? (a[i].onmouseover || a[i].onclick) |
||
506 | : null; |
||
507 | if(ovr) |
||
508 | { |
||
509 | asT2t = ovr.toString().match(/TagToTip\s*\(\s*'[^'.]+'\s*[\),]/); |
||
510 | if(asT2t && asT2t.length) |
||
511 | { |
||
512 | if(!tt_HideSrcTag(asT2t[0])) |
||
513 | return false; |
||
514 | } |
||
515 | } |
||
516 | } |
||
517 | return true; |
||
518 | } |
||
519 | function tt_HideSrcTag(sT2t) |
||
520 | { |
||
521 | var id, el; |
||
522 | |||
523 | // The ID passed to the found TagToTip() call identifies an HTML element |
||
524 | // to be converted to a tooltip, so hide that element |
||
525 | id = sT2t.replace(/.+'([^'.]+)'.+/, "$1"); |
||
526 | el = tt_GetElt(id); |
||
527 | if(el) |
||
528 | { |
||
529 | if(tt_Debug && !TagsToTip) |
||
530 | return false; |
||
531 | else |
||
532 | el.style.display = "none"; |
||
533 | } |
||
534 | else |
||
535 | tt_Err("Invalid ID\n'" + id + "'\npassed to TagToTip()." |
||
536 | + " There exists no HTML element with that ID.", true); |
||
537 | return true; |
||
538 | } |
||
539 | function tt_Tip(arg, t2t) |
||
540 | { |
||
541 | if(!tt_db || (tt_iState & 0x8)) |
||
542 | return; |
||
543 | if(tt_iState) |
||
544 | tt_Hide(); |
||
545 | if(!tt_Enabled) |
||
546 | return; |
||
547 | tt_t2t = t2t; |
||
548 | if(!tt_ReadCmds(arg)) |
||
549 | return; |
||
550 | tt_iState = 0x1 | 0x4; |
||
551 | tt_AdaptConfig1(); |
||
552 | tt_MkTipContent(arg); |
||
553 | tt_MkTipSubDivs(); |
||
554 | tt_FormatTip(); |
||
555 | tt_bJmpVert = false; |
||
556 | tt_bJmpHorz = false; |
||
557 | tt_maxPosX = tt_GetClientW() + tt_scrlX - tt_w - 1; |
||
558 | tt_maxPosY = tt_GetClientH() + tt_scrlY - tt_h - 1; |
||
559 | tt_AdaptConfig2(); |
||
560 | // Ensure the tip be shown and positioned before the first onmousemove |
||
561 | tt_OverInit(); |
||
562 | tt_ShowInit(); |
||
563 | tt_Move(); |
||
564 | } |
||
565 | function tt_ReadCmds(a) |
||
566 | { |
||
567 | var i; |
||
568 | |||
569 | // First load the global config values, to initialize also values |
||
570 | // for which no command is passed |
||
571 | i = 0; |
||
572 | for(var j in config) |
||
573 | tt_aV[i++] = config[j]; |
||
574 | // Then replace each cached config value for which a command is |
||
575 | // passed (ensure the # of command args plus value args be even) |
||
576 | if(a.length & 1) |
||
577 | { |
||
578 | for(i = a.length - 1; i > 0; i -= 2) |
||
579 | tt_aV[a[i - 1]] = a[i]; |
||
580 | return true; |
||
581 | } |
||
582 | tt_Err("Incorrect call of Tip() or TagToTip().\n" |
||
583 | + "Each command must be followed by a value.", true); |
||
584 | return false; |
||
585 | } |
||
586 | function tt_AdaptConfig1() |
||
587 | { |
||
588 | tt_ExtCallFncs(0, "LoadConfig"); |
||
589 | // Inherit unspecified title formattings from body |
||
590 | if(!tt_aV[TITLEBGCOLOR].length) |
||
591 | tt_aV[TITLEBGCOLOR] = tt_aV[BORDERCOLOR]; |
||
592 | if(!tt_aV[TITLEFONTCOLOR].length) |
||
593 | tt_aV[TITLEFONTCOLOR] = tt_aV[BGCOLOR]; |
||
594 | if(!tt_aV[TITLEFONTFACE].length) |
||
595 | tt_aV[TITLEFONTFACE] = tt_aV[FONTFACE]; |
||
596 | if(!tt_aV[TITLEFONTSIZE].length) |
||
597 | tt_aV[TITLEFONTSIZE] = tt_aV[FONTSIZE]; |
||
598 | if(tt_aV[CLOSEBTN]) |
||
599 | { |
||
600 | // Use title colours for non-specified closebutton colours |
||
601 | if(!tt_aV[CLOSEBTNCOLORS]) |
||
602 | tt_aV[CLOSEBTNCOLORS] = new Array("", "", "", ""); |
||
603 | for(var i = 4; i;) |
||
604 | {--i; |
||
605 | if(!tt_aV[CLOSEBTNCOLORS][i].length) |
||
606 | tt_aV[CLOSEBTNCOLORS][i] = (i & 1) ? tt_aV[TITLEFONTCOLOR] : tt_aV[TITLEBGCOLOR]; |
||
607 | } |
||
608 | // Enforce titlebar be shown |
||
609 | if(!tt_aV[TITLE].length) |
||
610 | tt_aV[TITLE] = " "; |
||
611 | } |
||
612 | // Circumvents broken display of images and fade-in flicker in Geckos < 1.8 |
||
613 | if(tt_aV[OPACITY] == 100 && typeof tt_aElt[0].style.MozOpacity != tt_u && !Array.every) |
||
614 | tt_aV[OPACITY] = 99; |
||
615 | // Smartly shorten the delay for fade-in tooltips |
||
616 | if(tt_aV[FADEIN] && tt_flagOpa && tt_aV[DELAY] > 100) |
||
617 | tt_aV[DELAY] = Math.max(tt_aV[DELAY] - tt_aV[FADEIN], 100); |
||
618 | } |
||
619 | function tt_AdaptConfig2() |
||
620 | { |
||
621 | if(tt_aV[CENTERMOUSE]) |
||
622 | { |
||
623 | tt_aV[OFFSETX] -= ((tt_w - (tt_aV[SHADOW] ? tt_aV[SHADOWWIDTH] : 0)) >> 1); |
||
624 | tt_aV[JUMPHORZ] = false; |
||
625 | } |
||
626 | } |
||
627 | // Expose content globally so extensions can modify it |
||
628 | function tt_MkTipContent(a) |
||
629 | { |
||
630 | if(tt_t2t) |
||
631 | { |
||
632 | if(tt_aV[COPYCONTENT]) |
||
633 | tt_sContent = tt_t2t.innerHTML; |
||
634 | else |
||
635 | tt_sContent = ""; |
||
636 | } |
||
637 | else |
||
638 | tt_sContent = a[0]; |
||
639 | tt_ExtCallFncs(0, "CreateContentString"); |
||
640 | } |
||
641 | function tt_MkTipSubDivs() |
||
642 | { |
||
643 | var sCss = 'position:relative;margin:0px;padding:0px;border-width:0px;left:0px;top:0px;line-height:normal;width:auto;', |
||
644 | sTbTrTd = ' cellspacing="0" cellpadding="0" border="0" style="' + sCss + '"><tbody style="' + sCss + '"><tr><td '; |
||
645 | |||
646 | tt_aElt[0].style.width = tt_GetClientW() + "px"; |
||
647 | tt_aElt[0].innerHTML = |
||
648 | ('' |
||
649 | + (tt_aV[TITLE].length ? |
||
650 | ('<div id="WzTiTl" style="position:relative;z-index:1;">' |
||
651 | + '<table id="WzTiTlTb"' + sTbTrTd + 'id="WzTiTlI" style="' + sCss + '">' |
||
652 | + tt_aV[TITLE] |
||
653 | + '</td>' |
||
654 | + (tt_aV[CLOSEBTN] ? |
||
655 | ('<td align="right" style="' + sCss |
||
656 | + 'text-align:right;">' |
||
657 | + '<span id="WzClOsE" style="position:relative;left:2px;padding-left:2px;padding-right:2px;' |
||
658 | + 'cursor:' + (tt_ie ? 'hand' : 'pointer') |
||
659 | + ';" onmouseover="tt_OnCloseBtnOver(1)" onmouseout="tt_OnCloseBtnOver(0)" onclick="tt_HideInit()">' |
||
660 | + tt_aV[CLOSEBTNTEXT] |
||
661 | + '</span></td>') |
||
662 | : '') |
||
663 | + '</tr></tbody></table></div>') |
||
664 | : '') |
||
665 | + '<div id="WzBoDy" style="position:relative;z-index:0;">' |
||
666 | + '<table' + sTbTrTd + 'id="WzBoDyI" style="' + sCss + '">' |
||
667 | + tt_sContent |
||
668 | + '</td></tr></tbody></table></div>' |
||
669 | + (tt_aV[SHADOW] |
||
670 | ? ('<div id="WzTtShDwR" style="position:absolute;overflow:hidden;"></div>' |
||
671 | + '<div id="WzTtShDwB" style="position:relative;overflow:hidden;"></div>') |
||
672 | : '') |
||
673 | ); |
||
674 | tt_GetSubDivRefs(); |
||
675 | // Convert DOM node to tip |
||
676 | if(tt_t2t && !tt_aV[COPYCONTENT]) |
||
677 | tt_El2Tip(); |
||
678 | tt_ExtCallFncs(0, "SubDivsCreated"); |
||
679 | } |
||
680 | function tt_GetSubDivRefs() |
||
681 | { |
||
682 | var aId = new Array("WzTiTl", "WzTiTlTb", "WzTiTlI", "WzClOsE", "WzBoDy", "WzBoDyI", "WzTtShDwB", "WzTtShDwR"); |
||
683 | |||
684 | for(var i = aId.length; i; --i) |
||
685 | tt_aElt[i] = tt_GetElt(aId[i - 1]); |
||
686 | } |
||
687 | function tt_FormatTip() |
||
688 | { |
||
689 | var css, w, h, pad = tt_aV[PADDING], padT, wBrd = tt_aV[BORDERWIDTH], |
||
690 | iOffY, iOffSh, iAdd = (pad + wBrd) << 1; |
||
691 | |||
692 | //--------- Title DIV ---------- |
||
693 | if(tt_aV[TITLE].length) |
||
694 | { |
||
695 | padT = tt_aV[TITLEPADDING]; |
||
696 | css = tt_aElt[1].style; |
||
697 | css.background = tt_aV[TITLEBGCOLOR]; |
||
698 | css.paddingTop = css.paddingBottom = padT + "px"; |
||
699 | css.paddingLeft = css.paddingRight = (padT + 2) + "px"; |
||
700 | css = tt_aElt[3].style; |
||
701 | css.color = tt_aV[TITLEFONTCOLOR]; |
||
702 | if(tt_aV[WIDTH] == -1) |
||
703 | css.whiteSpace = "nowrap"; |
||
704 | css.fontFamily = tt_aV[TITLEFONTFACE]; |
||
705 | css.fontSize = tt_aV[TITLEFONTSIZE]; |
||
706 | css.fontWeight = "bold"; |
||
707 | css.textAlign = tt_aV[TITLEALIGN]; |
||
708 | // Close button DIV |
||
709 | if(tt_aElt[4]) |
||
710 | { |
||
711 | css = tt_aElt[4].style; |
||
712 | css.background = tt_aV[CLOSEBTNCOLORS][0]; |
||
713 | css.color = tt_aV[CLOSEBTNCOLORS][1]; |
||
714 | css.fontFamily = tt_aV[TITLEFONTFACE]; |
||
715 | css.fontSize = tt_aV[TITLEFONTSIZE]; |
||
716 | css.fontWeight = "bold"; |
||
717 | } |
||
718 | if(tt_aV[WIDTH] > 0) |
||
719 | tt_w = tt_aV[WIDTH]; |
||
720 | else |
||
721 | { |
||
722 | tt_w = tt_GetDivW(tt_aElt[3]) + tt_GetDivW(tt_aElt[4]); |
||
723 | // Some spacing between title DIV and closebutton |
||
724 | if(tt_aElt[4]) |
||
725 | tt_w += pad; |
||
726 | // Restrict auto width to max width |
||
727 | if(tt_aV[WIDTH] < -1 && tt_w > -tt_aV[WIDTH]) |
||
728 | tt_w = -tt_aV[WIDTH]; |
||
729 | } |
||
730 | // Ensure the top border of the body DIV be covered by the title DIV |
||
731 | iOffY = -wBrd; |
||
732 | } |
||
733 | else |
||
734 | { |
||
735 | tt_w = 0; |
||
736 | iOffY = 0; |
||
737 | } |
||
738 | |||
739 | //-------- Body DIV ------------ |
||
740 | css = tt_aElt[5].style; |
||
741 | css.top = iOffY + "px"; |
||
742 | if(wBrd) |
||
743 | { |
||
744 | css.borderColor = tt_aV[BORDERCOLOR]; |
||
745 | css.borderStyle = tt_aV[BORDERSTYLE]; |
||
746 | css.borderWidth = wBrd + "px"; |
||
747 | } |
||
748 | if(tt_aV[BGCOLOR].length) |
||
749 | css.background = tt_aV[BGCOLOR]; |
||
750 | if(tt_aV[BGIMG].length) |
||
751 | css.backgroundImage = "url(" + tt_aV[BGIMG] + ")"; |
||
752 | css.padding = pad + "px"; |
||
753 | css.textAlign = tt_aV[TEXTALIGN]; |
||
754 | if(tt_aV[HEIGHT]) |
||
755 | { |
||
756 | css.overflow = "auto"; |
||
757 | if(tt_aV[HEIGHT] > 0) |
||
758 | css.height = (tt_aV[HEIGHT] + iAdd) + "px"; |
||
759 | else |
||
760 | tt_h = iAdd - tt_aV[HEIGHT]; |
||
761 | } |
||
762 | // TD inside body DIV |
||
763 | css = tt_aElt[6].style; |
||
764 | css.color = tt_aV[FONTCOLOR]; |
||
765 | css.fontFamily = tt_aV[FONTFACE]; |
||
766 | css.fontSize = tt_aV[FONTSIZE]; |
||
767 | css.fontWeight = tt_aV[FONTWEIGHT]; |
||
768 | css.textAlign = tt_aV[TEXTALIGN]; |
||
769 | if(tt_aV[WIDTH] > 0) |
||
770 | w = tt_aV[WIDTH]; |
||
771 | // Width like title (if existent) |
||
772 | else if(tt_aV[WIDTH] == -1 && tt_w) |
||
773 | w = tt_w; |
||
774 | else |
||
775 | { |
||
776 | // Measure width of the body's inner TD, as some browsers would expand |
||
777 | // the container and outer body DIV to 100% |
||
778 | w = tt_GetDivW(tt_aElt[6]); |
||
779 | // Restrict auto width to max width |
||
780 | if(tt_aV[WIDTH] < -1 && w > -tt_aV[WIDTH]) |
||
781 | w = -tt_aV[WIDTH]; |
||
782 | } |
||
783 | if(w > tt_w) |
||
784 | tt_w = w; |
||
785 | tt_w += iAdd; |
||
786 | |||
787 | //--------- Shadow DIVs ------------ |
||
788 | if(tt_aV[SHADOW]) |
||
789 | { |
||
790 | tt_w += tt_aV[SHADOWWIDTH]; |
||
791 | iOffSh = Math.floor((tt_aV[SHADOWWIDTH] * 4) / 3); |
||
792 | // Bottom shadow |
||
793 | css = tt_aElt[7].style; |
||
794 | css.top = iOffY + "px"; |
||
795 | css.left = iOffSh + "px"; |
||
796 | css.width = (tt_w - iOffSh - tt_aV[SHADOWWIDTH]) + "px"; |
||
797 | css.height = tt_aV[SHADOWWIDTH] + "px"; |
||
798 | css.background = tt_aV[SHADOWCOLOR]; |
||
799 | // Right shadow |
||
800 | css = tt_aElt[8].style; |
||
801 | css.top = iOffSh + "px"; |
||
802 | css.left = (tt_w - tt_aV[SHADOWWIDTH]) + "px"; |
||
803 | css.width = tt_aV[SHADOWWIDTH] + "px"; |
||
804 | css.background = tt_aV[SHADOWCOLOR]; |
||
805 | } |
||
806 | else |
||
807 | iOffSh = 0; |
||
808 | |||
809 | //-------- Container DIV ------- |
||
810 | tt_SetTipOpa(tt_aV[FADEIN] ? 0 : tt_aV[OPACITY]); |
||
811 | tt_FixSize(iOffY, iOffSh); |
||
812 | } |
||
813 | // Fixate the size so it can't dynamically change while the tooltip is moving. |
||
814 | function tt_FixSize(iOffY, iOffSh) |
||
815 | { |
||
816 | var wIn, wOut, h, add, pad = tt_aV[PADDING], wBrd = tt_aV[BORDERWIDTH], i; |
||
817 | |||
818 | tt_aElt[0].style.width = tt_w + "px"; |
||
819 | tt_aElt[0].style.pixelWidth = tt_w; |
||
820 | wOut = tt_w - ((tt_aV[SHADOW]) ? tt_aV[SHADOWWIDTH] : 0); |
||
821 | // Body |
||
822 | wIn = wOut; |
||
823 | if(!tt_bBoxOld) |
||
824 | wIn -= (pad + wBrd) << 1; |
||
825 | tt_aElt[5].style.width = wIn + "px"; |
||
826 | // Title |
||
827 | if(tt_aElt[1]) |
||
828 | { |
||
829 | wIn = wOut - ((tt_aV[TITLEPADDING] + 2) << 1); |
||
830 | if(!tt_bBoxOld) |
||
831 | wOut = wIn; |
||
832 | tt_aElt[1].style.width = wOut + "px"; |
||
833 | tt_aElt[2].style.width = wIn + "px"; |
||
834 | } |
||
835 | // Max height specified |
||
836 | if(tt_h) |
||
837 | { |
||
838 | h = tt_GetDivH(tt_aElt[5]); |
||
839 | if(h > tt_h) |
||
840 | { |
||
841 | if(!tt_bBoxOld) |
||
842 | tt_h -= (pad + wBrd) << 1; |
||
843 | tt_aElt[5].style.height = tt_h + "px"; |
||
844 | } |
||
845 | } |
||
846 | tt_h = tt_GetDivH(tt_aElt[0]) + iOffY; |
||
847 | // Right shadow |
||
848 | if(tt_aElt[8]) |
||
849 | tt_aElt[8].style.height = (tt_h - iOffSh) + "px"; |
||
850 | i = tt_aElt.length - 1; |
||
851 | if(tt_aElt[i]) |
||
852 | { |
||
853 | tt_aElt[i].style.width = tt_w + "px"; |
||
854 | tt_aElt[i].style.height = tt_h + "px"; |
||
855 | } |
||
856 | } |
||
857 | function tt_DeAlt(el) |
||
858 | { |
||
859 | var aKid; |
||
860 | |||
861 | if(el) |
||
862 | { |
||
863 | if(el.alt) |
||
864 | el.alt = ""; |
||
865 | if(el.title) |
||
866 | el.title = ""; |
||
867 | aKid = el.childNodes || el.children || null; |
||
868 | if(aKid) |
||
869 | { |
||
870 | for(var i = aKid.length; i;) |
||
871 | tt_DeAlt(aKid[--i]); |
||
872 | } |
||
873 | } |
||
874 | } |
||
875 | // This hack removes the native tooltips over links in Opera |
||
876 | function tt_OpDeHref(el) |
||
877 | { |
||
878 | if(!tt_op) |
||
879 | return; |
||
880 | if(tt_elDeHref) |
||
881 | tt_OpReHref(); |
||
882 | while(el) |
||
883 | { |
||
884 | if(el.hasAttribute && el.hasAttribute("href")) |
||
885 | { |
||
886 | el.t_href = el.getAttribute("href"); |
||
887 | el.t_stats = window.status; |
||
888 | el.removeAttribute("href"); |
||
889 | el.style.cursor = "hand"; |
||
890 | tt_AddEvtFnc(el, "mousedown", tt_OpReHref); |
||
891 | window.status = el.t_href; |
||
892 | tt_elDeHref = el; |
||
893 | break; |
||
894 | } |
||
895 | el = tt_GetDad(el); |
||
896 | } |
||
897 | } |
||
898 | function tt_OpReHref() |
||
899 | { |
||
900 | if(tt_elDeHref) |
||
901 | { |
||
902 | tt_elDeHref.setAttribute("href", tt_elDeHref.t_href); |
||
903 | tt_RemEvtFnc(tt_elDeHref, "mousedown", tt_OpReHref); |
||
904 | window.status = tt_elDeHref.t_stats; |
||
905 | tt_elDeHref = null; |
||
906 | } |
||
907 | } |
||
908 | function tt_El2Tip() |
||
909 | { |
||
910 | var css = tt_t2t.style; |
||
911 | |||
912 | // Store previous positioning |
||
913 | tt_t2t.t_cp = css.position; |
||
914 | tt_t2t.t_cl = css.left; |
||
915 | tt_t2t.t_ct = css.top; |
||
916 | tt_t2t.t_cd = css.display; |
||
917 | // Store the tag's parent element so we can restore that DOM branch |
||
918 | // when the tooltip is being hidden |
||
919 | tt_t2tDad = tt_GetDad(tt_t2t); |
||
920 | tt_MovDomNode(tt_t2t, tt_t2tDad, tt_aElt[6]); |
||
921 | css.display = "block"; |
||
922 | css.position = "static"; |
||
923 | css.left = css.top = css.marginLeft = css.marginTop = "0px"; |
||
924 | } |
||
925 | function tt_UnEl2Tip() |
||
926 | { |
||
927 | // Restore positioning and display |
||
928 | var css = tt_t2t.style; |
||
929 | |||
930 | css.display = tt_t2t.t_cd; |
||
931 | tt_MovDomNode(tt_t2t, tt_GetDad(tt_t2t), tt_t2tDad); |
||
932 | css.position = tt_t2t.t_cp; |
||
933 | css.left = tt_t2t.t_cl; |
||
934 | css.top = tt_t2t.t_ct; |
||
935 | tt_t2tDad = null; |
||
936 | } |
||
937 | function tt_OverInit() |
||
938 | { |
||
939 | if(window.event) |
||
940 | tt_over = window.event.target || window.event.srcElement; |
||
941 | else |
||
942 | tt_over = tt_ovr_; |
||
943 | tt_DeAlt(tt_over); |
||
944 | tt_OpDeHref(tt_over); |
||
945 | } |
||
946 | function tt_ShowInit() |
||
947 | { |
||
948 | tt_tShow.Timer("tt_Show()", tt_aV[DELAY], true); |
||
949 | if(tt_aV[CLICKCLOSE] || tt_aV[CLICKSTICKY]) |
||
950 | tt_AddEvtFnc(document, "mouseup", tt_OnLClick); |
||
951 | } |
||
952 | function tt_Show() |
||
953 | { |
||
954 | var css = tt_aElt[0].style; |
||
955 | |||
956 | // Override the z-index of the topmost wz_dragdrop.js D&D item |
||
957 | css.zIndex = Math.max((window.dd && dd.z) ? (dd.z + 2) : 0, 1010); |
||
958 | if(tt_aV[STICKY] || !tt_aV[FOLLOWMOUSE]) |
||
959 | tt_iState &= ~0x4; |
||
960 | if(tt_aV[EXCLUSIVE]) |
||
961 | tt_iState |= 0x8; |
||
962 | if(tt_aV[DURATION] > 0) |
||
963 | tt_tDurt.Timer("tt_HideInit()", tt_aV[DURATION], true); |
||
964 | tt_ExtCallFncs(0, "Show") |
||
965 | css.visibility = "visible"; |
||
966 | tt_iState |= 0x2; |
||
967 | if(tt_aV[FADEIN]) |
||
968 | tt_Fade(0, 0, tt_aV[OPACITY], Math.round(tt_aV[FADEIN] / tt_aV[FADEINTERVAL])); |
||
969 | tt_ShowIfrm(); |
||
970 | } |
||
971 | function tt_ShowIfrm() |
||
972 | { |
||
973 | if(tt_ie56) |
||
974 | { |
||
975 | var ifrm = tt_aElt[tt_aElt.length - 1]; |
||
976 | if(ifrm) |
||
977 | { |
||
978 | var css = ifrm.style; |
||
979 | css.zIndex = tt_aElt[0].style.zIndex - 1; |
||
980 | css.display = "block"; |
||
981 | } |
||
982 | } |
||
983 | } |
||
984 | function tt_Move(e) |
||
985 | { |
||
986 | if(e) |
||
987 | tt_ovr_ = e.target || e.srcElement; |
||
988 | e = e || window.event; |
||
989 | if(e) |
||
990 | { |
||
991 | tt_musX = tt_GetEvtX(e); |
||
992 | tt_musY = tt_GetEvtY(e); |
||
993 | } |
||
994 | if(tt_iState & 0x4) |
||
995 | { |
||
996 | // Prevent jam of mousemove events |
||
997 | if(!tt_op && !tt_ie) |
||
998 | { |
||
999 | if(tt_bWait) |
||
1000 | return; |
||
1001 | tt_bWait = true; |
||
1002 | tt_tWaitMov.Timer("tt_bWait = false;", 1, true); |
||
1003 | } |
||
1004 | if(tt_aV[FIX]) |
||
1005 | { |
||
1006 | tt_iState &= ~0x4; |
||
1007 | tt_PosFix(); |
||
1008 | } |
||
1009 | else if(!tt_ExtCallFncs(e, "MoveBefore")) |
||
1010 | tt_SetTipPos(tt_Pos(0), tt_Pos(1)); |
||
1011 | tt_ExtCallFncs([tt_musX, tt_musY], "MoveAfter") |
||
1012 | } |
||
1013 | } |
||
1014 | function tt_Pos(iDim) |
||
1015 | { |
||
1016 | var iX, bJmpMod, cmdAlt, cmdOff, cx, iMax, iScrl, iMus, bJmp; |
||
1017 | |||
1018 | // Map values according to dimension to calculate |
||
1019 | if(iDim) |
||
1020 | { |
||
1021 | bJmpMod = tt_aV[JUMPVERT]; |
||
1022 | cmdAlt = ABOVE; |
||
1023 | cmdOff = OFFSETY; |
||
1024 | cx = tt_h; |
||
1025 | iMax = tt_maxPosY; |
||
1026 | iScrl = tt_scrlY; |
||
1027 | iMus = tt_musY; |
||
1028 | bJmp = tt_bJmpVert; |
||
1029 | } |
||
1030 | else |
||
1031 | { |
||
1032 | bJmpMod = tt_aV[JUMPHORZ]; |
||
1033 | cmdAlt = LEFT; |
||
1034 | cmdOff = OFFSETX; |
||
1035 | cx = tt_w; |
||
1036 | iMax = tt_maxPosX; |
||
1037 | iScrl = tt_scrlX; |
||
1038 | iMus = tt_musX; |
||
1039 | bJmp = tt_bJmpHorz; |
||
1040 | } |
||
1041 | if(bJmpMod) |
||
1042 | { |
||
1043 | if(tt_aV[cmdAlt] && (!bJmp || tt_CalcPosAlt(iDim) >= iScrl + 16)) |
||
1044 | iX = tt_PosAlt(iDim); |
||
1045 | else if(!tt_aV[cmdAlt] && bJmp && tt_CalcPosDef(iDim) > iMax - 16) |
||
1046 | iX = tt_PosAlt(iDim); |
||
1047 | else |
||
1048 | iX = tt_PosDef(iDim); |
||
1049 | } |
||
1050 | else |
||
1051 | { |
||
1052 | iX = iMus; |
||
1053 | if(tt_aV[cmdAlt]) |
||
1054 | iX -= cx + tt_aV[cmdOff] - (tt_aV[SHADOW] ? tt_aV[SHADOWWIDTH] : 0); |
||
1055 | else |
||
1056 | iX += tt_aV[cmdOff]; |
||
1057 | } |
||
1058 | // Prevent tip from extending past clientarea boundary |
||
1059 | if(iX > iMax) |
||
1060 | iX = bJmpMod ? tt_PosAlt(iDim) : iMax; |
||
1061 | // In case of insufficient space on both sides, ensure the left/upper part |
||
1062 | // of the tip be visible |
||
1063 | if(iX < iScrl) |
||
1064 | iX = bJmpMod ? tt_PosDef(iDim) : iScrl; |
||
1065 | return iX; |
||
1066 | } |
||
1067 | function tt_PosDef(iDim) |
||
1068 | { |
||
1069 | if(iDim) |
||
1070 | tt_bJmpVert = tt_aV[ABOVE]; |
||
1071 | else |
||
1072 | tt_bJmpHorz = tt_aV[LEFT]; |
||
1073 | return tt_CalcPosDef(iDim); |
||
1074 | } |
||
1075 | function tt_PosAlt(iDim) |
||
1076 | { |
||
1077 | if(iDim) |
||
1078 | tt_bJmpVert = !tt_aV[ABOVE]; |
||
1079 | else |
||
1080 | tt_bJmpHorz = !tt_aV[LEFT]; |
||
1081 | return tt_CalcPosAlt(iDim); |
||
1082 | } |
||
1083 | function tt_CalcPosDef(iDim) |
||
1084 | { |
||
1085 | return iDim ? (tt_musY + tt_aV[OFFSETY]) : (tt_musX + tt_aV[OFFSETX]); |
||
1086 | } |
||
1087 | function tt_CalcPosAlt(iDim) |
||
1088 | { |
||
1089 | var cmdOff = iDim ? OFFSETY : OFFSETX; |
||
1090 | var dx = tt_aV[cmdOff] - (tt_aV[SHADOW] ? tt_aV[SHADOWWIDTH] : 0); |
||
1091 | if(tt_aV[cmdOff] > 0 && dx <= 0) |
||
1092 | dx = 1; |
||
1093 | return((iDim ? (tt_musY - tt_h) : (tt_musX - tt_w)) - dx); |
||
1094 | } |
||
1095 | function tt_PosFix() |
||
1096 | { |
||
1097 | var iX, iY; |
||
1098 | |||
1099 | if(typeof(tt_aV[FIX][0]) == "number") |
||
1100 | { |
||
1101 | iX = tt_aV[FIX][0]; |
||
1102 | iY = tt_aV[FIX][1]; |
||
1103 | } |
||
1104 | else |
||
1105 | { |
||
1106 | if(typeof(tt_aV[FIX][0]) == "string") |
||
1107 | el = tt_GetElt(tt_aV[FIX][0]); |
||
1108 | // First slot in array is direct reference to HTML element |
||
1109 | else |
||
1110 | el = tt_aV[FIX][0]; |
||
1111 | iX = tt_aV[FIX][1]; |
||
1112 | iY = tt_aV[FIX][2]; |
||
1113 | // By default, vert pos is related to bottom edge of HTML element |
||
1114 | if(!tt_aV[ABOVE] && el) |
||
1115 | iY += tt_GetDivH(el); |
||
1116 | for(; el; el = el.offsetParent) |
||
1117 | { |
||
1118 | iX += el.offsetLeft || 0; |
||
1119 | iY += el.offsetTop || 0; |
||
1120 | } |
||
1121 | } |
||
1122 | // For a fixed tip positioned above the mouse, use the bottom edge as anchor |
||
1123 | // (recommended by Christophe Rebeschini, 31.1.2008) |
||
1124 | if(tt_aV[ABOVE]) |
||
1125 | iY -= tt_h; |
||
1126 | tt_SetTipPos(iX, iY); |
||
1127 | } |
||
1128 | function tt_Fade(a, now, z, n) |
||
1129 | { |
||
1130 | if(n) |
||
1131 | { |
||
1132 | now += Math.round((z - now) / n); |
||
1133 | if((z > a) ? (now >= z) : (now <= z)) |
||
1134 | now = z; |
||
1135 | else |
||
1136 | tt_tFade.Timer( |
||
1137 | "tt_Fade(" |
||
1138 | + a + "," + now + "," + z + "," + (n - 1) |
||
1139 | + ")", |
||
1140 | tt_aV[FADEINTERVAL], |
||
1141 | true |
||
1142 | ); |
||
1143 | } |
||
1144 | now ? tt_SetTipOpa(now) : tt_Hide(); |
||
1145 | } |
||
1146 | function tt_SetTipOpa(opa) |
||
1147 | { |
||
1148 | // To circumvent the opacity nesting flaws of IE, we set the opacity |
||
1149 | // for each sub-DIV separately, rather than for the container DIV. |
||
1150 | tt_SetOpa(tt_aElt[5], opa); |
||
1151 | if(tt_aElt[1]) |
||
1152 | tt_SetOpa(tt_aElt[1], opa); |
||
1153 | if(tt_aV[SHADOW]) |
||
1154 | { |
||
1155 | opa = Math.round(opa * 0.8); |
||
1156 | tt_SetOpa(tt_aElt[7], opa); |
||
1157 | tt_SetOpa(tt_aElt[8], opa); |
||
1158 | } |
||
1159 | } |
||
1160 | function tt_OnScrl() |
||
1161 | { |
||
1162 | tt_scrlX = tt_GetScrollX(); |
||
1163 | tt_scrlY = tt_GetScrollY(); |
||
1164 | } |
||
1165 | function tt_OnCloseBtnOver(iOver) |
||
1166 | { |
||
1167 | var css = tt_aElt[4].style; |
||
1168 | |||
1169 | iOver <<= 1; |
||
1170 | css.background = tt_aV[CLOSEBTNCOLORS][iOver]; |
||
1171 | css.color = tt_aV[CLOSEBTNCOLORS][iOver + 1]; |
||
1172 | } |
||
1173 | function tt_OnLClick(e) |
||
1174 | { |
||
1175 | // Ignore right-clicks |
||
1176 | e = e || window.event; |
||
1177 | if(!((e.button && e.button & 2) || (e.which && e.which == 3))) |
||
1178 | { |
||
1179 | if(tt_aV[CLICKSTICKY] && (tt_iState & 0x4)) |
||
1180 | { |
||
1181 | tt_aV[STICKY] = true; |
||
1182 | tt_iState &= ~0x4; |
||
1183 | } |
||
1184 | else if(tt_aV[CLICKCLOSE]) |
||
1185 | tt_HideInit(); |
||
1186 | } |
||
1187 | } |
||
1188 | function tt_Int(x) |
||
1189 | { |
||
1190 | var y; |
||
1191 | |||
1192 | return(isNaN(y = parseInt(x)) ? 0 : y); |
||
1193 | } |
||
1194 | Number.prototype.Timer = function(s, iT, bUrge) |
||
1195 | { |
||
1196 | if(!this.value || bUrge) |
||
1197 | this.value = window.setTimeout(s, iT); |
||
1198 | } |
||
1199 | Number.prototype.EndTimer = function() |
||
1200 | { |
||
1201 | if(this.value) |
||
1202 | { |
||
1203 | window.clearTimeout(this.value); |
||
1204 | this.value = 0; |
||
1205 | } |
||
1206 | } |
||
1207 | function tt_GetWndCliSiz(s) |
||
1208 | { |
||
1209 | var db, y = window["inner" + s], sC = "client" + s, sN = "number"; |
||
1210 | if(typeof y == sN) |
||
1211 | { |
||
1212 | var y2; |
||
1213 | return( |
||
1214 | // Gecko or Opera with scrollbar |
||
1215 | // ... quirks mode |
||
1216 | ((db = document.body) && typeof(y2 = db[sC]) == sN && y2 && y2 <= y) ? y2 |
||
1217 | // ... strict mode |
||
1218 | : ((db = document.documentElement) && typeof(y2 = db[sC]) == sN && y2 && y2 <= y) ? y2 |
||
1219 | // No scrollbar, or clientarea size == 0, or other browser (KHTML etc.) |
||
1220 | : y |
||
1221 | ); |
||
1222 | } |
||
1223 | // IE |
||
1224 | return( |
||
1225 | // document.documentElement.client+s functional, returns > 0 |
||
1226 | ((db = document.documentElement) && (y = db[sC])) ? y |
||
1227 | // ... not functional, in which case document.body.client+s |
||
1228 | // is the clientarea size, fortunately |
||
1229 | : document.body[sC] |
||
1230 | ); |
||
1231 | } |
||
1232 | function tt_SetOpa(el, opa) |
||
1233 | { |
||
1234 | var css = el.style; |
||
1235 | |||
1236 | tt_opa = opa; |
||
1237 | if(tt_flagOpa == 1) |
||
1238 | { |
||
1239 | if(opa < 100) |
||
1240 | { |
||
1241 | // Hacks for bugs of IE: |
||
1242 | // 1.) Once a CSS filter has been applied, fonts are no longer |
||
1243 | // anti-aliased, so we store the previous 'non-filter' to be |
||
1244 | // able to restore it |
||
1245 | if(typeof(el.filtNo) == tt_u) |
||
1246 | el.filtNo = css.filter; |
||
1247 | // 2.) A DIV cannot be made visible in a single step if an |
||
1248 | // opacity < 100 has been applied while the DIV was hidden |
||
1249 | var bVis = css.visibility != "hidden"; |
||
1250 | // 3.) In IE6, applying an opacity < 100 has no effect if the |
||
1251 | // element has no layout (position, size, zoom, ...) |
||
1252 | css.zoom = "100%"; |
||
1253 | if(!bVis) |
||
1254 | css.visibility = "visible"; |
||
1255 | css.filter = "alpha(opacity=" + opa + ")"; |
||
1256 | if(!bVis) |
||
1257 | css.visibility = "hidden"; |
||
1258 | } |
||
1259 | else if(typeof(el.filtNo) != tt_u) |
||
1260 | // Restore 'non-filter' |
||
1261 | css.filter = el.filtNo; |
||
1262 | } |
||
1263 | else |
||
1264 | { |
||
1265 | opa /= 100.0; |
||
1266 | switch(tt_flagOpa) |
||
1267 | { |
||
1268 | case 2: |
||
1269 | css.KhtmlOpacity = opa; break; |
||
1270 | case 3: |
||
1271 | css.KHTMLOpacity = opa; break; |
||
1272 | case 4: |
||
1273 | css.MozOpacity = opa; break; |
||
1274 | case 5: |
||
1275 | css.opacity = opa; break; |
||
1276 | } |
||
1277 | } |
||
1278 | } |
||
1279 | function tt_Err(sErr, bIfDebug) |
||
1280 | { |
||
1281 | if(tt_Debug || !bIfDebug) |
||
1282 | alert("Tooltip Script Error Message:\n\n" + sErr); |
||
1283 | } |
||
1284 | |||
1285 | //============ EXTENSION (PLUGIN) MANAGER ===============// |
||
1286 | function tt_ExtCmdEnum() |
||
1287 | { |
||
1288 | var s; |
||
1289 | |||
1290 | // Add new command(s) to the commands enum |
||
1291 | for(var i in config) |
||
1292 | { |
||
1293 | s = "window." + i.toString().toUpperCase(); |
||
1294 | if(eval("typeof(" + s + ") == tt_u")) |
||
1295 | { |
||
1296 | eval(s + " = " + tt_aV.length); |
||
1297 | tt_aV[tt_aV.length] = null; |
||
1298 | } |
||
1299 | } |
||
1300 | } |
||
1301 | function tt_ExtCallFncs(arg, sFnc) |
||
1302 | { |
||
1303 | var b = false; |
||
1304 | for(var i = tt_aExt.length; i;) |
||
1305 | {--i; |
||
1306 | var fnc = tt_aExt[i]["On" + sFnc]; |
||
1307 | // Call the method the extension has defined for this event |
||
1308 | if(fnc && fnc(arg)) |
||
1309 | b = true; |
||
1310 | } |
||
1311 | return b; |
||
1312 | } |
||
1313 | |||
1314 | tt_Init(); |