// NICK NIELSEN JAVASCRIPT APPLICATION LIBRARY
// v 1.0




// SHUFFLE ARRAY (New array method that randomly shuffles and array.)

Array.prototype.shuffle = function() {
	var temp = new Array();
	var length = this.length;
	for(i=0; i<length; i++) {
		var randIndex = Math.floor(Math.random()*(this.length));
		var randElement = this.splice(randIndex,1);
		temp.push(randElement);
	}
	return temp;
}




// REPLACE ONE CHARACTER (New string method.)
// needle: ANY STRING: required (String to search for.)
// replacement: ANY STRING: required (Replace needle with this string.)
// number: ANY NUMBER≥0 (Number of replacements to make.  Default is "1";}
// index: ANY NUMBER≥0 (Index to begin searching. Default is "0".)

String.prototype.charReplace = function(needle,replacement,number,index) {
	if(!number) {var number=1;}
	if(!index) {var index=0;}
	var newString = '';
	var count = 0;
	for(i=0; i<this.length; i++) {
		if(this.charAt(i)==needle && count<number && i>=index) {
			newString+=replacement;
			count++;
		}
		else {newString+=this.charAt(i);}
	}
	return newString;
}




// GET ELEMENT BY ID

function $(id) {
	return document.getElementById(id);
}




// FADE IN - OUT ELEMENT
// direction: 1 OR -1  ("1" for fade in; "-1" for fade out. If no value is specified, or if "0" is entered, element will alternate between in and out.)
// speed: 0 < SPEED ≤ 100 ("0" is the slowest speed, with no fade - resorts to default; "100" is the fastest.  Default is "5".  Entering "0" sets to default.)
// hide: TRUE OR FALSE  (When fading out, if set to "TRUE", hides the element after it has completely faded out. Defatult value is "FALSE".)
// show: ANY ELEMENT DISPLAY VALUE  (When fading in, sets the display value of the element if it was previously "none".  Default is "block".)
// callback: ANY JAVASCRIPT CODE  (runs a script after completion.)

function fade(element,direction,speed,hide,show,callback) {
	var element, direction, speed, hide, show, callback, opacity, increment, animateFade;
	if(BrowserDetect.browser=='Explorer') {
		if(!element.style.filter) {opacity=1;}
		else {
			var string = element.style.filter.replace('alpha(opacity=','');
			string = string.replace(')','');
			opacity = string/100;
		}
	}
	else {
		if(!element.style.opacity) {opacity=1;}
		else {opacity = element.style.opacity;}
	}
	if(opacity>1) {opacity=1;}
	if(opacity<0) {opacity=0;}
	if(element.style.display=='none') {opacity=0;}
	element.style.opacity = opacity;
	element.style.filter = 'alpha(opacity='+opacity*100+')';
	if(!direction | direction==0) {
		if(opacity<.5) {direction=1;}
		else {direction=-1;}
	}
	if(!show | show=='none') {show='block';}
	if(element.style.display=='none' && direction==1) {element.style.display=show;}
	if(!speed | speed==0) {speed=5;}
	increment = .01*speed*direction;
	animateFade = function() {
		opacity = eval(opacity+'+'+increment);
		if(opacity<=0) {opacity=0;}
		if(opacity>=1) {opacity=1;}
		element.style.opacity = opacity;
		element.style.filter = 'alpha(opacity='+opacity*100+')';
		if(opacity==0 | opacity==1) {
			if(opacity==0 && hide) {element.style.display='none';}
			if(callback) {callback();}
			return false;
		}
		setTimeout(animateFade);
	}
	animateFade();
}




// DRAG & DROP
// evt: EVENT (The javascript event.)
// stack: TRUE OR FALSE (Brings selected element to the front of a stack.  Default is false.)

function drag(element,evt,stack) {
	var parentWidth,parentHeight,elementWidth,
	elementHeight,mouseStartX,mouseStartY,
	mouseX,mouseY,velX,velY,elementX,
	elementY,newX,newY,children,siblings,
	sortByZIndex,high,low,increment,zIndex,zKey;
	element.parentNode.style.position = 'relative';
	element.style.position = 'absolute';
	if(stack) {
		children = element.parentNode.childNodes;
		siblings = new Array();
		for (i=0; i<children.length; i++) {
			if(children[i].style) {
				siblings.push(children[i]);
				if(!children[i].style.zIndex) {children[i].style.zIndex=0;}
			}
		}
		sortByZIndex = function(a,b) {return a.style.zIndex - b.style.zIndex;}
		siblings.sort(sortByZIndex);
		high = siblings[siblings.length-1].style.zIndex;
		low = siblings[0].style.zIndex;
		increment = (high-low)/(siblings.length-1);
		var check = new Array();
		for(i=0; i<siblings.length; i++) {siblings[i].style.zIndex = (increment*i)+eval(low); check.push(siblings[i].style.zIndex);}
		//alert(check);
		var lower = false;
		for(i=0; i<siblings.length; i++) {
			if(lower==true) {siblings[i].style.zIndex = siblings[i].style.zIndex-increment;}
			if(siblings[i]==element) {
				lower = true;
				siblings[i].style.zIndex = increment*(siblings.length-1);
			}
		}
	}			
	document.onselectstart = function() {return false;}
	document.ondragstart = function() {return false;}
	parentWidth = element.parentNode.clientWidth;
	parentHeight = element.parentNode.clientHeight;
	element.style.left = element.offsetLeft+'px';
	element.style.top = element.offsetTop+'px';
	elementWidth = element.offsetWidth;
	elementHeight = element.offsetHeight;
	mouseStartX = evt.clientX;
	mouseStartY = evt.clientY;
	document.onmousemove = function(evt) {
		document.body.style.MozUserSelect = 'none';
		if(window.event) {evt = window.event;}
		document.onmouseup = function() {endDrag();}
		mouseX = evt.clientX;
		mouseY = evt.clientY;
		velX = mouseX - mouseStartX;
		velY = mouseY - mouseStartY;
		mouseStartX = mouseX;
		mouseStartY = mouseY;
		elementX = element.offsetLeft;
		elementY = element.offsetTop;
		if(velX<0 && elementX>0) {
			if((elementX+velX)<0) {newX=0;}
			else {newX = elementX+velX;}
			element.style.left = newX+'px';
		}
		if(velX>0 && (elementX+elementWidth)<parentWidth) {
			if((elementX+elementWidth+velX)>parentWidth) {newX = parentWidth-elementWidth;}
			else {newX = elementX+velX;}
			element.style.left = newX+'px';
		}
		if(velY<0 && elementY>0) {
			if((elementY+velY)<0) {newY=0;}
			else {newY = elementY+velY;}
			element.style.top = newY+'px';
		}
		if(velY>0 && (elementY+elementHeight)<parentHeight) {
			if((elementY+elementHeight+velY)>parentHeight) {newY = parentHeight-elementHeight;}
			else {newY = elementY+velY;}
			element.style.top = newY+'px';
		}
	}
	endDrag = function() {
		document.onmousemove = '';
		document.onselectstart = '';
		document.ondragstart = '';
		document.body.style.MozUserSelect = '';
	}
}




// FIND RELATIVE SCRIPT PATH
// name: NAME OF ANY JAVASCRIPT FILE LOADED IN <HEAD></HEAD>. (Function returns the relative path of the loaded script.)

function scriptPath(name) {
	var head = document.getElementsByTagName('head')[0];
	var scripts = head.getElementsByTagName('script');
	for (i=0; i<scripts.length; i++) {
		source = scripts[i].src;
		if(source.indexOf(name)!=-1) {path = source;}
	}
	var folder = path.replace(name,'');
	var rootPath = window.location.toString();
	var rootFolder = rootPath.slice(0,rootPath.lastIndexOf('/'));
	var path = folder.replace(rootFolder,'');
	if(path.charAt(0)=='/') {path = path.charReplace('/','');}
	return path;
}




// IMAGE SLIDESHOW
// slides_path: RELATIVE FOLDER PATH: required (Relative path to folder where slide images reside.)
// element_id: ANY ELEMENT ID: required (Id of element in which to display slide show.)
// speed: 0 < SPEED ≤ 100 (Speed at which slides are cross-faded. Default is 1.  If set to 0, speed is set to default.)
// time: ANY NUMBER (Time in seconds to display each slide before changing. Default is 3.  If set to 0, time is set to default.)
// shuffle: TRUE OR FALSE (When set to "true", slides are randomly shuffled.  Default is "false".)
// start: FILE NAME OR FALSE (Specify a starting slide.  Default is "false".)
// pause: TRUE OR FALSE (If "true", pauses slideshow onmouseover. Default is "false".)

function slideShow(slides_path,element_id,speed,time,shuffle,start,pause) {
	if(!pause) {pause=false;}
	if(!speed | speed==0) {var speed = 1;}
	if(!time | time==0) {var time=3;}
	time = time*1000;
	if(!shuffle) {var shuffle=false;}
	var element = $(element_id);
	var paused = false;
	if(pause) {
		element.style.cursor = 'pointer';
		var mouseover = function() {
			element.onmouseover = function() {
				var startPause = function() {mouseout(); paused=true; wait();}
				var timeout = setTimeout(startPause,1000);
				element.onmouseout = function() {clearTimeout(timeout);}
			}
		}
		var mouseout = function() {
			element.onmouseout = function() {
				var endPause = function() {mouseover(); paused=false; rotateImages();}
				var timeout = setTimeout(endPause,1000);
				element.onmouseover = function() {clearTimeout(timeout);}
			}
		}
		var wait = function() {if(paused==true) {setTimeout(wait);}}
		mouseover();
	}
	var relPath = scriptPath('application.js');
	var dirSplit = relPath.split('/');
	var dirs = new Array();
	for(i=0; i<dirSplit.length; i++) {if(dirSplit[i]!='') {dirs.push(dirSplit[i]);}}
	var upDirs = '';
	for (i=0; i<dirs.length; i++) {upDirs+='../';}
	var the_script = relPath+'list_files.php?path='+encodeURIComponent(slides_path)+'&upDirs='+encodeURIComponent(upDirs);
	var files = eval(ajax_request(the_script,false));
	if(shuffle) {files = files.shuffle();}
	if(start) {
		for(i=0; i<files.length; i++) {
			if(files[i]==start) {files.splice(i,1);}
		}
		files.unshift(start);
	}
	var images = new Array();
	element.style.position = 'relative';
	for (i=0; i<files.length; i++) {
		var image = new Image();
		image.style.display = 'none';
		image.style.position = 'absolute';
		image.style.width = element.style.width;
		image.style.height = element.style.height;
		image.src = slides_path+files[i];
		image.style.zIndex = 0;
		images.push(image);
		element.appendChild(image);
	}
	var div = document.createElement('div');
	div.style.clear = 'both';
	div.style.width = '100%';
	element.appendChild(div);
	var startIndex = 0;
	var image1 = images[startIndex];
	startIndex++;
	if(startIndex>images.length-1) {startIndex=0;}
	var image2 = images[startIndex];
	var rotateImages = function() {
		var func = function() {
			image1 = images[startIndex];
			startIndex++;
			if(startIndex>images.length-1) {startIndex=0;}
			image2 = images[startIndex];
			setTimeout(rotateImages,time);
		}
		if(paused==false) {
			image1.style.zIndex = 0;
			image2.style.zIndex = 1;
			fade(image1,0,speed,false);
			fade(image2,0,speed,false,'block',func);
		}
	}
	var func = function() {
		setTimeout(rotateImages,time);
	}
	image1.style.zIndex = 1;
	fade(image1,0,speed,false,'block',func);
}




// AJAX REQUEST
// theScript: RELATIVE PHP FILE PATH: required (Relative path to php script to be executed, including GET variables.)
// sync: TRUE OR FALSE (Indicate whether or not the call is assynchronous. Default is false.)
// callback: ANY JAVASCRIPT FUNCTION (Function to be executed after call is finished.)

function ajax_request(theScript,sync,callback) {
	if(!sync) {sync=false;}
	var GetXmlHttpObject = function() {
		if (window.XMLHttpRequest) {
  			// code for IE7+, Firefox, Chrome, Opera, Safari
 			return new XMLHttpRequest();
 		}
		else if (window.ActiveXObject) {
  			// code for IE6, IE5
  			return new ActiveXObject("Microsoft.XMLHTTP");
  		}
  	}
	var xmlhttp;
	xmlhttp = GetXmlHttpObject();
	if (xmlhttp==null) {alert("Your browser does not support XMLHTTP!");}
	if (sync == true) {
		xmlhttp.onreadystatechange=function() {
			if(xmlhttp.readyState == 4) {
				script_response = xmlhttp.responseText;
				if(callback) {callback(script_response);}
				else {return script_response;}
			}
		}
	}
	xmlhttp.open("GET",theScript,sync);
	xmlhttp.send(null);
	if (sync == false) {return xmlhttp.responseText;}
}




// GET FOLDER CONTENTS
// returns an array of files in a local folder, given the local folder path
// !IMPORTANT - make sure to change scriptPath to the name of this script file.

function folder_get_contents(path) {
	var path = encodeURIComponent(path);
	var relPath = scriptPath('application_release.js'); // change value in scriptPath to name of this script file.
	var dirSplit = relPath.split('/');
	var dirs = new Array();
	for(i=0; i<dirSplit.length; i++) {if(dirSplit[i]!='') {dirs.push(dirSplit[i]);}}
	var upDirs = '';
	for (i=0; i<dirs.length; i++) {upDirs+='../';}
	var script = relPath+'list_files.php?path='+path+'&upDirs='+encodeURIComponent(upDirs);
	var contents = ajax_request(script,false);
	return eval(contents);
}
