/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
 * Bivia Utilities, v1.5
 * (c) 2005 bivia.com
 * created by Ben Curtis of bivia.com, February 22 2005
 * $Id: bv_utilities.js,v 1.8 2005/03/14 08:48:59 bcurtis Exp $
 *~~~~*/


//var bv_enable_root = "/js/";
var bv_enable_root = "";


function debug(Msg,inline) { return 0;
	var newline = (inline) ? " " : "<br />";
	var Div = document.getElementById('debug');
	if (Div) Div.innerHTML += Msg + newline;
	else if (!window.bv_docInited) setTimeout('debug("delayed report:'+Msg+'");',50);
}



/*
	the ondocload "event" is triggered by a script call before the closing body tag:
		<script type="text/javascript">window.ondocload();</script>
		</body>

	it is the event before onload that indicates the document is done downloading;
	after the func declaration we set two handlers to make sure events assigned to
	docload are triggered onload if the author forgets to put the call in the doc,
	and after a delay to give the engine a chance to put everything in place; then
	we also need a check to see if it's already run onload, for pages with no img.
*/
	function bv_addListener(el, evt, fn) {
		if (typeof el == "string") el = document.getElementById(el);
		if (!el) return;
		if (window.addEventListener && evt != 'docload') { // DOM
			el.addEventListener(evt, fn, false); // false, because IE can't handle the truth
		} else if (window.attachEvent && evt != 'docload') { // MS, incl Opera
			el.attachEvent('on'+ evt, fn);
		} else { // Mac IE and the ondocload event
			var prevHandler = (typeof el['on'+ evt] == 'function') ? el['on'+ evt] : function () {};
			el['on'+ evt] = function() { prevHandler(); fn(); } 
		}
	}
	function bv_docLoaded() { setTimeout("if (!window.bv_docInited) window.ondocload();", 5); }
	bv_addListener(window, 'docload', function () { window.bv_docInited = true; });
	bv_addListener(window, 'load', bv_docLoaded);
/* END bv_addListener */



	function bv_assignId(el,base) {
		var b = (base) ? base : "bv";
		if (!el.id) el.id = b + parseInt(Math.random() *100000000000);
		return el.id;
	}



	function sortRandom(a,b) {
		if (Math.random() > 0.5) return 1;
		else return -1;
	}
	function bv_arrayShuffle(a) {
		if (a.length < 2) return a;
		var Last = a[a.length -1];
		do a = a.sort(sortRandom);
		while (Last == a[0]);
		return a;
	}



	function bv_trim(s,internal) {
// Mac IE chokes on the ?
//		s = s.replace(/^\s*(.*?)\s*$/, '$1');
		s = s.replace(/^\s+/g, '');
		s = s.replace(/\s+$/g, '');
		if (internal) s = s.replace(/\s+/g, ' ');
		return s;
	}



	function bv_getElementsByClassName(TagsIn,Class) {
		var It = "\\b"+Class+"\\b";
		var rtn = new Array();
		var Tags = TagsIn.split(",");
		for (var xx=0; xx<Tags.length; xx++) {
			var Els = (this.getElementsByTagName) ? this.getElementsByTagName(Tags[xx]) : this.all;
			for (var ii=0; ii<Els.length; ii++) {
				if (Els[ii].className.match(It))
					rtn[rtn.length] = Els[ii];
			}
		}
		return rtn;
	}
	document.getElementsByClassName = bv_getElementsByClassName;



	function bv_addClassName(el, nm) {
		var regex = new RegExp("\\b"+nm+"\\b", "gi");
		if (el.className.match(regex)) {
		} else el.className = bv_trim(el.className +" "+ nm, 1);
	}
	function bv_removeClassName(el, nm) {
		var regex = new RegExp("\\b"+nm+"\\b", "gi");
		el.className = bv_trim(el.className.replace(regex, ''), 1);
	}



	function bv_getOffsetFromParent(El,XY) {
		var Type = (XY == "top") ? "offsetTop" : "offsetLeft";
	// IE will treat the offset as to the parentNode; Moz refers all to the body element
		return (El.offsetParent == El.parentNode) ? 
				El[Type] : 
				El[Type] - El.parentNode[Type];
	}
	function bv_getOffsetFromRoot(El,XY) {
		var Type = (XY == "top") ? "offsetTop" : "offsetLeft";
		var offset = 0;
		while (El) {
			offset += El[Type];
			El = El.offsetParent;
		}
		return offset;
	}
	function bv_getWindowSize() {
		var windowSize = { h:0, w:0 };
		if (typeof(window.innerWidth) == 'number') {
			windowSize.w = window.innerWidth;
			windowSize.h = window.innerHeight;
		} else {
			if (document.documentElement && document.documentElement.clientWidth) {
				windowSize.w = document.documentElement.clientWidth;
				windowSize.h = document.documentElement.clientHeight;
			} else {
				if (document.body && document.body.clientWidth) {
					windowSize.w = document.body.clientWidth;
					windowSize.h = document.body.clientHeight;
				}
			}
		}
		return windowSize;
	}



	function bv_getStyleValue(el,prop) {
		if (document.defaultView && document.defaultView.getComputedStyle) {
			return document.defaultView.getComputedStyle(el,'').getPropertyValue(prop);
		} else {
			var bits = prop.split("-");
			for (var xx=1; xx<bits.length; xx++) if (bits[xx].length) bits[xx] = bits[xx].charAt(0).toUpperCase() + bits[xx].substring(1);
			var propCased = bits.join('');
			if (el.currentStyle) {
				return el.currentStyle[propCased];
			} else return el.style[propCased];
		}
	}



	function bv_attachNewWindows(prefix, allowedTypes, viewerLocation) {
		var pfx = (prefix && prefix.length) ? prefix : "bv_";
		var AllowPop = (/\bpopview\b/.test(allowedTypes) && (viewerLocation && viewerLocation.length));
		var AllowNew = /\bnewwin\b/.test(allowedTypes);
		var As = document.getElementsByTagName('a');
		for (var xx=0; xx<As.length; xx++) {
			if (AllowPop && As[xx].getAttribute('rel') == "popview") {
				As[xx].onclick = function () { window.open(viewerLocation+this.href,pfx+'viewer','resizable,scrollbars=0'); return false; }
			} else if (AllowNew && As[xx].getAttribute('rel') == "newwin") {
				As[xx].onclick = function () { window.open(this.href,pfx+'newwin'); return false; }
			}
		}
	}


	function bv_getOpacity(el) {
		var Style = null;
		var Alpha = 1;
		if (typeof el.bv_opacity == 'number')
			Alpha = el.bv_opacity;
		else if (Style = bv_getStyleValue(el, 'opacity'))
			Alpha = parseFloat(Style);
		else if (Style = bv_getStyleValue(el, '-moz-opacity'))
			Alpha = parseFloat(Style);
		else if (el.filters && el.filters.length && el.filters.alpha)
			Alpha = parseFloat(el.filters.alpha.opacity) /100;
		if (Alpha == 0.99999) Alpha = 1; // unmask masked values
		if (Alpha == 0.00001) Alpha = 0; // unmask masked values
		return Alpha;
	}
	function bv_setOpacity(el, Alpha) {
		if (Alpha > 0.99) Alpha = 0.99999; // mask incoming 1 to prevent fully-visible flickering transitions
		if (Alpha < 0.01) Alpha = 0.00001; // mask incoming 0 to prevent fully-visible flickering transitions
		el.bv_opacity = parseInt(Alpha *100000) /100000; // helps speed getter; needed for Safari in some cases
		el.style.opacity = el.bv_opacity;
		el.style.MozOpacity = el.bv_opacity;
		el.style.KHTMLOpacity = el.bv_opacity;
		if (el.filters && el.filters.length && el.filters.alpha)
			el.filters.alpha.opacity = el.bv_opacity *100;
		if (el.bv_opacity == 0.99999) el.bv_opacity = 1; // unmask masked values
		if (el.bv_opacity == 0.00001) el.bv_opacity = 0; // unmask masked values
		return el.bv_opacity;
	}
	function bv_adjustOpacity(el, AlphaDelta) {
		if ((""+AlphaDelta).charAt((""+AlphaDelta).length -1) == "%") {
			var Pct = parseFloat(AlphaDelta) /100;
			var AlphaDelta = (Pct >= 0) ?
				Math.ceil((1 - bv_getOpacity(el)) * Pct) :
				Math.floor(bv_getOpacity(el) * Pct);
		}
		return bv_setOpacity(el, bv_getOpacity(el) + parseFloat(AlphaDelta));
	}



/******** /standard * utilities ********/

/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
 * enableScrollBars, v1.0
 * (c) 2005 pizzulli.com
 * created by Ben Curtis of bivia.com, February 27 2005
 * $Id: enableScrollBars.js,v 1.5 2005/03/09 05:42:25 bcurtis Exp $
 *
 * Creates custom scrollbars for divs, for when 
 * overflow:auto|scroll is bad looking.
 *~~~~*/

function bv_makeScrollBars(Div) {
	Div.getElementsByClassName = bv_getElementsByClassName;
	Div.bv_scrollContent = Div.getElementsByClassName('div','bvScrollContainer')[0];
	Div.bv_scrollContent.style.top = "0px";
	Div.bv_scrollMax = Div.bv_scrollContent.offsetHeight - Div.offsetHeight;
	Div.bv_scrollUnit = Div.offsetHeight *0.9;
	Div.style.overflow = "hidden";

	var Gui = window.bv_ScrollBarPrototype.cloneNode(true);
		Div.appendChild(Gui);
		//Div.bv_scrollContent.style.marginRight = (Gui.offsetWidth +5) +"px";
		Div.bv_scrollGui = Gui;
	
// the addition of scrollbars can cause the content to squash and grow taller
	Div.bv_scrollMax = Div.bv_scrollContent.offsetHeight - Div.offsetHeight;

	if (Div.bv_scrollMax <= 0) bv_addClassName(Gui, "bvScrollDisabled");
	else {
		
	// Track
		Div.bv_scrollTrack = Div.getElementsByClassName('div','bvScrollTrack')[0];
		Div.bv_scrollTrack.bv_scroller   = Div;
		Div.bv_scrollTrack.onmousedown   = bv_scrollTrackClickDown;
		Div.bv_scrollTrack.onmouseup     = bv_scrollTrackClickUp;
		Div.bv_scrollTrack.bv_waitTimer  = null;
		Div.bv_scrollTrack.bv_cycleTimer = null;
	
	// Thumb
		Div.bv_scrollThumb = Div.getElementsByClassName('div','bvScrollThumb')[0];
		Div.bv_scrollThumb.bv_scroller = Div;
		Div.bv_scrollThumb.onmousedown = bv_scrollSlideClickDown;
		Div.bv_scrollThumb.onmouseup   = bv_scrollSlideClickUp;
	
	// ArrowUp
		Div.bv_scrollArrowUp = Div.getElementsByClassName('div','bvScrollUp')[0];
		Div.bv_scrollArrowUp.bv_scroller   = Div;
		Div.bv_scrollArrowUp.onclick       = bv_scrollArrowUpClick;
		Div.bv_scrollArrowUp.onmousedown   = bv_scrollArrowUpClickDown;
		Div.bv_scrollArrowUp.onmouseup     = bv_scrollArrowUpClickUp;
		Div.bv_scrollArrowUp.onmouseout    = bv_scrollArrowUpClickUp;
		Div.bv_scrollArrowUp.bv_waitTimer  = null;
		Div.bv_scrollArrowUp.bv_cycleTimer = null;
	
	// ArrowDown
		Div.bv_scrollArrowDown = Div.getElementsByClassName('div','bvScrollDown')[0];
		Div.bv_scrollArrowDown.bv_scroller   = Div;
		Div.bv_scrollArrowDown.onclick       = bv_scrollArrowDownClick;
		Div.bv_scrollArrowDown.onmousedown   = bv_scrollArrowDownClickDown;
		Div.bv_scrollArrowDown.onmouseup     = bv_scrollArrowDownClickUp;
		Div.bv_scrollArrowDown.onmouseout    = bv_scrollArrowDownClickUp;
		Div.bv_scrollArrowDown.bv_waitTimer  = null;
		Div.bv_scrollArrowDown.bv_cycleTimer = null;

		var TrackLength = Gui.offsetHeight - Div.bv_scrollArrowUp.offsetHeight - Div.bv_scrollArrowDown.offsetHeight;
		/* remove this part because I use a fixed height thumb (not a proportional one)
		Div.bv_scrollThumb.style.height = Math.max(
					parseInt(Div.bv_scrollThumb.offsetWidth) /1.5, 
					Div.offsetHeight *(TrackLength / Div.bv_scrollContent.offsetHeight)
				) +"px";
		*/
		Div.bv_scrollThumb.getElementsByTagName('div')[0].style.height = "100%";
		Div.bv_scrollThumb.bv_top = Div.bv_scrollArrowUp.offsetHeight;
		Div.bv_scrollThumb.style.top = Div.bv_scrollThumb.bv_top +"px";
		Div.bv_scrollThumb.bv_excursion = TrackLength - Div.bv_scrollThumb.offsetHeight;

	} // end disabled check

}

function bv_initScrollBars() {
	if (navigator.appName == "Microsoft Internet Explorer" && navigator.platform == "MacPPC") return;
	var Sc = document.getElementsByClassName("div,span,ol,ul", "bvScrollBars");
	if (Sc.length) { // since there are scrollbars needed, create the prototype
		window.bv_ScrollBarPrototype = document.createElement('div');
		window.bv_ScrollBarPrototype.className = "bvScrollGui";
		var ThumbTrack       = document.createElement('div');
		ThumbTrack.className = "bvScrollTrack";
		window.bv_ScrollBarPrototype.appendChild(ThumbTrack);
		var ThumbSlide       = document.createElement('div');
		ThumbSlide.className = "bvScrollThumb";
		var ThumbDetails       = document.createElement('div');
		ThumbDetails.className = "bvScrollThumbDetails";
		ThumbSlide.appendChild(ThumbDetails);
		window.bv_ScrollBarPrototype.appendChild(ThumbSlide);
		var ArrowUp       = document.createElement('div');
		ArrowUp.className = "bvScrollUp";
		window.bv_ScrollBarPrototype.appendChild(ArrowUp);
		var ArrowDown       = document.createElement('div');
		ArrowDown.className = "bvScrollDown";
		window.bv_ScrollBarPrototype.appendChild(ArrowDown);

		bv_addListener(window.document, "mousemove", bv_scrollSlideMove);
		bv_addListener(window.document, "mousedown", bv_scrollScrollCheck);
		bv_addListener(window.document, "mouseup", bv_scrollSlideClickUp);
	}
	for (var xx=0; xx<Sc.length; xx++) {
		if (Sc[xx].id == "") Sc[xx].id = "bvScrollBar"+ parseInt(Math.random() *10000000000000000);
		bv_makeScrollBars(Sc[xx]);
	}
}

bv_addListener(window, 'docload', bv_initScrollBars);
// Safari issues with overflow:hidden not hiding scrollbars; use the Pith Helmet Hack
if ((navigator.userAgent.toLowerCase()).indexOf("safari") != -1) document.write('<style type="text/css">html>body div.bvScrollBars { overflow:hidden; }</style>');


/*~~~~Action~Functions~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
 * Action Functions:
 * These things make the stuff go
 *~~~~*/

function bv_scrollBarTo(Which, Pos) { debug("called bv_scrollBarTo(Which, Pos)"); debug(Which.id +" pos:"+Pos,1);
	if (Pos < 0) Pos = 0;
	if (Pos > Which.bv_scrollMax) Pos = Which.bv_scrollMax;
debug(":"+Which.bv_scrollContent.style.top,1);
	Which.bv_scrollContent.style.top = (-1* Pos) +"px";
debug(":"+Which.bv_scrollContent.style.top,1);
debug(":"+Pos,1);
	bv_scrollAdjustThumb(Which);
}
function bv_scrollBarBy(Which,Amt) { debug("called bv_scrollBarBy(Which,Amt)");
	bv_scrollBarTo(Which, -1* (parseInt(Which.bv_scrollContent.style.top) - Amt));
}
function bv_scrollAdjustThumb(Which,Pos) { debug("called bv_scrollAdjustThumb(Which,Pos)");
	var T = Which.bv_scrollThumb;
	T.style.top = (Math.round(T.bv_excursion *(-1* parseInt(Which.bv_scrollContent.style.top)/Which.bv_scrollMax)) + T.bv_top) +"px";
debug("::thumb:"+T.style.top);
}

//~~/Action~Functions


/*~~~~Event~Handlers~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
 * Event Handlers:
 * coupled to the divs created, these channel events into action
 *~~~~*/

function bv_scrollScrollCheck(e) {
	var evt = (e) ? e : window.event;
	if (evt.target && evt.target.className.indexOf('Scroll') != -1)
		return evt.cancelBubble;
}

function bv_scrollTrackClickDown(e) { debug("called bv_scrollTrackClickDown()");
	var evt = (e) ? e : window.event;
	var ClickAt = evt.offsetY || evt.layerY;
	var Mod = (ClickAt > parseInt(this.bv_scroller.bv_scrollThumb.style.top)) ? 1 : -1;
	if (this.bv_cycleTimer) clearInterval(this.bv_cycleTimer);
	this.bv_waitTimer  = setTimeout("",350);
	this.bv_cycleTimer = setInterval("bv_scrollTrackBudge(document.getElementById('"+ this.bv_scroller.id +"'),"+ Mod +");",350);
}
function bv_scrollTrackClickUp(e) { debug("called bv_scrollTrackClickUp()");
	if (this.bv_cycleTimer) clearInterval(this.bv_cycleTimer);
	if (this.bv_waitTimer) {
		clearTimeout(this.bv_waitTimer);
		var evt = (e) ? e : window.event;
		var ClickAt = evt.offsetY || evt.layerY;
		var Mod = (ClickAt > parseInt(this.bv_scroller.bv_scrollThumb.style.top)) ? 1 : -1;
		bv_scrollTrackBudge(this.bv_scroller, Mod);
	}
}
function bv_scrollTrackBudge(Which, Mod) {
	if (Which.bv_scrollTrack.bv_waitTimer) clearTimeout(Which.bv_scrollTrack.bv_waitTimer);
	Which.bv_scrollTrack.bv_waitTimer = null;
	bv_scrollBarBy(Which, Mod * Which.bv_scrollUnit);
}

function bv_scrollSlideMove(e) { //debug("called bv_scrollSlideMove(e)");
	if (!window.bvScrollBarGrabbed) return true;
	else {
		var evt = (e) ? e : window.event;
		bv_scrollBarTo(
				window.bvScrollBarGrabbed.bv_scroller,
				window.bvScrollBarGrabbed.bv_scroller.bv_scrollMax *(
					(evt.clientY - window.bvScrollBarGrabbed.bv_scrollZeroPoint) / 
					window.bvScrollBarGrabbed.bv_excursion
				)
			);
		return true;
	}
}
function bv_scrollSlideClickDown(e) { debug("called bv_scrollSlideClickDown(e)");
	var evt = (e) ? e : window.event;
	window.bvScrollBarGrabbed = this;
	this.bv_scrollZeroPoint = evt.clientY - parseInt(this.style.top) + this.bv_top;
}
function bv_scrollSlideClickUp() { debug("called bv_scrollSlideClickUp()");
	window.bvScrollBarGrabbed = null;
}

function bv_scrollArrowUpClick() { debug("called bv_scrollArrowUpClick()");
	if (this.bv_waitTimer) clearTimeout(this.bv_waitTimer);
	if (this.bv_cycleTimer) clearInterval(this.bv_cycleTimer);
	else bv_scrollBarBy(this.bv_scroller, -15);
}
function bv_scrollArrowUpClickDown() { debug("called bv_scrollArrowUpClickDown()");
	if (this.bv_waitTimer) clearTimeout(this.bv_waitTimer);
	if (this.bv_cycleTimer) clearInterval(this.bv_cycleTimer);
	this.bv_waitTimer = setTimeout("bv_scrollArrowUpClickDownCycle('"+ this.bv_scroller.id +"');",500);
}
function bv_scrollArrowUpClickDownCycle(Id) { debug("called bv_scrollArrowUpClickDownCycle(Id)");
	document.getElementById(Id).bv_scrollArrowUp.bv_cycleTimer = setInterval("bv_scrollBarBy(document.getElementById('"+ Id +"'), -5);",25);
}
function bv_scrollArrowUpClickUp() { debug("called bv_scrollArrowUpClickUp()");
	if (this.bv_waitTimer) clearTimeout(this.bv_waitTimer);
	if (this.bv_cycleTimer) clearInterval(this.bv_cycleTimer);
}

function bv_scrollArrowDownClick() { debug("called bv_scrollArrowDownClick()");
	if (this.bv_waitTimer) clearTimeout(this.bv_waitTimer);
	if (this.bv_cycleTimer) clearInterval(this.bv_cycleTimer);
	else bv_scrollBarBy(this.bv_scroller, +15);
}
function bv_scrollArrowDownClickDown() { debug("called bv_scrollArrowDownClickDown()");
	if (this.bv_waitTimer) clearTimeout(this.bv_waitTimer);
	if (this.bv_cycleTimer) clearInterval(this.bv_cycleTimer);
	this.bv_waitTimer = setTimeout("bv_scrollArrowDownClickDownCycle('"+ this.bv_scroller.id +"');",500);
}
function bv_scrollArrowDownClickDownCycle(Id) { debug("called bv_scrollArrowDownClickDownCycle(Id)");
	document.getElementById(Id).bv_scrollArrowDown.bv_cycleTimer = setInterval("bv_scrollBarBy(document.getElementById('"+ Id +"'), +5);",25);
}
function bv_scrollArrowDownClickUp() { debug("called bv_scrollArrowDownClickUp()");
	if (this.bv_waitTimer) clearTimeout(this.bv_waitTimer);
	if (this.bv_cycleTimer) clearInterval(this.bv_cycleTimer);
}
