/************************************************************************
*	DOM.js
*  v 1.4  9/8/06
*  Richard Davies (Richard.Davies@portlandoregon.gov)
*
*  Browser independent functions for working with the DOM
*
*  Uses W3C DOM when supported by browswer, otherwise reverts to 
*  proprietary methods.
*
************************************************************************/


/************************************************************************
* Event Functions
************************************************************************/

// Returns the target object of an event
function getEventTarget(event) {
	// W3C DOM standard is event.target.parentNode, yet IE uses event.srcElement.parentElement
	if(event.target) {
		if (event.target.nodeType == 3) 
			// Safari: If an event occurs on an element that contains text, the text node, instead of the element, 
			// is considered the target of the event. So move up an additional node in the tree to the actual element.
			return event.target.parentNode;
		else
			// Mozilla
			return event.target;
	}
	if (event.srcElement)
		// IE
		return event.srcElement;
	
	// Default value
	return event;
}


// Add event listeners to objects
function addListener(object, event, fn, useCapture) {
	if (typeof(useCapture) == "undefined")
		var useCapture = false;
		
	if (object.addEventListener) {
		// W3C DOM standard
		object.addEventListener(event, fn, useCapture);
		return true;
	} else if (object.attachEvent) {
		// IE does things to the beat of its own drum
		return object.attachEvent('on' + event, fn);
	}	else {
		// Old school!
		object['on' + event] = fn;
	}
}
addEvent = addListener;		// Alias

// Run an event after the page has loaded
// Written by Simon Willison (http://simon.incutio.com/archive/2004/05/26/addLoadEvent)
// An alternative to using addListener(window,'load',func1);
function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	}
	else {
		window.onload = function() {
			oldonload();
			func();
		}
	}
}

// Cancels the default event (i.e. navigating to a clicked link)
function cancelDefault(e) {
	if (e && e.preventDefault) {						// DOM
		e.preventDefault();
		// Safari doesn't implement preventDefault so you should also set the target's
		// onclick attribute to cancelDefaultSafari (i.e. [target].onclick = cancelDefaultSafari;)
	} else if (window.event) {	// IE
		window.event.returnValue = false;
	}
}
function cancelDefaultSafari() {
	return false;
}

// Stop an event from propogating up to parent elements
function stopPropagation(e) {
	if (e && e.stopPropagation) {						// DOM
		e.stopPropagation();
		// Apparently, Safari incorrectly supports stopPropagation and doesn't actually do anything when it's called
	} else if (window.event) {							// Good ol' IE
		window.event.cancelBubble = true;
	}
}



/************************************************************************
* DOM Traversal
************************************************************************/


// Move up a node in the DOM tree
function getParent(object) {
	// W3C DOM standard is object.parentNode, yet IE uses object.parentElement
	if(object.parentNode)
		// Mozilla
		return object.parentNode;
	if (object.parentElement)
		// IE
		return object.parentElement;

	// Default value
	return object;
}

// Returns a reference to an iframe's document
function getIFrameDocument(objectID) { 
	var contentDocument = null; 
	
	// if contentDocument exists, W3C compliant (Mozilla) 
	if (document.getElementById(objectID).contentDocument) 
		// W3C DOM
		contentDocument = document.getElementById(objectID).contentDocument; 
	else 
		// IE 
		contentDocument = document.frames[objectID].document; 

	return contentDocument; 
} 

// Get elements by class
// Written by Dustin Diaz
function getElementsByClass(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}

// The Prototype dollar function : Basically a shorthand method for getElementById
// Use: $('elementID') or $('elementID1', 'elementID2', ...)
function $() {
	var elements = new Array();
	for (var i = 0; i < arguments.length; i++) {
		var element = arguments[i];
		if (typeof element == 'string')
			element = document.getElementById(element);
		if (arguments.length == 1)
			return element;
		elements.push(element);
	}
	return elements;
}
	

/************************************************************************
* DOM Manipulation functions
************************************************************************/


// Inserts a DOM element as a child node of 'parent' after 'referenceNode',
// which must also be a child of 'parent'
function insertAfter(parent, node, referenceNode) {
	parent.insertBefore(node, referenceNode.nextSibling);
}




/************************************************************************
* Window Functions
************************************************************************/


// Returns pixel amount document is scrolled horizontally
function windowScrollX() {
	if (window.pageXOffset)
		// W3C DOM
		return window.pageXOffset;
	if (document.documentElement && document.documentElement.scrollLeft)
		// IE 6
		return document.documentElement.scrollLeft;
	if (document.body && document.body.scrollLeft)
		// IE 5
		return document.body.scrollLeft;
	
	// Default value
	return 0;
}

// Returns pixel amount document is scrolled vertically
function windowScrollY() {
	if (window.pageYOffset)
		// W3C DOM
		return window.pageYOffset;
	if (document.documentElement && document.documentElement.scrollTop)
		// IE 6
		return document.documentElement.scrollTop;
	if (document.body && document.body.scrollTop)
		// IE 5
		return document.body.scrollTop;
	
	// Default value
	return 0;
}

// Returns pixel amount specified frame/window is scrolled vertically
function frameScrollY(frame) {
	if (frame.pageYOffset)
		// W3C DOM
		return frame.pageYOffset;
	if (frame.document.documentElement && frame.document.documentElement.scrollTop)
		// IE 6
		return frame.document.documentElement.scrollTop;
	if (frame.document.body && frame.document.body.scrollTop)
		// IE 5
		return frame.document.body.scrollTop;
	
	// Default value
	return 0;
}

// Returns width of browser window
function browserWidth() {
	if (window.innerWidth)
		// W3C DOM
		return window.innerWidth;
	if (document.documentElement.clientWidth)
		// IE
		return document.documentElement.clientWidth;
	if (document.body.clientWidth)
		// IE (v5?)
		return document.body.clientWidth;

	// Default value
	return null;
}


// Returns height of browser window
function browserHeight() {
	if (window.innerHeight)
		// W3C DOM
		return window.innerHeight;
	if (document.documentElement.clientHeight)
		// IE
		return document.documentElement.clientHeight;
	if (document.body.clientHeight)
		// IE (v5?)
		return document.body.clientHeight;
	
	return null;
}


/************************************************************************
* CSS Functions
************************************************************************/


// Returns a boolean indicating whether or not 'className' has been applied to the object
function hasClass(object, className) {
	return new RegExp('\\b' + className + '\\b').test(object.className);
}

// Applies 'className' to the object
function addClass(object, className) {
	if ( !hasClass(object, className) )
		object.className += object.className ? ' '+className : className;
}

// Removes 'className' from the object
function removeClass(object, className) {
	if ( hasClass(object, className) ) {
		var classString = object.className.match(' '+className) ? ' '+className : className;
		object.className = object.className.replace(classString, '');
	}
}

// Applies 'classNameNew' instead of 'classNameOld' to the object
function swapClass(object, classNameOld, classNameNew) {
	if ( hasClass(object, classNameOld) )
		object.className = object.className.replace(classNameOld, classNameNew);
	else
		object.className = object.className.replace(classNameNew, classNameOld);
}

// Returns the computed (current) style for an object when the style is not set
// inline or with JavaScript
function computedStyle(object, style) {
	if (document.defaultView)
		// W3C DOM
		return document.defaultView.getComputedStyle(object, '').getPropertyValue(style);
	if (object.currentStyle) {
		// IE
		// Most browsers use the standard CSS notation (i.e. margin-top) but IE
		// likes camelcase (i.e. marginTop) so convert style to camelcase
		var styleCC = "";
		var props = style.split("-");				// Split style at hyphen characters into an array
		for (i = 0; i < props.length; i++) {
			if (i != 0)
				// Capitalize first character of property (unless it's the first property)
				props[i] = props[i].charAt(0).toUpperCase() + props[i].substr(1);
			styleCC += props[i];						// Concatenate properties
		}
		return object.currentStyle[styleCC];
	}
	
	return "";
}



/************************************************************************
* Cookie Functions
************************************************************************/


/*
   name - name of the cookie
   value - value of the cookie
   [expires] - expiration date of the cookie
     (defaults to end of current session)
   [path] - path for which the cookie is valid
     (defaults to path of calling document)
   [domain] - domain for which the cookie is valid
     (defaults to domain of calling document)
   [secure] - Boolean value indicating if the cookie transmission requires
     a secure transmission
   * an argument defaults when it is assigned null as a placeholder
   * a null placeholder is not required for trailing omitted arguments
*/
function setCookie( name, value, expires, path, domain, secure ) {
	var today = new Date();
	today.setTime( today.getTime() );
	if ( expires ) {
		expires = expires * 1000 * 60 * 60 * 24;
	}
	var expires_date = new Date( today.getTime() + (expires) );
	document.cookie = name+"="+escape( value ) +
		( ( expires ) ? ";expires="+expires_date.toGMTString() : "" ) + //expires.toGMTString()
		( ( path ) ? ";path=" + path : "" ) +
		( ( domain ) ? ";domain=" + domain : "" ) +
		( ( secure ) ? ";secure" : "" );
}
	

/*
  name - name of the desired cookie
  return string containing value of specified cookie or null
  if cookie does not exist
*/
function getCookie( name ) {
	var start = document.cookie.indexOf( name + "=" );
	var len = start + name.length + 1;
	if ( ( !start ) && ( name != document.cookie.substring( 0, name.length ) ) ) {
		return null;
	}
	if ( start == -1 ) return null;
	var end = document.cookie.indexOf( ";", len );
	if ( end == -1 ) end = document.cookie.length;
	return unescape( document.cookie.substring( len, end ) );
}

/*
   name - name of the cookie
   [path] - path of the cookie (must be same as path used to create cookie)
   [domain] - domain of the cookie (must be same as domain used to
     create cookie)
   path and domain default if assigned null or omitted if no explicit
     argument proceeds
*/
function deleteCookie( name, path, domain ) {
	if ( getCookie( name ) ) document.cookie = name + "=" +
			( ( path ) ? ";path=" + path : "") +
			( ( domain ) ? ";domain=" + domain : "" ) +
			";expires=Thu, 01-Jan-1970 00:00:01 GMT";
}

