//<!--
//# Written by Russell Moffitt, NOAA
//# Modified Oct 2005
//# License: GPL
//-->

// CROSS-BROWSER DOM & CSS COMPATIBILITY FUNCTIONS
// Modified from cross-browser.com x lib (Mike Foster).

/* x_core.js
   additional functions can be found in
       x_dom.js:	DOM traversal and Element searching functions
       x_event.js:	W3C DOM and Microsoft event model compatibility functions
       x_slide.js:	Animation functions for a smooth sin slide (slow>>fast>>slow)
*/

// Default Variables
// I only intend this to work with the latest browsers, so no need to set IE4/5 or Opera6 variables.
// Browser sniffing is usually bad.  Object detection is good.  Having so many incompatibilities among browsers sucks.

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

var $ = xGetElementById;  // Optionally use Prototype-style element getter

function xParent(e, bNode) {
	if (!(e=xGetElementById(e))) return null;
	var p=null;
	if (!bNode && xDef(e.offsetParent)) p=e.offsetParent;
	else if (xDef(e.parentNode)) p=e.parentNode;
	else if (xDef(e.parentElement)) p=e.parentElement;
	return p;
}

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

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

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


// Appearance:
function xShow(e) {return xVisibility(e,1);}

function xHide(e){return xVisibility(e,0);}

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;
}

/* xGetComputedStyle
   A safe wrapper for getComputedStyle and currentStyle.
   For sProp use the css property name, not the object property name.
   For finding width this works in Moz and Op, but in IE only works
   if padding and border use px units in CSS.
   Return: String, or integer if bInt is true.
*/
function xGetComputedStyle(oEle, sProp, bInt) {
	var s, p = 'undefined';
	var dv = document.defaultView;
	if(dv && dv.getComputedStyle){
		s = dv.getComputedStyle(oEle,'');
		if (s) p = s.getPropertyValue(sProp);
	}
	else if(oEle.currentStyle) {
		// convert css property name to object property name for IE
		var a = sProp.split('-');
		sProp = a[0];
		for (var i=1; i<a.length; ++i) {
		c = a[i].charAt(0);
		sProp += a[i].replace(c, c.toUpperCase());
		}
		p = oEle.currentStyle[sProp];
	}
	else return null;
	return bInt ? (parseInt(p) || 0) : p;
}


// Position:
function xMoveTo(e,x,y) {
	xLeft(e,x);
	xTop(e,y);
}

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=0;
		}
	}
	else if(css && xDef(e.style.pixelLeft)) {
		if(xNum(iX)) e.style.pixelLeft=iX;
		else iX=e.style.pixelLeft;
	}
	return iX;
}

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=0;
		}
	}
	else if(css && xDef(e.style.pixelTop)) {
		if(xNum(iY)) e.style.pixelTop=iY;
		else iY=e.style.pixelTop;
	}
	return iY;
}

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

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

function xOffsetLeft(e) {
	if (!(e=xGetElementById(e))) return 0;
	if (xDef(e.offsetLeft)) return e.offsetLeft;
	else return 0;
}

function xOffsetTop(e) {
	if (!(e=xGetElementById(e))) return 0;
	if (xDef(e.offsetTop)) return e.offsetTop;
	else return 0;
}

function xScrollLeft(e, bWin) {
	var offset=0;
	if (!xDef(e) || bWin || e == document || e.tagName.toLowerCase() == 'html' || e.tagName.toLowerCase() == 'body') {
		var w = window;
		if (bWin && e) w = e;
		if(w.document.documentElement && w.document.documentElement.scrollLeft) offset=w.document.documentElement.scrollLeft;
		else if(w.document.body && xDef(w.document.body.scrollLeft)) offset=w.document.body.scrollLeft;
	}
	else {
		e = xGetElementById(e);
		if (e && xNum(e.scrollLeft)) offset = e.scrollLeft;
	}
	return offset;
}

function xScrollTop(e, bWin) {
	var offset=0;
	if (!xDef(e) || bWin || e == document || e.tagName.toLowerCase() == 'html' || e.tagName.toLowerCase() == 'body') {
		var w = window;
		if (bWin && e) w = e;
		if(w.document.documentElement && w.document.documentElement.scrollTop) offset=w.document.documentElement.scrollTop;
		else if(w.document.body && xDef(w.document.body.scrollTop)) offset=w.document.body.scrollTop;
	}
	else {
		e = xGetElementById(e);
		if (e && xNum(e.scrollTop)) offset = e.scrollTop;
	}
	return offset;
}

function xHasPoint(e,x,y,t,r,b,l) {
	if (!xNum(t)){t=r=b=l=0;}
	else if (!xNum(r)){r=b=l=t;}
	else if (!xNum(b)){l=r; b=t;}
	var eX = xPageX(e), eY = xPageY(e);
	return (x >= eX + l && x <= eX + xWidth(e) - r &&
			y >= eY + t && y <= eY + xHeight(e) - b );
}

function xIntersection(e1, e2, o) {
	var ix1, iy2, iw, ih, intersect = true;
	var e1x1 = xPageX(e1);
	var e1x2 = e1x1 + xWidth(e1);
	var e1y1 = xPageY(e1);
	var e1y2 = e1y1 + xHeight(e1);
	var e2x1 = xPageX(e2);
	var e2x2 = e2x1 + xWidth(e2);
	var e2y1 = xPageY(e2);
	var e2y2 = e2y1 + xHeight(e2);
	// horizontal
	if (e1x1 <= e2x1) {
		ix1 = e2x1;
		if (e1x2 < e2x1) intersect = false;
		else iw = Math.min(e1x2, e2x2) - e2x1;
	}
	else {
		ix1 = e1x1;
		if (e2x2 < e1x1) intersect = false;
		else iw = Math.min(e1x2, e2x2) - e1x1;
	}
	// vertical
	if (e1y2 >= e2y2) {
		iy2 = e2y2;
		if (e1y1 > e2y2) intersect = false;
		else ih = e2y2 - Math.max(e1y1, e2y1);
	}
	else {
		iy2 = e1y2;
		if (e2y1 > e1y2) intersect = false;
		else ih = e1y2 - Math.max(e1y1, e2y1);
	}
	// intersected rectangle
	if (intersect && typeof(o)=='object') {
		o.x = ix1;
		o.y = iy2 - ih;
		o.w = iw;
		o.h = ih;
	}
	return intersect;
}


// Size:
function xResizeTo(e,w,h) {
	xWidth(e,w);
	xHeight(e,h);
}

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;
}

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;
}

function xClip(e,t,r,b,l){
  if(!(e=xGetElementById(e))) return;
  if(e.style) {
    if (xNum(l)) e.style.clip='rect('+t+'px '+r+'px '+b+'px '+l+'px)';
    else e.style.clip='rect(0 '+parseInt(e.style.width)+'px '+parseInt(e.style.height)+'px 0)';
  }
}


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

function xClientHeight() {
	var h=0;
	if(document.compatMode == 'CSS1Compat' && !window.opera && document.documentElement && document.documentElement.clientHeight) {
		h=document.documentElement.clientHeight;
	}
	else if(document.body && document.body.clientHeight) {
		h=document.body.clientHeight;
	}
	else if(xDef(window.innerWidth,window.innerHeight,document.width)) {
		h=window.innerHeight;
		if(document.width>window.innerWidth) h-=16;
	}
	return h;
}
// end x_core.js