/***********************************************************************
 * Several scripts may want to have window.onload event handlers.
 * The following script allows them all to have their handlers work.
 ***********************************************************************/
var onLoadHandlers = new Array();
function registerOnLoadHandler(f) {
	if( f == null ) return;
	onLoadHandlers[onLoadHandlers.length] = f; // push not supported on IE5
};
var onLoadStarted = false;
function onLoadChain() {
	if( onLoadStarted ) return; // sometimes this gets called more than once
	onLoadStarted = true;
	for(var i = 0; i < onLoadHandlers.length; i++)
		onLoadHandlers[i]();
};
window.onload = onLoadChain;

/***********************************************************************
 * Browser detection
 ***********************************************************************/

function isIE() {
	// Opera DOES implement document.all when in IE-masquerading mode, and reports as MSIE,
	// so we explicitly check for Opera as well as check for IE.
	return navigator.appVersion.indexOf('MSIE') != -1 && navigator.userAgent.indexOf('Opera') == -1;
};

function getIEVersion() {
	return parseFloat(navigator.appVersion.split("MSIE")[1]);
};

function getMosaicLevel() {
	var body = document.getElementsByTagName('body')[0];
	var levelIdx = body.className.indexOf('level');
	if( levelIdx == -1 ) return null; // unable to determine
	return body.className.substring(levelIdx+5,levelIdx+6);
};

/***********************************************************************
 * Browser hacks
 ***********************************************************************/

var avoidParsingStylesheets = false; // set later

function findStylesheet(href) {
	if( avoidParsingStylesheets ) return;
	for( var i = 0; i < document.styleSheets.length; i++ ) {
		result = findStylesheetInside(document.styleSheets[i], href);
		if( result ) return result;
	}
	return null;
};

function findStylesheetInside(sheet, href) {
	if( sheet.href.indexOf(href) != -1 ) return sheet;
	try {
		if( sheet.cssRules ) { // Mozilla
			for( var i = 0; i < sheet.cssRules.length; i++ )
				if( sheet.cssRules[i].styleSheet ) {
					result = findStylesheetInside(sheet.cssRules[i].styleSheet, href);
					if( result ) return result;
				}
		} else if( sheet.imports ) { // IE
			for( var i = 0; i < sheet.imports.length; i++ ) {
				result = findStylesheetInside(sheet.imports[i], href);
				if( result ) return result;
			}
		}
	} catch(securityException){}
};

// Go over every single defined CSS rule, and call the function f on it.
// Signature of f: function(rule, sheet), returning a boolean
// If f ever returns true, abort the process.
function foreachCssRule(f, sheet) {
	if( avoidParsingStylesheets ) return;
	
	if( !sheet ) { // if this is the outermost call
		for( var i = 0; i < document.styleSheets.length; i++ )
			if( foreachCssRule(f, document.styleSheets[i]) ) return true;
		return;
	}

	// Go over each of this sheet's rules
	if( sheet.rules ) {
		for( var i = 0; i < sheet.rules.length; i++ )
			if( f(sheet.rules[i], sheet) ) return true;
	}
	
	// Enumerate over each of this sheet's subsheets, if any
	if( sheet.imports ) {
		for( var i = 0; i < sheet.imports.length; i++ )
			if( foreachCssRule(f, sheet.imports[i]) ) return true;
	}
};

function swapPNGsInsideElement(element) {
	if( element == null ) return;
	var images = element.getElementsByTagName('IMG');
	for( var i = 0; i < images.length; i++ ) {
		var img = images[i];
		if( img.src.substring(img.src.length-4).toLowerCase() == '.png' ) {
			var span = document.createElement('span');
			span.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + img.src + '",sizingMethod="scale")';
			span.style.width = img.width;
			span.style.height = img.height;
			span.title = img.alt;
			span.style.display = 'block';
			img.parentNode.replaceChild(span, img);
		}
	}
};

function fixIETransparentPNGs() {
	// Only do this swap for IE6 browsers
	if( !(isIE() && getIEVersion() == 6) ) return;
	// Look for all targeted IMG tags, and swap out PNGs with background-images
	var orgbar = document.getElementById('OrganizationBar');
	var tabsbar = document.getElementById('Tabs');
	var bottombar = document.getElementById('BottomBar');
	swapPNGsInsideElement(orgbar);
	swapPNGsInsideElement(tabsbar);
	swapPNGsInsideElement(bottombar);
	if( tabsbar ) {
		var tabs = tabsbar.getElementsByTagName('LI');
		tabsbar.className = 'iehack';
		for( var i = 0; i < tabs.length; i++ ) {
			var tab = tabs[i];
			var a = tab.getElementsByTagName('A');
			tab.style.filter = null;
			tab.style.margin = "0";
			var tbl = document.createElement('table');
			if( a.length ) tbl.onclick = a[0].onclick; // copy onclick handler to table so it still works
			tbl.cellPadding = 0; tbl.cellSpacing = 0;
			var tr = tbl.insertRow(0);
			var tdBefore = tr.insertCell(tr.cells.length);
			var td = tr.insertCell(tr.cells.length);
	
			tdBefore.className = 'left';
			td.className = 'right';
			
			// Move contents of original LI into the second cell
			while( tab.childNodes.length ) td.appendChild( tab.childNodes[0] );
			tab.appendChild(tbl);
		}
	}
	fixImageReferences();
};

function fixImageReferences() {
	// Fix CSS references to mosaic images in alpha filters, where a non-relative url had to be given.
	var mosaicSrc;
	foreachCssRule(function(rule, sheet) {
							var re = new RegExp('"mosaic/images/(.+?)"');
							if( !(re.test(rule.style.filter) ) ) return false;
							// This is one of the standard stylesheets, so use that to determine
							// the location of the mosaic template, if we don't know already.
							if( !mosaicSrc ) mosaicSrc = (new RegExp("^(.+)[\\/]+styles[\\/]+[^\\/]+")).exec(sheet.href)[1];
							// Rip out the incorrect reference and stick in the correct one.
							// This is really only necessary when the webmaster is using the mosaic
							// templates in a location other than directly beneath the current web page,
							// (which will likely be most of the time).
							rule.style.filter = rule.style.filter.replace(re, '"' + mosaicSrc + '/images/$1"');
							});
}

function fixIERouteYLoginForm() {
	// Fix (bug in) IE where ENTER on password field fails to submit form.
	if( !isIE() ) return; // nothing to fix if not IE
	// on level1 pages, we want ryPassword.  on level2 pages, we want password.
	var pwd = document.getElementById('ryPassword') || document.getElementById('password');
	if( pwd ) pwd.onkeypress = function() {if(event.keyCode==13) return this.form.submit();};
}

function browserHacks() {
	// For some reason, IE can't parse stylesheets on level 1 pages without crashing completely.
	avoidParsingStylesheets = isIE() && getMosaicLevel() == 1;

	fixIETransparentPNGs();
	fixIERouteYLoginForm();
};

registerOnLoadHandler(browserHacks);

/***********************************************************************
 * Stylesheet selector link behavior
 ***********************************************************************/

function getAlternateStylesheets() {
	var list = new Array();
	var links = document.getElementsByTagName("link");
	for( var i=0; i < links.length; i++ ) {
		sheet = sheet = links[i];
		 if ( sheet.getAttribute("rel") != null ) {
			 if( sheet.getAttribute("rel").indexOf("style") != -1 && sheet.getAttribute("title") )
				list[list.length] = sheet;
		}
	}
	return list;
};

function activateAlternateStylesheet(href) {
	if( href )
		setCookie(href, 'activeStylesheet');
	else
		unsetCookie('activeStylesheet');
	var list = getAlternateStylesheets();
	for( var i=0; sheet = list[i]; i++ )
		sheet.disabled = sheet.href.indexOf(href) == -1;
};

function isSheetTurnedOn(href) {
	var list = getAlternateStylesheets();
	for( var i=0; i < list.length; i++ )
		if( list[i].href.indexOf(href) != -1 ) return !list[i].disabled;
	return false;
};

function isItemTurnedOn(li) {
	var arr = li.getElementsByTagName('A');
	if( arr.length == 0 ) return;
	a = arr[0];
	var m = /\W(\w+\.css)/i.exec(a.onclick); // find .css file
	if( !m ) {
		// standard stylesheet is considered "on" when alternatives are off
		var list = getAlternateStylesheets();
		for( var i=0; i < list.length; i++ )
			if( isSheetTurnedOn(list[i].href) ) return false;
		return true;
	}
	return isSheetTurnedOn(m[1]);
};

function selectAlternateStylesheet(href) {
	activateAlternateStylesheet(href);
	// update the checkmark on the dropdown selection list.
	if( !document.getElementById('StylesheetSelection') ) return;
	var lis = document.getElementById('StylesheetSelection').getElementsByTagName('LI');
	for( var i = 0; i < lis.length; i++ )
		lis[i].className = isItemTurnedOn(lis[i]) ? 'selected' : '';
};

function stylesheetInitialize() {
	selectAlternateStylesheet(getCookie('activeStylesheet'));
};

registerOnLoadHandler(stylesheetInitialize);

/***********************************************************************
 * Common utility functions
 ***********************************************************************/

// getElementsByTagName returns all descendant nodes,
// but this method returns only those nodes that are immediate children.
function getImmediateChildrenByTagName(element, tagName)
{
	if( !element ) return new Array(); // quit without error if null is sent in.
	var list = element.getElementsByTagName(tagName);
	// Keep elements that are immediate children 
	// of supplied element.
	var finalList = new Array();
	var finalIdx = 0;
	for( var i = 0; i < list.length; i++ )
		if( list[i].parentNode == element )
			finalList[finalIdx++] = list[i];
	return finalList;
};

function getElementsByClassName(className, container, tagName) {
	var outArray = new Array();
	var all = container.getElementsByTagName(tagName ? tagName : '*');
	for( var i = 0; i < all.length; i++ )
		if( all[i].className == className ) outArray[outArray.length] = all[i];
	return outArray;
};

/* The next several utility functions are utilized by our index generation javascript */
var defaultEmptyOK = false;
var whitespace = " \t\n\r";
var digits = "0123456789";
var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz";
var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

function isEmpty(s)
{   return ((s == null) || (s.length == 0))
};

function isLetter (c)
{   return ( ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) )
};

function isDigit (c)
{   return ((c >= "0") && (c <= "9"))
};

function stripCharsInBag (s, bag)
{   var i;
    var returnString = "";

    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.

    for (i = 0; i < s.length; i++)
    {   
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }

    return returnString;
};

function stripWhitespace (s)
{   return stripCharsInBag (s, whitespace)
};

function isAlphanumeric (s)
{   var i;

    if (isEmpty(s)) 
       if (isAlphanumeric.arguments.length == 1) return defaultEmptyOK;
       else return (isAlphanumeric.arguments[1] == true);

    // Search through string's characters one by one
    // until we find a non-alphanumeric character.
    // When we do, return false; if we don't, return true.

    for (i = 0; i < s.length; i++)
    {   
        // Check that current character is number or letter.
        var c = s.charAt(i);

        if (! (isLetter(c) || isDigit(c) ) )
        return false;
    }

    // All characters are numbers or letters.
    return true;
};

function setCookie(cValue, cookieID) {
	var NameOfCookie = cookieID;
	document.cookie = NameOfCookie + "=" + escape(cValue);
};

function unsetCookie(cookieID) {
	setCookie (null, cookieID);
};

function getCookie(cookieID) {
	var dc = document.cookie, prefix = cookieID + "=", begin = dc.indexOf("; " + prefix);
	if (begin == -1) { 
		begin = dc.indexOf(prefix); 
		if (begin != 0) 
			return null; 
	}
	else 
		begin += 2;
	var end = document.cookie.indexOf(";", begin);
	if (end == -1) 
		end = dc.length;
	return unescape(dc.substring(begin + prefix.length, end));
};

/***********************************************************************
 * csshover.htc
 * For security reasons, IE blocks .htc files accessed from a remote 
 * site (a site other than the hosting web site).  So we include it here 
 * instead.
 ***********************************************************************/
 
/**
 *	Pseudos - V1.30.050121 - hover & active
 *	---------------------------------------------
 *	Peterned - http://www.xs4all.nl/~peterned/
 *	(c) 2005 - Peter Nederlof
 *
 *	Credits  - Arnoud Berendsen 
 *	         - Martin Reurings
 *           - Robert Hanson
 *
 *	howto: body { behavior:url("csshover.htc"); }
 *	---------------------------------------------
 */

var currentSheet, doc = window.document, activators = {
	onhover:{on:'onmouseover', off:'onmouseout'},
	onactive:{on:'onmousedown', off:'onmouseup'}
};

function parseStylesheets() {
	if( avoidParsingStylesheets ) return;
	if( !doc.styleSheets ) return; // non IE browsers don't need this anyway.
	var sheets = doc.styleSheets, l = sheets.length;
	for(var i=0; i<l; i++) 
		parseStylesheet(sheets[i]);
};
	function parseStylesheet(sheet) {
		if(sheet.imports) {
			try {
				var imports = sheet.imports, l = imports.length;
				for(var i=0; i<l; i++) parseStylesheet(sheet.imports[i]);
			} catch(securityException){}
		}

		try {
			var rules = (currentSheet = sheet).rules, l = rules.length;
			for(var j=0; j<l; j++) parseCSSRule(rules[j]);
		} catch(securityException){}
	};

	function parseCSSRule(rule) {
		var select = rule.selectorText, style = rule.style.cssText;
		if(!(/(^|\s)(([^a]([^ ]+)?)|(a([^#.][^ ]+)+)):(hover|active)/i).test(select) || !style) return;
		
		var pseudo = select.replace(/[^:]+:([a-z-]+).*/i, 'on$1');
		var newSelect = select.replace(/(\.([a-z0-9_-]+):[a-z]+)|(:[a-z]+)/gi, '.$2' + pseudo);
		var className = (/\.([a-z0-9_-]*on(hover|active))/i).exec(newSelect)[1];
		var affected = select.replace(/:hover.*$/, '');
		var elements = getElementsBySelect(affected);

		currentSheet.addRule(newSelect, style);
		for(var i=0; i<elements.length; i++)
			new HoverElement(elements[i], className, activators[pseudo]);
	};

function HoverElement(node, className, events) {
	if(!node.hovers) node.hovers = {};
	if(node.hovers[className]) return;
	node.hovers[className] = true;
	node.attachEvent(events.on,
		function() { node.className += ' ' + className; });
	node.attachEvent(events.off,
		function() { node.className = 
			node.className.replace(new RegExp('\\s+'+className, 'g'),''); });
};

function getElementsBySelect(rule) {
	var parts, nodes = [doc];
	parts = rule.split(' ');
	for(var i=0; i<parts.length; i++) {
		nodes = getSelectedNodes(parts[i], nodes);
	}	return nodes;
};
	function getSelectedNodes(select, elements) {
		var result, node, nodes = [];
		var classname = (/\.([a-z0-9_-]+)/i).exec(select);
		var identify = (/\#([a-z0-9_-]+)/i).exec(select);
		var tagName = select.replace(/(\.|\#|\:)[a-z0-9_-]+/i, '');
		for(var i=0; i<elements.length; i++) {
			result = tagName? elements[i].all.tags(tagName):elements[i].all; 
			for(var j=0; j<result.length; j++) {
				node = result[j];
				if((identify && node.id != identify[1]) || (classname && !(new RegExp('\\b' +
					classname[1] + '\\b').exec(node.className)))) continue;
				nodes[nodes.length] = node;
			}
		}	return nodes;
	};
	
registerOnLoadHandler(parseStylesheets);
