PageSourceSearch

https://www.minoritycounselor.com/jscript/wz_tooltip.js

js minoritycounselor.com collected 2026-10-06 07:32:23 UTC 35,077 bytes, 1,238 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.