/***********************************************
	sIFR 2.0.2
	Copyright 2004 - 2006 Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben
	This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
***********************************************/



var hasFlash=function(){var a=6;if(navigator.appVersion.indexOf("MSIE")!=-1&&navigator.appVersion.indexOf("Windows")>-1){document.write('<script language="VBScript"\> \non error resume next \nhasFlash = (IsObject(CreateObject("ShockwaveFlash.ShockwaveFlash." & '+a+'))) \n</script\> \n');if(window.hasFlash!=null)return window.hasFlash}if(navigator.mimeTypes&&navigator.mimeTypes["application/x-shockwave-flash"]&&navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){var b=(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description;return parseInt(b.charAt(b.indexOf(".")-1))>=a}return false}();String.prototype.normalize=function(){return this.replace(/\s+/g," ")};if(Array.prototype.push==null){Array.prototype.push=function(){var i=0,a=this.length,b=arguments.length;while(i<b){this[a++]=arguments[i++]}return this.length}}if(!Function.prototype.apply){Function.prototype.apply=function(a,b){var c=[];var d,e;if(!a)a=window;if(!b)b=[];for(var i=0;i<b.length;i++){c[i]="b["+i+"]"}e="a.__applyTemp__("+c.join(",")+");";a.__applyTemp__=this;d=eval(e);a.__applyTemp__=null;return d}}function named(a){return new named.Arguments(a)}named.Arguments=function(a){this.oArgs=a};named.Arguments.prototype.constructor=named.Arguments;named.extract=function(a,b){var c,d;var i=a.length;while(i--){d=a[i];if(d!=null&&d.constructor!=null&&d.constructor==named.Arguments){c=a[i].oArgs;break}}if(c==null)return;for(e in c)if(b[e]!=null)b[e](c[e]);return};var parseSelector=function(){var a=/^([^#.>`]*)(#|\.|\>|\`)(.+)$/;function r(s,t){var u=s.split(/\s*\,\s*/);var v=[];for(var i=0;i<u.length;i++)v=v.concat(b(u[i],t));return v}function b(c,d,e){c=c.normalize().replace(" ","`");var f=c.match(a);var g,h,i,j,k,n;var l=[];if(f==null)f=[c,c];if(f[1]=="")f[1]="*";if(e==null)e="`";if(d==null)d=document;switch(f[2]){case "#":k=f[3].match(a);if(k==null)k=[null,f[3]];g=document.getElementById(k[1]);if(g==null||(f[1]!="*"&&!o(g,f[1])))return l;if(k.length==2){l.push(g);return l}return b(k[3],g,k[2]);case ".":if(e!=">")h=m(d,f[1]);else h=d.childNodes;for(i=0,n=h.length;i<n;i++){g=h[i];if(g.nodeType!=1)continue;k=f[3].match(a);if(k!=null){if(g.className==null||g.className.match("(\\s|^)"+k[1]+"(\\s|$)")==null)continue;j=b(k[3],g,k[2]);l=l.concat(j)}else if(g.className!=null&&g.className.match("(\\s|^)"+f[3]+"(\\s|$)")!=null)l.push(g)}return l;case ">":if(e!=">")h=m(d,f[1]);else h=d.childNodes;for(i=0,n=h.length;i<n;i++){g=h[i];if(g.nodeType!=1)continue;if(!o(g,f[1]))continue;j=b(f[3],g,">");l=l.concat(j)}return l;case "`":h=m(d,f[1]);for(i=0,n=h.length;i<n;i++){g=h[i];j=b(f[3],g,"`");l=l.concat(j)}return l;default:if(e!=">")h=m(d,f[1]);else h=d.childNodes;for(i=0,n=h.length;i<n;i++){g=h[i];if(g.nodeType!=1)continue;if(!o(g,f[1]))continue;l.push(g)}return l}}function m(d,o){if(o=="*"&&d.all!=null)return d.all;return d.getElementsByTagName(o)}function o(p,q){return q=="*"?true:p.nodeName.toLowerCase().replace("html:", "")==q.toLowerCase()}return r}();var sIFR=function(){var a="http://www.w3.org/1999/xhtml";var b=false;var c=false;var d;var ah=[];var al=document;var ak=al.documentElement;var am=window;var au=al.addEventListener;var av=am.addEventListener;var f=function(){var g=navigator.userAgent.toLowerCase();var f={a:g.indexOf("applewebkit")>-1,b:g.indexOf("safari")>-1,c:navigator.product!=null&&navigator.product.toLowerCase().indexOf("konqueror")>-1,d:g.indexOf("opera")>-1,e:al.contentType!=null&&al.contentType.indexOf("xml")>-1,f:true,g:true,h:null,i:null,j:null,k:null};f.l=f.a||f.c;f.m=!f.a&&navigator.product!=null&&navigator.product.toLowerCase()=="gecko";if(f.m&&g.match(/.*gecko\/(\d{8}).*/))f.j=new Number(g.match(/.*gecko\/(\d{8}).*/)[1]);f.n=g.indexOf("msie")>-1&&!f.d&&!f.l&&!f.m;f.o=f.n&&g.match(/.*mac.*/)!=null;if(f.d&&g.match(/.*opera(\s|\/)(\d+\.\d+)/))f.i=new Number(g.match(/.*opera(\s|\/)(\d+\.\d+)/)[2]);if(f.n||(f.d&&f.i<7.6))f.g=false;if(f.a&&g.match(/.*applewebkit\/(\d+).*/))f.k=new Number(g.match(/.*applewebkit\/(\d+).*/)[1]);if(am.hasFlash&&(!f.n||f.o)){var aj=(navigator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description;f.h=parseInt(aj.charAt(aj.indexOf(".")-1))}if(g.match(/.*(windows|mac).*/)==null||f.o||f.c||(f.d&&(g.match(/.*mac.*/)!=null||f.i<7.6))||(f.b&&f.h<7)||(!f.b&&f.a&&f.k<312)||(f.m&&f.j<20020523))f.f=false;if(!f.o&&!f.m&&al.createElementNS)try{al.createElementNS(a,"i").innerHTML=""}catch(e){f.e=true}f.p=f.c||(f.a&&f.k<312);return f}();function at(){return{bIsWebKit:f.a,bIsSafari:f.b,bIsKonq:f.c,bIsOpera:f.d,bIsXML:f.e,bHasTransparencySupport:f.f,bUseDOM:f.g,nFlashVersion:f.h,nOperaVersion:f.i,nGeckoBuildDate:f.j,nWebKitVersion:f.k,bIsKHTML:f.l,bIsGecko:f.m,bIsIE:f.n,bIsIEMac:f.o,bUseInnerHTMLHack:f.p}}if(am.hasFlash==false||!al.getElementsByTagName||!al.getElementById||(f.e&&(f.p||f.n)))return{UA:at()};function af(e){if((!k.bAutoInit&&(am.event||e)!=null)||!l(e))return;b=true;for(var i=0,h=ah.length;i<h;i++)j.apply(null,ah[i]);ah=[]}var k=af;function l(e){if(c==false||k.bIsDisabled==true||((f.e&&f.m||f.l)&&e==null&&b==false)||(al.body==null||al.getElementsByTagName("body").length==0))return false;return true}function m(n){if(f.n)return n.replace(new RegExp("%\d{0}","g"),"%25");return n.replace(new RegExp("%(?!\d)","g"),"%25")}function as(p,q){return q=="*"?true:p.nodeName.toLowerCase().replace("html:", "")==q.toLowerCase()}function o(p,q,r,s,t){var u="";var v=p.firstChild;var w,x,y,z;if(s==null)s=0;if(t==null)t="";while(v){if(v.nodeType==3){z=v.nodeValue.replace("<","&lt;");switch(r){case "lower":u+=z.toLowerCase();break;case "upper":u+=z.toUpperCase();break;default:u+=z}}else if(v.nodeType==1){if(as(v,"a")&&!v.getAttribute("href")==false){if(v.getAttribute("target"))t+="&sifr_url_"+s+"_target="+v.getAttribute("target");t+="&sifr_url_"+s+"="+m(v.getAttribute("href")).replace(/&/g,"%26");u+='<a href="asfunction:_root.launchURL,'+s+'">';s++}else if(as(v,"br"))u+="<br/>";if(v.hasChildNodes()){y=o(v,null,r,s,t);u+=y.u;s=y.s;t=y.t}if(as(v,"a"))u+="</a>"}w=v;v=v.nextSibling;if(q!=null){x=w.parentNode.removeChild(w);q.appendChild(x)}}return{"u":u,"s":s,"t":t}}function A(B){if(al.createElementNS&&f.g)return al.createElementNS(a,B);return al.createElement(B)}function C(D,E,z){var p=A("param");p.setAttribute("name",E);p.setAttribute("value",z);D.appendChild(p)}function F(p,G){var H=p.className;if(H==null)H=G;else H=H.normalize()+(H==""?"":" ")+G;p.className=H}function aq(ar){var a=ak;if(k.bHideBrowserText==false)a=al.getElementsByTagName("body")[0];if((k.bHideBrowserText==false||ar)&&a)if(a.className==null||a.className.match(/\bsIFR\-hasFlash\b/)==null)F(a, "sIFR-hasFlash")}function j(I,J,K,L,M,N,O,P,Q,R,S,r,T){if(!l())return ah.push(arguments);aq();named.extract(arguments,{sSelector:function(ap){I=ap},sFlashSrc:function(ap){J=ap},sColor:function(ap){K=ap},sLinkColor:function(ap){L=ap},sHoverColor:function(ap){M=ap},sBgColor:function(ap){N=ap},nPaddingTop:function(ap){O=ap},nPaddingRight:function(ap){P=ap},nPaddingBottom:function(ap){Q=ap},nPaddingLeft:function(ap){R=ap},sFlashVars:function(ap){S=ap},sCase:function(ap){r=ap},sWmode:function(ap){T=ap}});var U=parseSelector(I);if(U.length==0)return false;if(S!=null)S="&"+S.normalize();else S="";if(K!=null)S+="&textcolor="+K;if(M!=null)S+="&hovercolor="+M;if(M!=null||L!=null)S+="&linkcolor="+(L||K);if(O==null)O=0;if(P==null)P=0;if(Q==null)Q=0;if(R==null)R=0;if(N==null)N="#FFFFFF";if(T=="transparent")if(!f.f)T="opaque";else N="transparent";if(T==null)T="";var p,V,W,X,Y,Z,aa,ab,ac;var ad=null;for(var i=0,h=U.length;i<h;i++){p=U[i];if(p.className!=null&&p.className.match(/\bsIFR\-replaced\b/)!=null)continue;V=p.offsetWidth-R-P;W=p.offsetHeight-O-Q;aa=A("span");aa.className="sIFR-alternate";ac=o(p,aa,r);Z="txt="+m(ac.u).replace(/\+/g,"%2B").replace(/&/g,"%26").replace(/\"/g, "%22").normalize() + S + "&w=" + V + "&h=" + W + ac.t;F(p,"sIFR-replaced");if(ad==null||!f.g){if(!f.g){if(!f.n)p.innerHTML=['<embed class="sIFR-flash" type="application/x-shockwave-flash" src="',J,'" quality="best" wmode="',T,'" bgcolor="',N,'" flashvars="',Z,'" width="',V,'" height="',W,'" sifr="true"></embed>'].join("");else p.innerHTML=['<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" sifr="true" width="',V,'" height="',W,'" class="sIFR-flash"><param name="movie" value="',J,"?",Z,'"></param><param name="quality" value="best"></param><param name="wmode" value="',T,'"></param><param name="bgcolor" value="',N,'"></param> </object>'].join('')}else{if(f.d){ab=A("object");ab.setAttribute("data",J);C(ab,"quality","best");C(ab,"wmode",T);C(ab,"bgcolor",N)}else{ab=A("embed");ab.setAttribute("src",J);ab.setAttribute("quality","best");ab.setAttribute("flashvars",Z);ab.setAttribute("wmode",T);ab.setAttribute("bgcolor",N)}ab.setAttribute("sifr","true");ab.setAttribute("type","application/x-shockwave-flash");ab.className="sIFR-flash";if(!f.l||!f.e)ad=ab.cloneNode(true)}}else ab=ad.cloneNode(true);if(f.g){if(f.d)C(ab,"flashvars",Z);else ab.setAttribute("flashvars",Z);ab.setAttribute("width",V);ab.setAttribute("height",W);ab.style.width=V+"px";ab.style.height=W+"px";p.appendChild(ab)}p.appendChild(aa);if(f.p)p.innerHTML+=""}if(f.n&&k.bFixFragIdBug)setTimeout(function(){al.title=d},0)}function ai(){d=al.title}function ae(){if(k.bIsDisabled==true)return;c=true;if(k.bHideBrowserText)aq(true);if(am.attachEvent)am.attachEvent("onload",af);else if(!f.c&&(al.addEventListener||am.addEventListener)){if(f.a&&f.k>=132&&am.addEventListener)am.addEventListener("load",function(){setTimeout("sIFR({})",1)},false);else{if(al.addEventListener)al.addEventListener("load",af,false);if(am.addEventListener)am.addEventListener("load",af,false)}}else if(typeof am.onload=="function"){var ag=am.onload;am.onload=function(){ag();af()}}else am.onload=af;if(!f.n||am.location.hash=="")k.bFixFragIdBug=false;else ai()}k.UA=at();k.bAutoInit=true;k.bFixFragIdBug=true;k.replaceElement=j;k.updateDocumentTitle=ai;k.appendToClassName=F;k.setup=ae;k.debug=function(){aq(true)};k.debug.replaceNow=function(){ae();k()};k.bIsDisabled=false;k.bHideBrowserText=true;return k}();



if(typeof sIFR == "function" && !sIFR.UA.bIsIEMac){

	sIFR.setup();

};
if(typeof sIFR == "function"){
	sIFR.replaceElement(named({sSelector:"h3.producttitleh3", sFlashSrc:"futura.swf", sColor:"#8f9598", sEmColor:"#FF6600", sStrongColor:"#FF0000", sSpanColor:"#c9ad2f", sLinkColor:"#8f9598", sBgColor:"#FFFFFF", sWmode: "transparent", sHoverColor:"#eda700"}));
	sIFR.replaceElement(named({sSelector:"h3", sFlashSrc:"futura.swf", sCase:"upper", sColor:"#8f9598", sEmColor:"#FF6600", sStrongColor:"#FF0000", sSpanColor:"#c9ad2f", sLinkColor:"#8f9598", sBgColor:"#FFFFFF", sWmode: "transparent", sHoverColor:"#eda700"}));
}



/***********************************************
* Tab Content script v2.0- © Dynamic Drive DHTML code library (www.dynamicdrive.com)
* This notice MUST stay intact for legal use
* Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code
***********************************************/



//** Tab Content script v2.0- © Dynamic Drive DHTML code library (http://www.dynamicdrive.com)
//** Updated Oct 7th, 07 to version 2.0. Contains numerous improvements:
//   -Added Auto Mode: Script auto rotates the tabs based on an interval, until a tab is explicitly selected
//   -Ability to expand/contract arbitrary DIVs on the page as the tabbed content is expanded/ contracted
//   -Ability to dynamically select a tab either based on its position within its peers, or its ID attribute (give the target tab one 1st)
//   -Ability to set where the CSS classname "selected" get assigned- either to the target tab's link ("A"), or its parent container 

////NO NEED TO EDIT BELOW////////////////////////

function ddtabcontent(tabinterfaceid){
	this.tabinterfaceid=tabinterfaceid //ID of Tab Menu main container
	this.tabs=document.getElementById(tabinterfaceid).getElementsByTagName("a") //Get all tab links within container
	this.enabletabpersistence=true
	this.hottabspositions=[] //Array to store position of tabs that have a "rel" attr defined, relative to all tab links, within container
	this.subcontentids=[] //Array to store ids of the sub contents ("rel" attr values)
	this.revcontentids=[] //Array to store ids of arbitrary contents to expand/contact as well ("rev" attr values)
	this.selectedClassTarget="link" //keyword to indicate which target element to assign "selected" CSS class ("linkparent" or "link")
}

ddtabcontent.getCookie=function(Name){ 
	var re=new RegExp(Name+"=[^;]+", "i"); //construct RE to search for target name/value pair
	//if (document.cookie.match(re)) //if cookie found
		//return document.cookie.match(re)[0].split("=")[1] //return its value
	return ""
}

ddtabcontent.setCookie=function(name, value){
	document.cookie = name+"="+value+";path=/" //cookie value is domain wide (path=/)
}

ddtabcontent.prototype={

	expandit:function(tabid_or_position){ //PUBLIC function to select a tab either by its ID or position(int) within its peers
		this.cancelautorun() //stop auto cycling of tabs (if running)
		var tabref=""
		try{
			if (typeof tabid_or_position=="string" && document.getElementById(tabid_or_position).getAttribute("rel")) //if specified tab contains "rel" attr
				tabref=document.getElementById(tabid_or_position)
			else if (parseInt(tabid_or_position)!=NaN && this.tabs[tabid_or_position].getAttribute("rel")) //if specified tab contains "rel" attr
				tabref=this.tabs[tabid_or_position]
		}
		catch(err){alert("Invalid Tab ID or position entered!")}
		if (tabref!="") //if a valid tab is found based on function parameter
			this.expandtab(tabref) //expand this tab
	},

	setpersist:function(bool){ //PUBLIC function to toggle persistence feature
			this.enabletabpersistence=bool
	},

	setselectedClassTarget:function(objstr){ //PUBLIC function to set which target element to assign "selected" CSS class ("linkparent" or "link")
		this.selectedClassTarget=objstr || "link"
	},

	getselectedClassTarget:function(tabref){ //Returns target element to assign "selected" CSS class to
		return (this.selectedClassTarget==("linkparent".toLowerCase()))? tabref.parentNode : tabref
	},

	expandtab:function(tabref){
		var subcontentid=tabref.getAttribute("rel") //Get id of subcontent to expand
		//Get "rev" attr as a string of IDs in the format ",john,george,trey,etc," to easily search through
		var associatedrevids=(tabref.getAttribute("rev"))? ","+tabref.getAttribute("rev").replace(/\s+/, "")+"," : ""
		this.expandsubcontent(subcontentid)
		this.expandrevcontent(associatedrevids)
		for (var i=0; i<this.tabs.length; i++){ //Loop through all tabs, and assign only the selected tab the CSS class "selected"
			this.getselectedClassTarget(this.tabs[i]).className=(this.tabs[i].getAttribute("rel")==subcontentid)? "selected" : ""
		}
		if (this.enabletabpersistence) //if persistence enabled, save selected tab position(int) relative to its peers
			ddtabcontent.setCookie(this.tabinterfaceid, tabref.tabposition)
	},

	expandsubcontent:function(subcontentid){
		for (var i=0; i<this.subcontentids.length; i++){
			var subcontent=document.getElementById(this.subcontentids[i]) //cache current subcontent obj (in for loop)
			subcontent.style.display=(subcontent.id==subcontentid)? "block" : "none" //"show" or hide sub content based on matching id attr value
		}
	},


	expandrevcontent:function(associatedrevids){
		var allrevids=this.revcontentids
		for (var i=0; i<allrevids.length; i++){ //Loop through rev attributes for all tabs in this tab interface
			//if any values stored within associatedrevids matches one within allrevids, expand that DIV, otherwise, contract it
			document.getElementById(allrevids[i]).style.display=(associatedrevids.indexOf(","+allrevids[i]+",")!=-1)? "block" : "none"
		}
	},

	autorun:function(){ //function to auto cycle through and select tabs based on a set interval
		var currentTabIndex=this.automode_currentTabIndex //index within this.hottabspositions to begin
		var hottabspositions=this.hottabspositions //Array containing position numbers of "hot" tabs (those with a "rel" attr)
		this.expandtab(this.tabs[hottabspositions[currentTabIndex]])
		this.automode_currentTabIndex=(currentTabIndex<hottabspositions.length-1)? currentTabIndex+1 : 0 //increment currentTabIndex
	},

	cancelautorun:function(){
		if (typeof this.autoruntimer!="undefined")
			clearInterval(this.autoruntimer)
	},

	init:function(automodeperiod){
		var persistedtab=ddtabcontent.getCookie(this.tabinterfaceid) //get position of persisted tab (applicable if persistence is enabled)
		var persisterror=true //Bool variable to check whether persisted tab position is valid (can become invalid if user has modified tab structure)
		this.automodeperiod=automodeperiod || 0
		for (var i=0; i<this.tabs.length; i++){
			this.tabs[i].tabposition=i //remember position of tab relative to its peers
			if (this.tabs[i].getAttribute("rel")){
				var tabinstance=this
				this.hottabspositions[this.hottabspositions.length]=i //store position of "hot" tab ("rel" attr defined) relative to its peers
				this.subcontentids[this.subcontentids.length]=this.tabs[i].getAttribute("rel") //store id of sub content ("rel" attr value)
				this.tabs[i].onclick=function(){
					tabinstance.expandtab(this)
					tabinstance.cancelautorun() //stop auto cycling of tabs (if running)
					return false
				}
				if (this.tabs[i].getAttribute("rev")){ //if "rev" attr defined, store each value within "rev" as an array element
					this.revcontentids=this.revcontentids.concat(this.tabs[i].getAttribute("rev").split(/\s*,\s*/))
				}
				if (this.enabletabpersistence && parseInt(persistedtab)==i || !this.enabletabpersistence && this.getselectedClassTarget(this.tabs[i]).className=="selected"){
					this.expandtab(this.tabs[i]) //expand current tab if it's the persisted tab, or if persist=off, carries the "selected" CSS class
					persisterror=false //Persisted tab (if applicable) was found, so set "persisterror" to false
					//If currently selected tab's index(i) is greater than 0, this means its not the 1st tab, so set the tab to begin in automode to 1st tab:
					this.automode_currentTabIndex=(i>0)? 0 : 1
				}
			}
		} //END for loop
		if (persisterror) //if an error has occured while trying to retrieve persisted tab (based on its position within its peers)
			this.expandtab(this.tabs[this.hottabspositions[0]]) //Just select first tab that contains a "rel" attr
		if (parseInt(this.automodeperiod)>500 && this.hottabspositions.length>1){
			this.automode_currentTabIndex=this.automode_currentTabIndex || 0
			this.autoruntimer=setInterval(function(){tabinstance.autorun()}, this.automodeperiod)
		}
	} //END int() function

} //END Prototype assignment


/***********************************************/

var preloaded = new Array();

function preload_images() {

    for (var i = 0; i < arguments.length; i++){

        preloaded[i] = document.createElement('img');

        preloaded[i].setAttribute('src',arguments[i]);

    };

};

preload_images(

    'templates/Original/images/header.gif',

    'templates/Original/images/bg.gif',

    'templates/Original/images/leftcolbgbody.jpg',

    'templates/Original/images/infoboxbody.gif',

    'templates/Original/images/infoboxheader.gif',

    'templates/Original/images/infoboxbodyright.gif',

    'templates/Original/images/infoboxheaderright.gif',

    'templates/Original/images/bgimagesmall.gif',

	'templates/Original/images/bgfeaturedfirst.gif',

	'templates/Original/images/bgfeaturedlast.gif',

	'templates/Original/images/bgfeatured.gif',

	'templates/Original/images/contentbg.jpg',

	'templates/Original/images/leftbg.jpg',

	'templates/Original/images/boxtop.gif',

	'templates/Original/images/boxbottom.gif',

	'templates/Original/images/leftcolbgbottom.gif',

	'templates/Original/images/leftcolbgtop.gif',

	'templates/Original/images/sidebgimage.gif',

	'templates/Original/images/productbgtop.png',

	'templates/Original/images/bgproductcontrol.gif',

	'templates/Original/images/productbg.jpg',

	'templates/Original/images/bodyshadow.png',

	'templates/Original/images/subselected.gif',

	'templates/Original/images/dottedselected.gif',

	'templates/Original/images/dotted.gif'

);
/***********************************************/


function checkAll(field) 

{

for (i = 0; i < field.length; i++)

	field[i].checked = true ;

};



function uncheckAll(field) 

{

for (i = 0; i < field.length; i++)

	field[i].checked = false ;

};

/**
 * Tooltip.js
 *
 * Advanced Tooltip class
 *
 * WARNING: Due to an IE bug, Tooltips will NOT display on top of a <select> element.
 *
 * @copyright Davey Shafik (c) 2005 All Rights Reserved
 * @authors Davey Shafik <davey@php.net>
 * @version 0.6.0
 * @license MIT-style <http://tooltip.crtx.org/LICENSE>
 * @todo Fix accessibility, make it possible to tab in/out of tooltips, and look into CSS Voice stuff
 * @todo Add ability to change the events *per* Tooltip
 */

/**
 * Add an Array.contains() method, mimics PHPs in_array() function
 */

Array.prototype.contains = function (value)
{
	for (var i = 0; i < this.length; i++) {
		if (this[i] == value) {
			return true;
		}
	}
	return false;
}

/**
 * Tooltip Object definition
 */
var Tooltip = {
	/**
	 * @var string|Array An event name or an array of event names on which to trigger showing the Tooltip
	 */
	showEvent: "click",

	/**
	 * @var string|Array An event name or an array of event names on which to trigger hiding the Tooltip
	 */
	hideEvent: "click",

	/**
	 * @var float Duration of the fade events, in seconds
	 * @author Idea contributed by Richard Thomas <cyberlot@cyberlot.net>
	 */
	fade: 0.5,

	/**
	 * @var string Close Link Text
	 */
	closeText: "Close",

	/**
	 * @var function Set the method which will be called for showing the tooltip
	 */
	showMethod: Effect.Appear,

	/**
	 * @var function Set the method which will be called for hiding the tooltip
	 */
	hideMethod: Effect.Fade,

	/**
     * @var boolean Whether the Tooltip should follow the mouse or not. Warning: Cheesy!
     */
    autoFollowMouse: false,

	/**
	 * @var integer If set, the Tooltip will automatically hide after X seconds
     *
     * When followMouse is true, the mouseout event does not trigger the hide callback
     * till X has passed. This is to allow the user to move a little off the element -
     * which is especially useful when it's an inline element such as a link.
     */
    autoHideTimeout: 40,

	/**
	 * @var boolean Allow user to click anywhere to hide current tooltip
	 */
	autoHideClick: true,

	/**
	 * @var boolean If set to true, the Tooltip will be displayed (static) at the current Mouse Cursor location.
	 */
	autoMoveToCursor: true,

	/**
	 * @const int Indicate that the current tooltip should be used
	 */
	CURRENT_TOOLTIP: 1,

	/**
	 * @var object Currently shown Tooltip
	 */
	_current: false,

	/**
	 * Initial Setup
	 *
	 * Find all standard tooltips and auto-initialize them
	 *
	 * @return void
	 */
	setup: function ()
	{
		match_class = new RegExp("^(.*)\s?tooltip\s?(.*)$", 'i');
		match_for = new RegExp("^.*\s?for_(.*)\s?.*$", 'i');
		var divs = document.getElementsByTagName('div');
		var for_result;
		if (divs.length > 0) {
            // Automatically register the mouseout event if followMouse = true and autoHideTimeout is being used
            if (Tooltip.autoFollowMouse && Tooltip.autoHideTimeout) {
                Tooltip.hideEvent[Tooltip.hideEvent.length] = "mouseout";
            }

			if (Tooltip.autoHideClick) {
				Tooltip._attachEvent(document.getElementsByTagName("body").item(0), "clickanywhere");
			}

			for (var i = 0; i < divs.length; i++) {
				if (divs.item(i).className.match(match_class)) {
					for_result = divs.item(i).className.match(match_for);
					if (for_result && for_result.length > 0) {
						if (document.getElementById(for_result[1])) {
							var activator = document.getElementById(for_result[1]);
						}
					} else {
						var foundPrevious = false;
						var activator = divs.item(i);
						while (foundPrevious == false) {
							activator = activator.previousSibling;
							if (activator.tagName) {
								foundPrevious = true;
								break;
							}
						}
					}
					activator.Tooltip = divs.item(i);
					// Just in case you need to access the activator from the Tooltip (i.e. a "Close" button)
					if (!activator.id) {
						activator.id = "tt" + i;
					}
					activator.Tooltip.activator = activator.id ;
	  				Tooltip.init(activator);
				}
			}
		}
	},


	/**
	 * Initiate an Activator/Tooltip for events and display
	 *
	 * @param activator DomElement The element to which the Tooltip show/hide events are attached
	 * @return void
	 */
	init: function (activator)
	{
		var tooltip = activator.Tooltip;
		activator.Tooltip.style.visibility = "hidden";

		Tooltip._attachEvent(activator, "toggle");


		// Remove Link Hrefs
		if (activator.tagName.toLowerCase() == "a") {
			try {
				activator.removeAttribute("href");
				activator.style.cursor = (document.links[0].style.cursor.length > 0) ? document.links[0].style.cursor : "pointer";
			}
			catch (e) {
				//DEBUG alert(e.message);
			}
		}

        // Make sure the Tooltip is on top, only works if the element has position: absolute; in the CSS
        tooltip.style.zIndex = "1000";

		if (Tooltip.autoFollowMouse != true) {
			// Create the <p><a href="#">Close</a></p> and add it to the Tooltip

			// <p> element
			var p = document.createElement('p');

			// <p> styles
			p.style.textAlign = "right";
			p.style.padding.padding = "0";
			p.style.margin = "0";

			// <p> class name
			p.className = "close";

			// <a> element
			var link = document.createElement('a');

			// Set the Tooltip var to the tooltip element
			link.Tooltip = tooltip;

			link.style.cursor = "pointer";

			// Add the click handler
			Tooltip._attachEvent(link, "click");

			// "Close" text node
			var close = document.createTextNode(Tooltip.closeText);

			// Append the text to the <a> element
			link.appendChild(close);

			// Append the <a> to the <p> element
			p.appendChild(link);

			// Stick the entire thing on the end of the Tooltip
			tooltip.appendChild(p, tooltip.firstChild);
		}
	},

	/**
	 * Manually add a Tooltip
	 *
	 * When passed an Activator and Tooltip element or ID, it is setup as a Tooltip
	 *
	 * @param activator Activator Element or ID, this is the element that activates the Tooltip
	 * @param tooltip Tooltip Element or ID, this is the Tooltip element itself that is shown/hidden
	 */
	add: function (activator, tooltip)
	{
		if (typeof activator == 'string') {
			activator = document.getElementById(activator);
		}
		if (typeof tooltip == 'string') {
			tooltip = document.getElementById(tooltip);
		}

		activator.Tooltip = tooltip;
		Tooltip.init(activator);
	},

	/**
	 * Toggle the Tooltip
         *
         * Shows or Hides the Tooltip
         *
         * @param activator Activator Element
         * @return void
	 */

	toggle: function (activator, event)
	{
		try {
			if (activator == 1) {
				activator = document.getElementById(window._currentTT);
			}
		}
		catch (e) { }

		if (Tooltip.autoHideClick && event.type == "click") {
			var close_class = new RegExp("^(.*)\s?close\s?(.*)$", 'i');
			var tooltip_class = new RegExp("^(.*)\s?tooltip\s?(.*)$", 'i');
			if (event.srcElement) {
				var node = event.srcElement;
			} else if (event.fromElement) {
				var node = event.fromElement;
			} else if (event.target) {
				var node = event.target;
			}
			if (node.className == null  || !node.className.match(close_class)) {
				var isWithinTooltip = false;
				while (!isWithinTooltip && node.parentNode) {
					// Check if the parent is a close element first, if so, we can break
					// and we still want to close the tooltip
					if (node.className && node.className.match(close_class)) {
						break;
					}
					if (node.className && node.className != null && node.className.match(tooltip_class)) {
						isWithinTooltip = true;
						break;
					}
					node = node.parentNode;
				}
			}

			if (isWithinTooltip) {
				return;
			}
		}

		try {
			if (activator.Tooltip.isVisible) {
				Tooltip._hide(activator, event);
			} else {
				Tooltip._show(activator, event);
			}
		}
		catch (e) {
			try {
				Tooltip._hide(activator, event);
			}
			catch (e) { }
		}
		event.cancelBubble = true;
		try {
			event.stopPropagation();
		}
		catch (e) { }
	},

	/**
	 * Show the Tooltip
	 *
	 * Displays the Tooltip and sets the hide events up. You should never need to call this manually.
	 *
	 * @param activator Activator Element
    * @private
	 * @return void
	 */
	_show: function (activator, event, ignore_event)
	{
		if (Tooltip.autoHideClick && window._currentTT) {
			Tooltip._hide(document.getElementById(window._currentTT), event, true);
		}

		window._currentTT = activator.id;

		if (ignore_event == true || typeof Tooltip.showEvent == "string" || Tooltip.showEvent.constructor && Tooltip.showEvent.constructor == Array && Tooltip.showEvent.contains(event.type)) {
			activator.Tooltip.isVisible = true;
         if (Tooltip.autoFollowMouse || Tooltip.autoMoveToCursor) {
            Tooltip._follow(activator, event);
         }
			try {
				if (typeof Effect) {
					Element.setOpacity(activator.Tooltip, 0.1);
					activator.Tooltip.style.visibility = "visible";
					Tooltip.showMethod(activator.Tooltip, {duration:Tooltip.fade});
				} else {
					activator.Tooltip.style.visibility = "visible";
				}
			}
			catch (e) {
				try {
					activator.Tooltip.style.visibility = "visible";
				}
				catch (e) {
					//DEBUG alert(tooltip.id);
				}
			}
            if (Tooltip.autoFollowMouse) {
                Tooltip._attachEvent(activator, "follow");
            }

            if (Tooltip.autoHideTimeout && !Tooltip.autoFollowMouse) {
                activator.timer = setTimeout(function () {
                                            try {
                                                Tooltip.hideMethod(activator.Tooltip, {duration:Tooltip.fade});
                                            }
                                            catch (e) {
                                                activator.Tooltip.style.visibility = "hidden"; }
                                            }, Tooltip.autoHideTimeout * 1000);
            }

			return;
		}
	},

	/**
	 * Hide the Tooltip
	 *
	 * Hides the Tooltip and sets the show events up. You should never need to call this manually.
	 *
	 * @param activator Activator Element
         * @private
	 * @return void
	 */
	_hide: function (activator, event, ignore_event)
	{
		if (!activator) {
			return;
		}

		event = event.type;

		var tooltip = activator.Tooltip;
        // We need to defer this
        if (event == "mouseout" && Tooltip.autoFollowMouse) {
            activator.timer = setTimeout(function () {
                                            try {
                                                Tooltip.hideMethod(tooltip, {duration:Tooltip.fade});
                                            }
                                            catch (e) {
                                                activator.Tooltip.style.visibility = "hidden"; }
                                            }, Tooltip.autoHideTimeout * 1000);
        } else if (ignore_event == true || ((typeof Tooltip.hideEvent == "string" && Tooltip.hideEvent == event) || Tooltip.hideEvent.constructor && Tooltip.hideEvent.constructor == Array && Tooltip.hideEvent.contains(event))) {
			activator.Tooltip.isVisible = false;
			try {
				Tooltip.hideMethod(tooltip, {duration:Tooltip.fade});
			}
			catch (e) {
				activator.Tooltip.style.visibility = "hidden";
			}

			if (Tooltip.autoFollowMouse) {
				Tooltip._removeEvent(activator, "follow");
			}

			window._currentTT = false;

			return;
		}
	},

    _follow: function (activator, event)
    {
      if (activator.timer) {
	      try {
	         clearTimeout(activator.timer);
         }
         catch (e) { }
      }

		var winWidth, winHeight, d=document;
		if (typeof window.innerWidth!='undefined') {
			winWidth = window.innerWidth;
			winHeight = window.innerHeight;
		} else {
			if (d.documentElement && typeof d.documentElement.clientWidth!='undefined' && d.documentElement.clientWidth!=0) {
				winWidth = d.documentElement.clientWidth
				winHeight = d.documentElement.clientHeight
			} else {
				if (d.body && typeof d.body.clientWidth!='undefined') {
					winWidth = d.body.clientWidth
					winHeight = d.body.clientHeight
				}
			}
		}

		var tooltipWidth, tooltipHeight;
		if (activator.Tooltip.currentStyle) {
			tooltipWidth = activator.Tooltip.currentStyle.width;
			tooltipHeight = activator.Tooltip.currentStyle.height;
		} else if (window.getComputedStyle) {
			tooltipWidth = window.getComputedStyle(activator.Tooltip, null).width;
			tooltipHeight = window.getComputedStyle(activator.Tooltip, null).height;
		}

      activator.Tooltip.style.position = "absolute";

		if (event.pageY) {
			var top = event.pageY;
			var left = event.pageX;
		} else if (event.clientY) {
			// put an If here instead, ?: doesn't seem to work
			if (document.body.scrollTop > document.documentElement.scrollTop) {
				var top = event.clientY + document.body.scrollTop;
			} else {
				var top = event.clientY + document.documentElement.scrollTop;
			}

			if (document.body.scrollLeft > document.documentElement.scrollLeft) {
				var left = event.clientX + document.body.scrollLeft;
			} else {
				var left = event.clientX + document.documentElement.scrollLeft;
			}
		}

		// Make sure the Tooltip doesn't go off the page. The 1.2 comes from Trial and error. 
		// We don't track the height, its possible (and much more common) that the height of an item will be more than the browser pane
		if ((left + parseInt(tooltipWidth)) > winWidth) {
			left = winWidth - parseInt(tooltipWidth) * 1.2;
		}

		activator.Tooltip.style.top = top + "px";
		activator.Tooltip.style.left = left + "px";
    },

	/**
	 * Attach show/hide/load events
	 *
	 * This method removes any existing events first
	 * in case show/hide are the same.
	 *
	 * @param element Element to which events should be attached
	 * @param event Event for which events are being registered. One of show/hide/load/click.
	 */

	_attachEvent: function (element, event)
	{
		var i;
		var events = new Array();
        if (event == "toggle") {
			if (Tooltip.showEvent.constructor && Tooltip.showEvent.constructor == Array) {
                for (i = 0; i < Tooltip.showEvent.length; i++) {
                    events.push(Tooltip.showEvent[i]);
                    if (element.addEventListener) {
                        element.addEventListener(Tooltip.showEvent[i], function (e) { Tooltip.toggle(element, e, false); return false; }, false);
                    } else if (element.attachEvent) {
                        element.attachEvent('on' + Tooltip.showEvent[i], function (e) { Tooltip.toggle(element, e, false); return false; });
                    }
                }
            } else {
                events.push(Tooltip.showEvent);
                if (element.addEventListener) {
                    element.addEventListener(Tooltip.showEvent, function (e) { Tooltip.toggle(element, e, false); return false; }, false);
                } else if (element.attachEvent) {
                    element.attachEvent('on' + Tooltip.showEvent, function (e) { Tooltip.toggle(element, e, false); return false; });
                }
            }

            if (Tooltip.hideEvent.constructor && Tooltip.hideEvent.constructor == Array) {
                for (i = 0; i < Tooltip.hideEvent.length; i++) {
                    if (!events.contains(Tooltip.hideEvent[i])) {
                        events.push(Tooltip.hideEvent[i]);
                        if (element.addEventListener) {
                            element.addEventListener(Tooltip.hideEvent[i], function (e) { Tooltip.toggle(element, e, false); return false; }, false);
                        } else if (element.attachEvent) {
                            element.attachEvent('on' + Tooltip.hideEvent[i], function (e) { Tooltip.toggle(element, e, false); return false; });
                        }
                    }
                }
            } else {
                if (!events.contains(Tooltip.hideEvent)) {
                    events.push(Tooltip.hideEvent);
                    if (element.addEventListener) {
                        element.addEventListener(Tooltip.hideEvent, function (e) { Tooltip.toggle(element, e, false); return false; }, false);
                    } else if (element.attachEvent) {
                        element.attachEvent('on' + Tooltip.hideEvent, function (e) { Tooltip.toggle(element, e, false); return false; });
                    }
                }
            }
        } else if (event == "load") {
            if (element.addEventListener) {
                element.addEventListener("load", function () { Tooltip.setup(); }, false);
            } else if (element.attachEvent) {
                element.attachEvent('on' + "load", function () { Tooltip.setup(); });
            }
        } else if (event == "click") {
            if (element.addEventListener) {
                element.addEventListener("click", function (e) { Tooltip.toggle(element, e, true); }, false);
            } else if (element.attachEvent) {
                element.attachEvent('on' + "click", function (e) { Tooltip.toggle(element, e, true); });
            }
        } else if (event == "follow") {
            if (element.addEventListener) {
                element.addEventListener("mousemove", function (e) { Tooltip._follow(element, e); }, false);
            }  else {
                element.attachEvent('onmousemove', function (e) { Tooltip._follow(element, e);  });
            }
        } else if (event == "clickanywhere") {
			if (element.addEventListener) {
                element.addEventListener("click", function (e) { Tooltip.toggle(Tooltip.CURRENT_TOOLTIP, e, false); }, false);
            }  else {
                element.attachEvent('onclick', function (e) { Tooltip.toggle(Tooltip.CURRENT_TOOLTIP, e, false);  });
            }
		}
	},

    _removeEvent: function (element, event)
    {
        try {
            if (event == "follow") {
                if (element.addEventListener) {
                    element.removeEventListener("mousemove", function (e) { Tooltip._follow(element, e); }, false);
                } else {
                    element.dettachEvent('onmousemove', function (e) { Tooltip._follow(element, e); });
                }
            }
        }
        catch (e) {}
    }
}

// Start the Tooltips in motion
try {
	Tooltip._attachEvent(window, 'load');
}
catch (e) { }
