// $Id: X.js,v 1.1.1.1 2009/04/02 00:08:57 cmanley Exp $
// Parts of X, a Cross-Browser Javascript Library, Distributed under the terms of the GNU LGPL
// Copyright 2001-2007 Michael Foster (Cross-Browser.com)


function xGetElementById(e) {
	if(typeof(e)=='string') {
		if(document.getElementById) e=document.getElementById(e);
		else if(document.all) e=document.all[e];
		else e=null;
	}
	return e;
}


// xGetElementsByTagName r5
function xGetElementsByTagName(t,p) {
	var list = null;
	t = t || '*';
	p = xGetElementById(p) || document;
	if (typeof p.getElementsByTagName != 'undefined') { // DOM1
		list = p.getElementsByTagName(t);
		if (t=='*' && (!list || !list.length)) list = p.all; // IE5 '*' bug
	}
	else { // IE4 object model
		if (t=='*') list = p.all;
		else if (p.all && p.all.tags) list = p.all.tags(t);
	}
	return list || [];
}


// xGetElementsByClassName(sClsName, oParentEle, sTagName, fnCallback) r5, Copyright 2002-2007 Michael Foster (Cross-Browser.com)
function xGetElementsByClassName(c,p,t,f) {
	var r = new Array();
	var re = new RegExp("(^|\\s)"+c+"(\\s|$)");
	//var e = p.getElementsByTagName(t);
	var e = xGetElementsByTagName(t,p); // See xml comments.
	for (var i = 0; i < e.length; ++i) {
		if (re.test(e[i].className)) {
			r[r.length] = e[i];
			if (f) f(e[i]);
		}
	}
	return r;
}


// http://cross-browser.com/x/lib/view.php?sym=xAddEventListener
// Modified by Craig Manley to accept arrays of event names.
// Modified by Craig Manley to support stacked on* events in old browsers.
function xAddEventListener(e,eT,eL,cap) {
	if ((typeof(eT) == 'object') && (eT.constructor.toString().indexOf('function Array()') != -1)) {
		for (var i=0; i<eT.length; i++) {
			xAddEventListener(e,eT[i],eL,cap);
		}
	}
	else {
		if(!(e=xGetElementById(e)))return;
		eT=eT.toLowerCase();
		if(e.addEventListener)e.addEventListener(eT,eL,cap||false);
		else if(e.attachEvent)e.attachEvent('on'+eT,eL);
		//else e['on'+eT]=eL;
		else {
			if (e['on'+eT]) {
				var f = e['on'+eT];
				e['on'+eT] = function() {
					f();
					eL();
				}
			}
			else {
				e['on'+eT]=eL;
			}
		}
	}
}


// xCamelize r1
function xCamelize(cssPropStr) {
	var i, c, a = cssPropStr.split('-');
	var s = a[0];
	for (i=1; i<a.length; ++i) {
		c = a[i].charAt(0);
		s += a[i].replace(c, c.toUpperCase());
	}
	return s;
}


// xGetComputedStyle r7
function xGetComputedStyle(e, p, i) {
	if(!(e=xGetElementById(e))) return null;
	var s, v = 'undefined', dv = document.defaultView;
	if(dv && dv.getComputedStyle){
		s = dv.getComputedStyle(e,'');
		if (s) v = s.getPropertyValue(p);
	}
	else if(e.currentStyle) {
		v = e.currentStyle[xCamelize(p)];
	}
	else return null;
	return i ? (parseInt(v) || 0) : v;
}


// xDef r1
function xDef() {
	for(var i=0; i<arguments.length; ++i){if(typeof(arguments[i])=='undefined') return false;}
	return true;
}


// xStr r1
function xStr(s) {
	for(var i=0; i<arguments.length; ++i){if(typeof(arguments[i])!='string') return false;}
	return true;
}


// xNum r2
function xNum() {
	for(var i=0; i<arguments.length; ++i){if(isNaN(arguments[i]) || typeof(arguments[i])!='number') return false;}
	return true;
}


// xLeft r2
function xLeft(e, iX) {
	if(!(e=xGetElementById(e))) return 0;
	var css=xDef(e.style);
	if (css && xStr(e.style.left)) {
		if(xNum(iX)) e.style.left=iX+'px';
		else {
			iX=parseInt(e.style.left);
			if(isNaN(iX)) iX=xGetComputedStyle(e,'left',1);
			if(isNaN(iX)) iX=0;
		}
	}
	else if(css && xDef(e.style.pixelLeft)) {
		if(xNum(iX)) e.style.pixelLeft=iX;
		else iX=e.style.pixelLeft;
	}
	return iX;
}


// xTop r2
function xTop(e, iY) {
	if(!(e=xGetElementById(e))) return 0;
	var css=xDef(e.style);
	if(css && xStr(e.style.top)) {
		if(xNum(iY)) e.style.top=iY+'px';
		else {
			iY=parseInt(e.style.top);
			if(isNaN(iY)) iY=xGetComputedStyle(e,'top',1);
			if(isNaN(iY)) iY=0;
		}
	}
	else if(css && xDef(e.style.pixelTop)) {
		if(xNum(iY)) e.style.pixelTop=iY;
		else iY=e.style.pixelTop;
	}
	return iY;
}


// xWidth r6
function xWidth(e,w) {
	if(!(e=xGetElementById(e))) return 0;
	if (xNum(w)) {
		if (w<0) w = 0;
		else w=Math.round(w);
	}
	else w=-1;
	var css=xDef(e.style);
	if (e == document || e.tagName.toLowerCase() == 'html' || e.tagName.toLowerCase() == 'body') {
		w = xClientWidth();
	}
	else if(css && xDef(e.offsetWidth) && xStr(e.style.width)) {
		if(w>=0) {
			var pl=0,pr=0,bl=0,br=0;
			if (document.compatMode=='CSS1Compat') {
				var gcs = xGetComputedStyle;
				pl=gcs(e,'padding-left',1);
				if (pl !== null) {
					pr=gcs(e,'padding-right',1);
					bl=gcs(e,'border-left-width',1);
					br=gcs(e,'border-right-width',1);
				}
				// Should we try this as a last resort?
				// At this point getComputedStyle and currentStyle do not exist.
				else if(xDef(e.offsetWidth,e.style.width)){
					e.style.width=w+'px';
					pl=e.offsetWidth-w;
				}
			}
			w-=(pl+pr+bl+br);
			if(isNaN(w)||w<0) return;
			else e.style.width=w+'px';
		}
		w=e.offsetWidth;
	}
	else if(css && xDef(e.style.pixelWidth)) {
		if(w>=0) e.style.pixelWidth=w;
		w=e.style.pixelWidth;
	}
	return w;
}


// xHeight r6
function xHeight(e,h) {
	if(!(e=xGetElementById(e))) return 0;
	if (xNum(h)) {
		if (h<0) h = 0;
		else h=Math.round(h);
	}
	else h=-1;
	var css=xDef(e.style);
	if (e == document || e.tagName.toLowerCase() == 'html' || e.tagName.toLowerCase() == 'body') {
		h = xClientHeight();
	}
	else if(css && xDef(e.offsetHeight) && xStr(e.style.height)) {
		if(h>=0) {
			var pt=0,pb=0,bt=0,bb=0;
			if (document.compatMode=='CSS1Compat') {
				var gcs = xGetComputedStyle;
				pt=gcs(e,'padding-top',1);
				if (pt !== null) {
					pb=gcs(e,'padding-bottom',1);
					bt=gcs(e,'border-top-width',1);
					bb=gcs(e,'border-bottom-width',1);
				}
				// Should we try this as a last resort?
				// At this point getComputedStyle and currentStyle do not exist.
				else if(xDef(e.offsetHeight,e.style.height)){
					e.style.height=h+'px';
					pt=e.offsetHeight-h;
				}
			}
			h-=(pt+pb+bt+bb);
			if(isNaN(h)||h<0) return;
			else e.style.height=h+'px';
		}
		h=e.offsetHeight;
	}
	else if(css && xDef(e.style.pixelHeight)) {
		if(h>=0) e.style.pixelHeight=h;
		h=e.style.pixelHeight;
	}
	return h;
}


// xPageX r2
function xPageX(e) {
	var x = 0;
	e = xGetElementById(e);
	while (e) {
		if (xDef(e.offsetLeft)) x += e.offsetLeft;
		e = xDef(e.offsetParent) ? e.offsetParent : null;
	}
	return x;
}


// xPageY r4
function xPageY(e) {
	var y = 0;
	e = xGetElementById(e);
	while (e) {
		if (xDef(e.offsetTop)) y += e.offsetTop;
		e = xDef(e.offsetParent) ? e.offsetParent : null;
	}
	return y;
}


// xDocSize r1
function xDocSize() {
	var b=document.body, e=document.documentElement;
	var esw=0, eow=0, bsw=0, bow=0, esh=0, eoh=0, bsh=0, boh=0;
	if (e) {
		esw = e.scrollWidth;
		eow = e.offsetWidth;
		esh = e.scrollHeight;
		eoh = e.offsetHeight;
	}
	if (b) {
		bsw = b.scrollWidth;
		bow = b.offsetWidth;
		bsh = b.scrollHeight;
		boh = b.offsetHeight;
	}
	return {w:Math.max(esw,eow,bsw,bow),h:Math.max(esh,eoh,bsh,boh)};
}


// xClientHeight r5
// Patched to work with Opera 9.50 by Craig Manley 2008-06-16
function xClientHeight() {
	var v=0,d=document,w=window;
	if((!d.compatMode || d.compatMode == 'CSS1Compat') && !(w.opera && (!w.opera.version || parseFloat(w.opera.version()) < 9.5)) && d.documentElement && d.documentElement.clientHeight)
		{v=d.documentElement.clientHeight;}
	else if(d.body && d.body.clientHeight)
		{v=d.body.clientHeight;}
	else if(xDef(w.innerWidth,w.innerHeight,d.width)) {
		v=w.innerHeight;
		if(d.width>w.innerWidth) v-=16;
	}
	return v;
}


// xClientWidth r5
function xClientWidth() {
	var v=0,d=document,w=window;
	if((!d.compatMode || d.compatMode == 'CSS1Compat') && !w.opera && d.documentElement && d.documentElement.clientWidth)
		{v=d.documentElement.clientWidth;}
	else if(d.body && d.body.clientWidth)
		{v=d.body.clientWidth;}
	else if(xDef(w.innerWidth,w.innerHeight,d.height)) {
		v=w.innerWidth;
		if(d.height>w.innerHeight) v-=16;
	}
	return v;
}


// xSmartLoad r1
function xSmartLoad(what, url) {
	var loadedBefore = false;
	var s;
	for (var i=0; i<xSmartLoad.list.length; i++) {
		if (xSmartLoad.list[i].url == url) {
			loadedBefore = true;
			s = xSmartLoad.list[i].node;
			break;
		}
	}
	if (document.createElement && document.getElementsByTagName && !loadedBefore) {
		s = document.createElement(what);
		var h = document.getElementsByTagName('head');
		if (s && h.length) {
			switch (what.toUpperCase()) {
			case 'SCRIPT':
				s.src = url;
				break;
			case 'LINK':
				s.rel = 'stylesheet';
				s.type = 'text/css';
				s.href = url;
				break;
			default:
				s = null;
				break;
			}
			h[0].appendChild(s);
			xSmartLoad.list[xSmartLoad.list.length] = {url:url, node:s};
		}
	}
	return s;
}
xSmartLoad.list = []; // static property of xSmartLoad


// xOpacity r1
function xOpacity(e, o) {
	var set = xDef(o);
	//	if (set && o == 1) o = .9999; // FF1.0.2 but not needed in 1.5
	if(!(e=xGetElementById(e))) return 2; // error
	if (xStr(e.style.opacity)) { // CSS3
		if (set) e.style.opacity = o + '';
		else o = parseFloat(e.style.opacity);
	}
	else if (xStr(e.style.filter)) { // IE5.5+
		if (set) e.style.filter = 'alpha(opacity=' + (100 * o) + ')';
		else if (e.filters && e.filters.alpha) { o = e.filters.alpha.opacity / 100; }
	}
	else if (xStr(e.style.MozOpacity)) { // Gecko before CSS3 support
		if (set) e.style.MozOpacity = o + '';
		else o = parseFloat(e.style.MozOpacity);
	}
	else if (xStr(e.style.KhtmlOpacity)) { // Konquerer and Safari
		if (set) e.style.KhtmlOpacity = o + '';
		else o = parseFloat(e.style.KhtmlOpacity);
	}
	return isNaN(o) ? 1 : o; // if NaN, should this return an error instead of 1?
}


// xAniOpacity r1
function xAniOpacity(e, o, t, a, oe) {
	if (!(e=xGetElementById(e))) return;
	var o0 = xOpacity(e); // start value
	var dx = o - o0; // displacement
	var fq = 1 / t; // frequency
	if (a) fq *= (Math.PI / 2);
	var t0 = new Date().getTime(); // start time
	var tmr = setInterval(
		function() {
			var et = new Date().getTime() - t0; // elapsed time
			if (et < t) {
				var f = et * fq; // constant velocity
				if (a == 1) f = Math.sin(f); // sine acceleration
				else if (a == 2) f = 1 - Math.cos(f); // cosine acceleration
				f = Math.abs(f);
				xOpacity(e, f * dx + o0); // instantaneous value
			}
			else {
				clearInterval(tmr);
				xOpacity(e, o); // target value
				if (typeof oe == 'function') oe(); // 'onEnd' handler
				else if (typeof oe == 'string') eval(oe);
			}
		}, 10 // timer resolution
	);
}


// xHasClass r3
function xHasClass(e, c) {
	e = xGetElementById(e);
	if (!e || e.className=='') return false;
	var re = new RegExp("(^|\\s)"+c+"(\\s|$)");
	return re.test(e.className);
}


// xAddClass r3
function xAddClass(e, c) {
	if ((e=xGetElementById(e))!=null) {
		var s = '';
		if (e.className.length && e.className.charAt(e.className.length - 1) != ' ') {
			s = ' ';
		}
		if (!xHasClass(e, c)) {
			e.className += s + c;
			return true;
		}
	}
	return false;
}


// xRemoveClass r3
function xRemoveClass(e, c) {
	if(!(e=xGetElementById(e))) return false;
	e.className = e.className.replace(new RegExp("(^|\\s)"+c+"(\\s|$)",'g'),
		function(str, p1, p2) { return (p1 == ' ' && p2 == ' ') ? ' ' : ''; }
	);
	return true;
}


// xDisplay r3
function xDisplay(e,s) {
	if ((e=xGetElementById(e)) && e.style && xDef(e.style.display)) {
		if (xStr(s)) {
			try { e.style.display = s; }
			catch (ex) { e.style.display = ''; } // Will this make IE use a default value appropriate for the element?
		}
		return e.style.display;
	}
	return null;
}


// xVisibility r1
function xVisibility(e, bShow) {
	if(!(e=xGetElementById(e))) return null;
	if(e.style && xDef(e.style.visibility)) {
		if (xDef(bShow)) e.style.visibility = bShow ? 'visible' : 'hidden';
		return e.style.visibility;
	}
	return null;
}

