
// Code to handle DHTML layers

// Shortcut way to get objects by string ID. If already an object then return it unchanged.
// If strict is true then an error is thrown when the object isn't found. Defaults to true.
function obj(ref, strict)
{
	var isStrict = strict || typeof strict == 'undefined';
	if (isString(ref)) {
		var o = document.getElementById(ref);
		if (isStrict && !o) throw new Error(0,"No element with id '" + ref + "' found");
		return o;
	} else {
		if (isStrict && !ref) throw "Null passed to obj()";
		return ref;
	}
}

// Dynamically change CSS class
function setClass(ref, newClass)
{
	obj(ref).className = newClass;
}

// Dynamically change contents
function setText(ref,text)
{
	obj(ref).innerHTML = text;
}

/*
 * cssjs
 * written by Christian Heilmann (http://icant.co.uk)
 * eases the dynamic application of CSS classes via DOM
 * parameters: action a, object or name o and class names c1 and c2 (c2 optional)
 * actions: swap exchanges c1 and c2 in object o
 *			add adds class c1 to object o
 *			remove removes class c1 from object o
 *			toggle turns class c1 off if it is currently on and vice-versa
 *			check tests if class c1 is applied to object o
 * example:	cssjs('swap',document.getElementById('foo'),'bar','baz');
 */

function cssjs(a,ref,c1,c2)
{
	var o = obj(ref, false);
	if (o) {
		switch (a){
			case 'swap':
				o.className=!cssjs('check',o,c1)?o.className.replace(c2,c1):o.className.replace(c1,c2);
				break;
			case 'add':
				if(!cssjs('check',o,c1)){o.className+=o.className?' '+c1:c1;}
				break;
			case 'remove':
				var rep=o.className.match(' '+c1)?' '+c1:c1;
				o.className=o.className.replace(rep,'');
				break;
			case 'toggle':
				cssjs('check',ref,c1) ? cssjs('remove',ref,c1) : cssjs('add',ref,c1);
				break;		
			case 'check':
				return new RegExp('\\b'+c1+'\\b').test(o.className);
		}
	}
}
function showImage(ref) 
{
	var img = obj(ref);
	cssjs('remove',img,'hidden');
	img.src = img.src; // reload
}

function hideImage(ref) 
{
	cssjs('add',ref,'hidden');
}

/* call this to continue image loading when interrupted by a javascript action */
function reloadImages() {
	var images = document.getElementsByTagName('IMG');
	for (var i=0;i<images.length;i++){
		images[i].src = images[i].src;
	}
}

function showLayer(ref) 
{
	cssjs('remove',ref,'hidden');
}

function hideLayer(ref) 
{
	cssjs('add',ref,'hidden');
}

function deleteLayer(ref) {
	var node = obj(ref);
	node.parentNode.removeChild(node);
}

/* Show next hidden layer in a sequence (up to a maximum) */
function showNextLayer(ref, max) 
{
	if (!isNumber(max)) max = 999;
	for (var i=1; i<max; i=i+1) {
		var el = obj(ref + '_' + i);
		if (el) {
			if (cssjs('check',el,'hidden')) {
				// found next hidden element in sequence
				showLayer(el);
				break;
			}
		} else {
			// no more elements
			break;
		}
	}
	// reached max
}
function scrollLayer(id,amount) {
	var el = obj(id);
	var prev_arrow = obj(id+'_prev');
	var next_arrow = obj(id+'_next');
	var old_top = el.scrollTop;
	el.scrollTop += amount;
	var new_top = el.scrollTop;
	window.status = 'o: '+old_top+' n: '+new_top;

	if (new_top <= 0) {
		prev_arrow.style.visibility = 'hidden';
	} else {
		prev_arrow.style.visibility = 'visible';
	}
	if (new_top <= old_top + amount) {
		next_arrow.style.visibility = 'hidden';
	} else {
		next_arrow.style.visibility = 'visible';
	}
}
function showPopup(ref) 
{
	//window.scroll(0,0);
	showLayer('overlay_background');
	showLayer('overlay');
	showLayer(ref + '_popup');
}

function hidePopup(ref) 
{
	hideLayer(ref + '_popup');
	hideLayer('overlay');
	hideLayer('overlay_background');
}

// writes or changes a general message
function message(text, className)
{
	try {
		// We write the message into the page if the class has 'inline', otherwise it's a popup message
		// eg, msg("Display in page", "popup warning")
		className = className || '';
		var is_popup = new RegExp('\\bpopup\\b').test(className);
		// Add the message text as a list item
		var message_ul = obj( is_popup ? 'popup_messages_list' : 'inline_messages_list' );
		message_ul.innerHTML += '<li class="'+className+'">' + text;
		// Set visual style based on class
		if (is_popup && obj('messages')) {
			showPopup('messages');
		} else {
			showLayer('inline_messages');
		}
		window.scroll(0,0);
	} catch(e) {
		window.alert(text); // fallback to basic alert
	}
}

// writes or changes a warning message
function warning(text, className)
{
	className = className || '';
	message(text, className + ' warning');
}

// writes or changes an error message
function error(text, className)
{
	className = className || '';
	message(text, className + ' error');
}

// Clear any messages already written
function clearMessages()
{
	var pml = obj('popup_messages_list',false);
	var iml = obj('inline_messages_list',false);
	if (pml) pml.innerHTML = '';
	if (iml) iml.innerHTML = '';
}

// Clear any messages already written
function hideMessages()
{
	hidePopup('messages');
	hideLayer('inline_messages');
	clearMessages();
}

// Shortcuts (backwards-compat)
msg = message;
warn = warning;
err = error;

// Hide difference between w3c and IE non-standard events
function getEvent(e) {
    return e ? e : window.event;
} 

function getTarget(e) {
    return e ? e.target : window.event.srcElement;
} 

// To use just add cancelBubble(e) to the top your handler function
function cancelBubble(e) {
    var e = e || window.event;
    e.cancelBubble = true;
    if (e.stopPropagation) e.stopPropagation();
} 

// Cross-browser function to stop default browser action after an event handler
function cancelDefaultAction(e) {
	if(document.preventDefault) { // w3c
		e.preventDefault();
	} else { // IE
		e.returnValue = false;
	}
}

// Mostly cross-browser function to prevent text selection in an element. Requires unselectable class defined in layers.css.
function preventSelection(el) {
	el.unselectable = 'on'; // IE
	cssjs('add', el, 'noselect'); // use CSS class to hide select
}

// Undo preventSelection() 
function allowSelection(el) {
	el.unselectable = 'off'; // IE
	cssjs('remove', el, 'noselect'); // Other browsers
}

// Simulate mouseleave event from IE
// Author: Peter-Paul Koch (slightly modified)
// Website: http://www.quirksmode.org/js/events_mouse.html
// License: Public Domain
// Usage: if (mouseReallyOut(e)) do stuff... in a mouseout handler

function mouseReallyOut(e) {
	if (!e) var e = window.event;
	var tg = (window.event) ? e.srcElement : e.target;
	var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
	while (reltg != tg && reltg.nodeName != 'BODY') {
		reltg = reltg.parentNode;
	}
	return !(reltg == tg);
}

function mouseReallyIn(e) {
	if (!e) var e = window.event;
	var tg = (window.event) ? e.srcElement : e.target;
	var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
	while (reltg != tg && reltg.nodeName != 'BODY') {
		reltg = reltg.parentNode;
	}
	return (reltg == tg);
}

//Cross-browser get first/last element (ignoring text nodes)
function getFirstElement(el)
{
	var first_el = el.firstChild;
	while (first_el.nodeType != 1) {
		first_el = first_el.nextSibling;
	}
	return first_el;
}
function getLastElement(el)
{
	var last_el = el.lastChild;
	while (last_el.nodeType != 1) {
		last_el = last_el.previousSibling;
	}
	return last_el;
}

/*
	Cross-browser getElementsByClassName. Falls back to slower implementations when native support is missing
	Developed by Robert Nyman, http://www.robertnyman.com
	Code/licensing: http://code.google.com/p/getelementsbyclassname/
*/
var getElementsByClassName = function (className, tag, elm){
	if (document.getElementsByClassName) {
		getElementsByClassName = function (className, tag, elm) {
			elm = elm || document;
			var elements = elm.getElementsByClassName(className),
				nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
				returnElements = [],
				current;
			for(var i=0, il=elements.length; i<il; i+=1){
				current = elements[i];
				if(!nodeName || nodeName.test(current.nodeName)) {
					returnElements.push(current);
				}
			}
			return returnElements;
		};
	}
	else {
		getElementsByClassName = function (className, tag, elm) {
			tag = tag || "*";
			elm = elm || document;
			var classes = className.split(" "),
				classesToCheck = [],
				elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
				current,
				returnElements = [],
				match;
			for(var k=0, kl=classes.length; k<kl; k+=1){
				classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
			}
			for(var l=0, ll=elements.length; l<ll; l+=1){
				current = elements[l];
				match = false;
				for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
					match = classesToCheck[m].test(current.className);
					if (!match) {
						break;
					}
				}
				if (match) {
					returnElements.push(current);
				}
			}
			return returnElements;
		};
	}
	return getElementsByClassName(className, tag, elm);
};



/* Shortcut functions for converting and caching arrays of DOM properties based on id, tag, class or style
KEY ::  I=id, E=element, E=classes, T=tag, S=style, X=XPath
*/

var conversion_cache = {}; /* Storage for cached conversions */
var conversion_cache_max = 10000; /* Default limit of caching of results from conversions */
var conversion_cache_interval = 5; /* Number of seconds between cleanups */
/*
IdToNode = function(id, cache, root) {
	var root = root || document;
	if (cache || element_cache) {
		var key = str(id);
		return root.getElementById(id);
	}
}
IdsToNodes = function(ids) {
	switch type(ids) {
		case 'string': return IdsToNodes(ids.split(',')); break;
		case 'number': return IdToNode(ids); break;
	}
}

NodesToIds
TagsToNodes
ClassesToNodes
StylesToNodes

function Ids = getElementById;
function getTags = document.getElementsByTagName;
function getClasses = getElementsByClassName;
window.setTimeout('conversion_cache_cleanup()',conversion_cache_interval)
*/




/* SPECIAL EFFECTS */
/* jQuery rollover effects */
function imageRollover(selector) {
	$(selector + " img").each(function() {
		// preload over image
		var oImg = new Image();
		oImg.src = this.src.replace("-norm","-over");
	}).hover(
		// add swap handler
		function() {this.src = this.src.replace("-norm","-over");},
		function() {this.src = this.src.replace("-over","-norm");}
	);
}

/* Shadows: Draw fuzzy shadows under elements with the specified class.
function drawShadows(tags, classes, bottom, right, top, left, method, z) {
	tag = tag || "*";
	className = className || "*";
	
	if (tag != '*') {
		elms = getNodes(tags, classes);
*/
