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