/* to include this file in a .html or .php script, type this in the head brackets
<script type="text/javascript" language="Javascript" src="MyJavaScriptFunctions.js"></script>
*/

function addLoadEvent(func){
/*This function is called AddLoadEvent, and it was written by Simon Willison.
It takes a single argument: the name of the function that you want to execute when the page loads
This function effectively creates a queue of functions to be executed when the page loads.
To add functions to this queue, I just need to write:
addLoadEvent(func);

If you want to pass parameters into your func, then do this:
addLoadEvent( 
	function() {
		function2(param1, param2);
	}
);
*/
	var oldonload = window.onload;
	if (typeof window.onload != 'function'){
		window.onload = func;
	}else {
		window.onload = function(){
			oldonload();
			func();
		}
	}
}

function insertAfter(newElement, targetElement) {
/*function -- that for some reason the DOM doesn't provide -- that inserts a node after another node already
placed in the DOM. The 'newElement' argument is the content that you want to place after the 'targetElement'*/
	var parent = targetElement.parentNode;
	if (parent.lastChild == targetElement){
		parent.appendChild(newElement);
	} else{
		parent.insertBefore(newElement, targetElement,nextSibling);
	}
}

function highlightPage(nav, here) {
/*this function presents the navigation bar so that the current page's link in the navigation bar
is un-clickable. Also, it allows you to use CSS to display this link differently from the other links
in the navigation. This function also adds an 'id' to the body tag, so that each page can have a unique
style associated with it (for example, changing the header image of each page). The name of body id tag will
be the name of the text within the un-clickable link's <a> tag.
Arguments:
	nav - the id name of the division thata contains the navigation (should be a string)
	here - the class name of the link that will be un-clickable
		Style this link as such with CSS (to make it un-clickable):
			#nav a.here:link,
			#nav a.here:visited,
			#nav a.here:hover,
			#nav a.here:active {
				color: #---;
				background-color: #---;
			}
*/
	if (!document.getElementsByTagName) return false;
	if (!document.getElementById) return false;
	if (!document.getElementById(nav)) return false;
	var nav = document.getElementById(nav);
	var links = nav.getElementsByTagName("a");
	for (var i = 0; i < links.length; i++) {
		var linkurl = links[i].getAttribute("href");
		var currenturl = window.location.href;
		if (currenturl.indexOf(linkurl) != -1) {
			links[i].className = here;   //assigns class to un-clickable link
			var linktext = links[i].lastChild.nodeValue.toLowerCase(); //get text within 'a' tag
			document.body.setAttribute("id", linktext); //assign body id tag
		}
	}
}

function stripeTables(){
/*Apply a different background color to every second row in a table*/
	if (!document.getElementsByTagName) return false;
	var tables = document.getElementsByTagName("table");
	for (var i = 0 ; i < tables.length; i++){
		var odd = false;
		var rows = tables[i].getElementsByTagName("tr");
		for(var j = 0; j < rows.length; j++){
			if (odd == true){
				addClass(rows[j], "odd");
				odd = false;
			} else{
				odd = true;
			}
		}
	}
}

function highlightRows(){
/*this function bolds the text in any table row whenever it is moused over.
In practice, this will only work in certain browsers. -- unless W3C changes it
this function should be called in addLoadEvent(highlightRows)*/
	if (!document.getElementsByTagName) return false;
	var rows = document.getElementsByTagName("tr");
	for (var i = 0; i < rows.length; i++){
		rows[i].onmouseover = function(){
			this.style.fontWeight = "bold";
		}
		rows[i].onmouseout = function(){
			this.style.fontWeight = "normal";
		}
	}
}

function addClass(element, value){
/*this allows element nodes to have class names, rather than inline styles
this makes it easy to edit class CSS properties within the CSS file*/
	if (!element.className){
		element.className = value;
	} else {
		newClassName = element.className;
		newClassName += " ";
		newClassName += value;
		element.className = newClassName;
	}
}

function styleElementSiblings(tag,theclass) {
/*this function styles all element nodes preceding the node specified in 'tag'
for example, if you wish to add a style to all paragraphs after headers,
you would call styleElementSiblings("h2","paragraph")*/
	if (!document.getElementsByTagName) return false;
	var elems = document.getElementsByTagName(tag);
	for (var i = 0; i < elems.length; i++) {
		var elem = getNextElement(elems[i].nextSibling);
		addClass(elem, theclass);
	}
}

function moveElement(elementID, final_x, final_y, interval){
/*this function is used for animation. It moves a specific element to a specific
place (with a damping effect), pausing for a specific amount of time between movements. All of that information
is hardcoded into the fucntion.
Arguments:
	1.elementID -- the ID of the element you want to move
	2.final_x -- the left position to which you want to move the element
	3.final_y -- the top position to which you want to move the element
	4.interval -- how long to wait between each movement

Example of use by having image with separate images within it move:
	<div id = "slideshow">
		<img src="topics.gif" id="preview"/>
	</div>
	
	--javascript--
	links[0].onmouseover= function(){
		moveElement("preview",-100,0,10);
	}
	
	--CSS--
	#slideshow {
		width:100px; height:100px;
		position:relative;
		overflow:hidden;
	}
	#preview {
		position:absolute;
	}
*/
		

	if (!document.getElementById) return false;
	if (!document.getElementByID(elementID)) return false;
	var elem = document.getElementById(elementID);
	if (elem.movement) {
		clearTimeout(elem.movement);
	}
	if (!elem.style.left) {
		elem.style.left = "0px";
	}
	if (!elem.style.top) {
		elem.style.top = "0px";
	}
	var xpos = parseInt(elem.style.left);
	var ypos = parseInt(elem.style.top);
	if (xpos == final_x && ypos == final_y) {
		return true;
	}
	if (xpos < final_x) {
		var dist = Math.ceil((final_x - xpos)/10);
		xpos = xpos + dist;
	}
	if (xpos > final_x) {
		var dist = Math.ceil((xpos - final_x)/10);
		xpos = xpos - dist;
	}
	if (ypos < final_y) {
		var dist = Math.ceil((final_y - ypos)/10);
		ypos = ypos + dist;
	}
	if (ypos > final_y) {
		var dist = Math.ceil((ypos - final_y)/10);
		ypos = ypos - dist;
	}
	elem.style.left = xpos + "px";
	elem.style.top = ypos + "px";
	var repeat = "moveElement('"+elementID+"',"+final_x+","+final_y+","+interval+")";
	elem.movement = setTimeout(repeat,interval);
}

function resetFields(whichform) {
/*Form fields may have default initial values. These values are useful for indicating to the user
what they should type in each field. However, it can be tedious for the user to delete these default
values. This function automatically deletes the default values whenever a form field is brought into
focus (i.e. clicked on). Likewise, if the user moves on without entering a value in the field, the
default value reappears.
**You need to activate the function by passing it a Form object. */
	for (var i = 0; I < whichform.elements.length; i++) {
		var element = whichform.elements[i];
		if (element.type == "submit") continue;
		if (element.defaultValue) continue;
		element.onfocus = function() {
			if (this.value == this.defaultValue) {
				this.value = "";
			}
		}
		element.onblur = function() {
			if (this.value == "") {
				this.value = this.defaultValue;
			}
		}
	}
}

function prepareForms() {
/*this function prepares a form so that resetFields is a feature of the form.
this function must be queued as: addLoadEvent(prepareForms);*/
	for (var i = 0; i < document.forms.length; i++) {
		var thisform = document.forms[i];
		resetFields(thisform);
	}
}

function focusLabels() {
/*the label element is a very useful aid to accessibility. Using the 'for' attribute, it specifically
associates a piece of text with a form field. This can be of great value to screen-reading software.
*/
	if (!document.getElementsByTagName) return false;
	var labels = document.getElementsByTagName("label");
	for (var i = 0; i < labels.length; i++) {
		if (!labels[i].getAttribute("for")) continue;
		labels[i].onclick = function() {
			var id = this.getAttribute("for");
			if (!document.getElementById(id)) return false;
			var element = document.getElementById(id);
			element.focus();
		}
	}
}

function validateLogin(username, password){
//this function checks to see if user entry is valid. This is a very useful method
//returns true if user input is valid
//returns false if username or password is either empty or contains a punctuation
//the first argument is the username object : document.form.username  -- NOT THE VALUE
//the second argument is the password object: document.form.password  -- NOT THE VALUE
//the value is not passes so that we can focus on the text box after an error message appears
	if (isBlank(username.value)){
		alert("You must enter a username before submitting.");
		username.focus();
		return false;
	}
	else if (containsPunct(username.value)){
		alert("You must enter a valid username with no punctuations.");
		username.focus();
		return false;
	}
	if (isBlank(password.value)){
		alert("You must enter a password before submitting.");
		password.focus();
		return false;
	}
	else if (containsPunct(password.value)){
		alert("You must enter a valid password with no punctuations.");
		password.focus();
		return false;
	}
	return true;
}

function containsNumber(input){
//this function looks at the string and determines if there is a number in the string
//this works for names, for example, since no names contain numbers in them.
//returns true if there is a number in string, returns false otherwise
	for (i = 0; i < input.length; i++){
		if ((input.charAt(i) * 1) >= 0){ //this means that the character in the string is a number
			return true;
		}
	}
	return false;
}
function containsPunct(input){
//this function looks at the string and determines if there is a punctuation in the string
//this works for usernames, for example, since no usernames should contain punctuations in them.
//returns true if there is a punctuation in string, returns false otherwise
	return /[\@\#\%\^\&\-\;\'\"\<\>\!\$\(\)\*\+\.\/\:\=\?\[\\\]\^\{\|\}\,]/.test(input);
}	
function isBlank(input){
//this function looks at the string and determines if it is blank
//this works well for any type of input
//returns true if string is blank, false otherwise
	if (input == "")
		return true;
	else
		return false;
}

function swapImage(version, imagename){
//this function takes two parameters, the version name(ON or OFF) and the image name
//This makes it possible to handle all image swapping with only this function.
//the image swapping is used for buttons and hovering effects
	if (document.images){
		document[imagename].src = eval(imagename + version + ".src");
	}
}

function resizeImage(imgSrcPath, imgSrcNameAndId, maxWidth) {
	//input: path to img file, filename of image to be resized, the max width that you want the image to take up
	//this function takes into account the proportion of dimensions of original image
	//and applies that proportion to the create dimensions for a new image
	//thus, you can use this function to enlarge or shrink an image
	
	//get image dimensions
	var img = new Image();
	img.src = imgSrcPath + imgSrcNameAndId;	
	var width = img.width;
	var ht = img.height;
	var ratio = ht/width;           //this ratio tells us proportion of image, which should
				       //be held constant no matter what size new image is

	if (ratio <= .8){ //if image tends to be fat
			   //most pictures are .75
		width = maxWidth;
		ht = ratio * width;
	}
	else if (ratio > .8 && ratio <= 1.2){ //it is a tall,skinny image
		width = maxWidth * .8;  //reduce the width of image by 20 pixels
		ht = ratio * width;
	}
	else if (ratio > 1.2 && ratio <= 1.6){ //ratio is greater than 1.2 but less than 1.6
		width = maxWidth * .62;
		ht = ratio * width;
	}
	else{
		width = maxWidth * .5;
		ht = ratio * width;
	}
	
	//set image's new dimenions
	var newImg = document.getElementById(imgSrcNameAndId);
	newImg.width = width;
	newImg.height = ht;
}

function replaceImage(imgId, newImgPath) {
//change the src attribute of an image with id of 'imgId' to 'newImgPath'
	var oldImg = document.getElementById(imgId);
	oldImg.src = newImgPath;
}


////////////////////////////////////////////////////////////////////////////////////////////////////
// makeAsynchronousRequest-- submits an asynchronous http request to the specified url and invokes 
// callbackFunc upon completion
//  @param url - the url of the request
//  @param callbackFunc the function to be called upon completion of the request. The function will
//        receive the XmlHttpRequest object as an argument.
////////////////////////////////////////////////////////////////////////////////////////////////////
function makeAsynchronousRequest(url, callbackFunc) {
	http_request = createHttpRequest();
	if (!http_request) {
		alert('Cannot create XMLHTTP instance');
		return false;
	}

	http_request.onreadystatechange = function() { 
		if( http_request.readyState == 4 ) {
			callbackFunc( http_request );
		}
	};

	http_request.open('GET', url, true);
	http_request.send(null);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// makeSynchronousRequest-- submits a synchronous http request to the specified url and invokes 
// callbackFunc upon completion
//  @param url - the url of the request
//  @param callbackFunc the function to be called upon completion of the request. The function will
//        receive the XmlHttpRequest object as an argument.
////////////////////////////////////////////////////////////////////////////////////////////////////
function makeSynchronousRequest(url, callbackFunc) {
	var http_request = createHttpRequest();
	if (!http_request) {
		alert('Cannot create XMLHTTP instance');
		return false;
	}

	http_request.open('GET', url, false);
	http_request.send(null);
	callbackFunc(http_request);
}

function createHttpRequest() {
	var http_request = false;
	if (window.XMLHttpRequest) { // Mozilla, Safari,...
		http_request = new XMLHttpRequest();
		if (http_request.overrideMimeType) {
			http_request.overrideMimeType('text/xml');
		}
	}
	else if (window.ActiveXObject) { // IE
		try {
			http_request = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				http_request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {}
		}
	}	
	return http_request;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// getElementValue
////////////////////////////////////////////////////////////////////////////////////////////////////
function getElementValue( element ) {
	if( element == null ) {
		return null;
	}
	
	if( element.tagName == "INPUT" ) {
		return element.value;
	}

	var value;
	if( element.hasChildNodes() ) {
		value = element.firstChild.nodeValue;
	}
	else {
		value = element.nodeValue;
	}

	return value;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// setElementValue
////////////////////////////////////////////////////////////////////////////////////////////////////
function setElementValue( element, value ) {
	if( element == null ) {
		return;
	}
	
	if( element.tagName == "INPUT") {
		element.value = value;
		element.defaultValue = value;
		return;
	}
	
	if( element.tagName == "SELECT" ) {
		element.value = value;
		for( var i = 0; i < element.options.length; i++ ) {
			if( element.options[i].value == value ) {
				element.options[i].defaultSelected=true;
			}
			else {
				element.options[i].defaultSelected=false;
			}
		}
		return;
	}

	newElem = document.createTextNode( value );
	if( element.hasChildNodes() ) {
		element.replaceChild( newElem, element.firstChild );
	}
	else {
		element.appendChild( newElem );
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// elementChildren-- browser agnostic method for getting element.children/element.childNodes
////////////////////////////////////////////////////////////////////////////////////////////////////
function elementChildren( element ) {
	if( element.children ) {
		children = element.children; // IE
	}
	else {
		children = element.childNodes; // moz
	}
	return children;
}

function removeChildren( element ) {
	while( element.hasChildNodes() ) {
		element.removeChild( element.firstChild );
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// getChildrenWithAttribute-- returns an array of the specified element's descendants who possess the
// named attribute. if attrValue is provided this will only return elements with a
// matching value for the specified attribute. This does not drill beyond the first occurrence,
// so it allows us to find "children" that are not first descendants of the parent node. This is
// useful in that it allows us to ignore html tags that may be cosmetic wrappers around the items
// we're looking for.
////////////////////////////////////////////////////////////////////////////////////////////////////
function getChildrenWithAttribute( element, attrName, attrValue, limit ) {

	var results = new Array();

	if( element == null ) {
		return results;
	}

	if( limit == null ) {
		limit = 99999;
	}

	if( attrName == "class" || attrName == "className" ) {
		attrName = getCssClassAttrName();
	}

	var children = elementChildren( element );

	if( children ) {
		for( var i = 0; i < children.length; i++ ) {
			var curChild = children.item(i);
			if(	(	curChild.getAttribute
				&&	curChild.getAttribute( attrName )
				&&	(!attrValue || curChild.getAttribute( attrName ) == attrValue ) ) 
				|| attrName == "tagName" && curChild.tagName == attrValue )
			{
					results[ results.length ] = curChild;
					if( limit > 0 && results.length >= limit ) {
						return results;
					}
			} 
			else {
				var deepResults = getChildrenWithAttribute( curChild, attrName, attrValue, Math.max( limit, limit - results.length ) );
				if( deepResults.length != 0 ) {
					results = results.concat( deepResults );
				}
			}
		}

	}

	return results;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// findContainerWithAttribute-- finds the element containing startElem that
// has the specified attribute. If a value argument is provided, returns the
// container that has the named attribute with the specified value.
////////////////////////////////////////////////////////////////////////////////////////////////////
function findContainerWithAttribute( startElem, attrName, attrValue ) {

	var curElem = startElem.parentNode;
	
	if( attrName == "class" || attrName == "className" ) {
		attrName = getCssClassAttrName();
	}

	// if the currentElement doesn't have the attribute or if a value was specified and it doesn't match currentElement's value for
	// the specified attribute, move up to the parent. repeat until we find a match or run out of parents.
    while( curElem != null
	    	&&	curElem.getAttribute
			&& ( curElem.getAttribute( attrName ) == null || curElem.getAttribute( attrName ) == ""
		    		||	(attrValue && curElem.getAttribute( attrName ) != attrValue ) )
			&& ! ( attrName == "tagName" && curElem.tagName == attrValue )
	) {
    	curElem = curElem.parentNode;
	}

	return (curElem && curElem.getAttribute) ? curElem : null;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// previousNode-- element.previousSibling returns white space nodes; we're only interested in elements.
////////////////////////////////////////////////////////////////////////////////////////////////////
function previousNode( startElem ) {
	prev = startElem.previousSibling;
	while( prev != null && prev.nodeType != 1 ) {
		prev = prev.previousSibling;
	}
	return prev;
}


////////////////////////////////////////////////////////////////////////////////////////////////////
// nextNode-- element.nextSibling returns white space nodes; we're only interested in elements.
////////////////////////////////////////////////////////////////////////////////////////////////////
function nextNode( startElem ) {
	next = startElem.nextSibling;
	while( next != null && next.nodeType != 1 ) {
		next = next.nextSibling;
	}
	return next;
}

var CSS = {
	addClass:function( elem, cssClassName ) {
		if( elem.className.indexOf( cssClassName ) < 0 ) {
			elem.className += (elem.className ? ' ' : '') + cssClassName;
		}
	},
	removeClass:function( elem, cssClassName ) {
		var expr = elem.className.match(' ' + cssClassName ) ? ' ' + cssClassName : cssClassName;
		elem.className = elem.className.replace( expr, '' );
	}
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// elementWidth-- returns the pixel width of the given element
////////////////////////////////////////////////////////////////////////////////////////////////////
function elementWidth( elem ) {
	return elementDimensions( elem ).width;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// elementHeight-- returns the pixel height of the given element
////////////////////////////////////////////////////////////////////////////////////////////////////
function elementHeight( elem ) {
	return elem.offsetHeight; elementDimensions( elem ).height;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// windowInfo-- returns a struct containing size and scroll information about the window.
////////////////////////////////////////////////////////////////////////////////////////////////////
function windowInfo() {	
	var width = 0;
	var height = 0;
	var yScroll = 0;
	var xScroll = 0;
	
	// get window dimensions
	if( typeof( window.innerWidth ) == 'number' ) {
		// moz
		width = window.innerWidth;
		height = window.innerHeight;
	}
	else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		//IE 6+ in 'standards compliant mode'
		width = document.documentElement.clientWidth;
		height = document.documentElement.clientHeight;
	}
	else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
		//IE 4 compatible
		width = document.body.clientWidth;
		height = document.body.clientHeight;
	}
	
	// get scroll position
	yScroll = getScrollY();
	xScroll = getScrollX();
	
	return { height:height, width:width, yScroll:yScroll, xScroll:xScroll };
}

function resizeImage_Mine(){
	var imgPath = 'images/henaac2008/';
				var maxWidth = 150;
				resizeImage( imgPath, '1.jpg', maxWidth );
				
}