/*
ALL SCRIPTING IN THIS DOCUMENT WAS WRITTEN BY NICK ANNIS FOR THE ENGINES AND ENERGY CONVERSION LAB (CSU)
	-last revised: 3/12/09
	
	requires additional files:
		-collapsable.js
		-genMotion.js
		-vector.js
		-tools.js

AVAILABLE FUNCTIONS:
-constructor				:	generates all necessary html elements for the scrollBox and applies them as
								innerHTML value to the case passed in as an argument
									-args:	name 		- STRING what the scrollBox will reference itself as in
														  window["<name>"] calls
											divObj 		- ELEMENT case to apply html to
											viewWidth 	- INT width to set the display to (pixels)
											viewHeight	- INT height to set the display to (pixels)
											entries		- INT number of entries in the data
											
-sMouseDown					:	when mouse is clicked in the scrollbar, sets up necessary function calls for
								the scrollbar to function
									-args:	e			-EVENT fired from the clicked element
									
-sMouseUp					:	when mouse is released, disables previous function calls for scrollbar to function
-trackMouse					:	tracks the location of the mouse on the screen, translates that position
								to where the slider in the scrollbar should be positioned
									-args:	e			-EVENT fired from onmousemove
-transSliderPos				:	translates the style.top value of the slider to its corresponding viewbox position
									-args:	slideTop	-INT value of style.top of the slider
transViewPos				:	translates the current style.top value of the viewbox to its corresponding slider
								position
									-args:	currTop		-INT value of style.top of the viewbox
getOffset					:	returns the total offsetTop value of the specified element, with respect to
								the top of the page
									-args:	Element		-ELEMENT to calculate top value
										NOTE: IE sometimes returns erroneous values, error checking required
setExpand					:	when called, determines if the current position the scrollbox is in has extra
								information available. If so, will make the case for displaying the info visible
scrollDown					:	sets up setInerval calls to move the viewport accordingly
									-args:	amount		-INT value, amount to move down by
scrollUp					:	sets up setInerval calls to move the viewport accordingly
									-args:	amount		-INT value, amount to move up by
intDown						:	incremental function for animating viewport, called by scrollDown setInterval
								calls
intUp						:	incremental function for animating viewport, called by scrollUp setInterval calls
stopScroll					:	stops all scrolling generated by setInterval calls
checkArrows					:	checks the current position of the viewbox and determines what status the arrows 
								should be at, sets accordingly
arrows						:	enables or disables the specified arrow
									-args:	id			-STRING value ("up" or "down") specifying which arrow 
														 to modify
											mod			-BOOLEAN value specifying whether the arrow is enabled
														 (true) or disabled (false) 
swapImage					:	swaps an image element's source for a new specified source, does error checking
								for arrows, whether or not they're allowed to change their source
									-args:	imgid		-STRING value specifying the id of the image to modify
											newsrc		-STRING value specifying the new source to apply
jumpTo						: 	snaps the viewbox to the specified index
									-args:	index		-INT value, which index position to snap to
fixTrans					:	fixes IE6 bug where transparent .png images arent rendered correctly
									-args:	imgId		-STRING value, id of the images to check and possibly fix
addExtraInfo				:	associates inHtml of extra info to index location, when the specified index is 
								selected/visible in the viewbox, enables the extra info box to be expanded, 
								displaying inHtml value as the innerHTML of the extra info box
									-args 	index			-INT value of the index to associate with
											inHtml			-innerHTML to display when box is expanded
												NOTE:	there is not error checking for inHtml or its dimensions
preloadImages				:	preloads the images specifically used by the class
getUID						:	returns the unique id of the object
getTotalHeight				:	returns the total height of the element in the viewbox
getViewHeight				:	returns the height of the viewbox
getName						:	returns the name specified in the argument of the constructor
setRate						:	sets a new rate for the incremental animation functions to move by (pixels)
									-args	newRate			-INT value of the new rate to use
setNewInterval				:	sets a new interval, this is how many milliseconds between incremental function
								calls
									-args	newInterval		-INT value of the new interval to use
getArgs						:	parses url args that specify what state the scroller class should be in
									NOTE:	format for args - 
					<URL>?<scroller object name>=<index, int>.<boolean: extra info open or closed, optional>
				ex:	http://www.eecl.colostate.edu/engines.html?engine=1.true

*/

function scrollBox(name,divOBJ,viewWidth,viewHeight,entries){
	if(typeof scrollBox.count == 'undefined'){
		scrollBox.count = 0;
	}
	scrollBox.count++;
	
	this.name = name;
	window[this.name] = this;
	this.object = "window[\""+this.name+"\"]";
	this.debug = false;
	
	this.viewWidth = viewWidth;
	this.viewHeight = viewHeight;
	this.entries = entries;
	this.tCHeight = this.entries*this.viewHeight;
	
	this.total = 0;
	this.indexLocation = 0;
	this.step = 9
	this.rate = 32;
	this.move;
	this.lastIndex = -1;
	this.UID = scrollBox.count;
	
	this.mouseDown = false;
	this.origTarget = null;
	this.addOffset = 0;
	this.offsetErr = 0;
	
	this.extraData = [];
	for(var i=0;i<this.entries;i++){
		this.extraData[i] = null;
	}
	
	this.allowUp = false;
	this.allowDown = true;
	this.allowClick = true;
	this.letClick = true;
	
	this.innerCaseStyle = "position:absolute;top:0px;width:"+this.viewWidth+"px;";
	this.outerCaseStyle = "position:relative;overflow:hidden;border:solid #000000 1px;width:"
						  +this.viewWidth+"px;height:"+this.viewHeight+"px;";
	
	this.slideBoxClass = "slideBox";
	this.slideClass = "slide";
	this.slideCaptureClass = "slideCapture";
	this.extraCaseStyle = "height:0px;overflow:hidden;width:"+(this.viewWidth-2)+"px;";
	
		this.blank = "../frames/blank.gif";
		this.loader = "../images/loader.gif";
		this.slider = "../frames/slider2.gif";
		
		this.upNorm = "../frames/up.png";
		this.upOver = "../frames/up1.png";
		this.upDown = "../frames/up2.png";
		
		this.downNorm = "../frames/down.png";
		this.downOver = "../frames/down1.png";
		this.downDown = "../frames/down2.png";
		
		this.imgArray = new Array(this.blank,this.loader,this.slider,this.upNorm,this.upOver,
								  this.upDown,this.downNorm,this.downOver,this.downDown);
	
	var inHTML = "<table cellpadding='0' cellspacing='0' width='"+(this.viewWidth+80)+"' height='"+this.viewHeight+"'>"+
		"<tr><td width='"+this.viewWidth+"' height='"+this.viewHeight+"'>"+
			"<div id='scrollFrame"+this.UID+"' name='scrollFrame"+this.UID+"' style='"+this.outerCaseStyle+"'>"+
			"<div id='scrollBoxCase"+this.UID+"' name='scrollBoxCase"+this.UID+"' style='"+this.innerCaseStyle+"'>"+divOBJ.innerHTML+"</div></div>"+
		"</td>"+
		
		"<td valign='top' width='20'>"+
				
			"<div class='"+this.slideBoxClass+"' style='height:"+this.viewHeight+"px;'><div id='slider"+this.UID+
			"' name='slider"+this.UID+"' class='"+this.slideClass+"' style='background:url("+this.slider+
			");background-repeat:no-repeat;'></div><div id='scrollCase"+this.UID+"' name='scrollCase"+this.UID+
			"' onmousedown='"+this.object+".sMouseDown(event)' onmouseup='"+this.object+".sMouseUp()' class='"+this.slideCaptureClass+"' style='height:"+this.viewHeight+"px;'></div></div>"+
				
		"</td>"+
  
		"<td width='60' valign='middle'><a href='javascript:void(0)' onmouseover='"+
			this.object+".swapImage(\"up"+this.UID+"\",\""+this.upOver+"\")' onmousedown='"+
			this.object+".swapImage(\"up"+this.UID+"\",\""+this.upDown+"\"),"+this.object+".scrollUp()' onmouseUp='"+
			this.object+".swapImage(\"up"+this.UID+"\",\""+this.upOver+"\")' onmouseout='"+
			this.object+".swapImage(\"up"+this.UID+"\",\""+this.upNorm+"\")'>"+
			"<img src='"+this.blank+"' name='up"+this.UID+"' id='up"+this.UID+"' border='0' /></a>"+
			
			"<a href='javascript:void(0)' onmouseover='"+
			this.object+".swapImage(\"down"+this.UID+"\",\""+this.downOver+"\")' onmousedown='"+
			this.object+".swapImage(\"down"+this.UID+"\",\""+this.downDown+"\"),"+this.object+".scrollDown()' onmouseup='"+
			this.object+".swapImage(\"down"+this.UID+"\",\""+this.downOver+"\")' onmouseout='"+
			this.object+".swapImage(\"down"+this.UID+"\",\""+this.downNorm+"\")'>"+
			"<img src='"+this.downNorm+"' name='down"+this.UID+"' id='down"+this.UID+"' border='0'/></a>"+
			
			"<FORM><INPUT TYPE='hidden' ID='hidden"+this.UID+"' VALUE='' /></FORM>"+
			
		"</td></tr>"+
		
		"<tr><td>"+
			"<div id='extraCase"+this.UID+"' name='extraCase"+this.UID+"' style='"+this.extraCaseStyle+"'>"+
			"<div style='width:"+this.viewWidth+"px;'>&nbsp;</div>"+
			"</div>"+
		"</td><td>&nbsp;</td><td>&nbsp;</td></tr></table>"+
		/*debugger display*/
			"<div id='debugWrap"+this.UID+"' name='debugWrap"+this.UID+"' style='display:none'><div style='text-align:right;"+
			"border-top:2px solid #00490c;border-bottom:1px solid #00490c;background:#00490c;'><span class='bodytext' style='"+
			"color:#ffffff;float:left;margin-left:5px;'>DEBUG MODE</span><a href='javascript:void(0)' style='color:#ffffff;"+
			"margin-right:10px;' onclick='"+this.object+".clearDebug()'>reset</a></div><div class='bodytext' style='width:"+
			(this.viewWidth+80)+"px;max-width:"+(this.viewWidth+80)+"px;max-height:200px;overflow-y:auto;margin:0;"+
			"background:#eeeeee;' id='debug"+this.UID+"' name='debug"+this.UID+"'>&nbsp;</div></div>";
	
	divOBJ.innerHTML = inHTML;
	
	if(this.debug){
		document.getElementById('debugWrap'+this.UID).style.display = "block";
		this.clearDebug();
	}
	
	this.boxScroller = new genMotion("boxScroller"+this.UID,document.getElementById("scrollBoxCase"+this.UID),"y");
	this.boxScroller.acceleration(-700);
	this.boxScroller.rate(this.rate);
	this.boxScroller.addEval(this.object+".transViewPos(this.currValue())");
	this.boxScroller.addTermEval(this.object+".stopScroll(); "+this.object+".checkArrows()");
	
	
	this.expand = new collapsable("expand"+this.UID,document.getElementById("extraCase"+this.UID),0);
	this.expand.setDefaultColor("#000000");
	this.expand.setDefaultTextColor("#ffffff");
	this.expand.setExpandText("Additional Information Available, Click to View");
	this.expand.setCollapseText("Click to Hide");
	this.expand.hideBox();
	
	this.fixTrans("down"+this.UID);
	
	this.tC = document.getElementById("scrollBoxCase"+this.UID);
	
	return true;
}

	scrollBox.prototype.debugOP = function(output){
		if(this.debug){
			if(typeof this.debugCount == 'undefined'){
				this.debugCount = 0;	
			}
			document.getElementById("debug"+this.UID).innerHTML += (this.debugCount++)+" : "+output+"<br/>";
		}
	}
	
	scrollBox.prototype.clearDebug = function(){
		if(this.debug){
			this.debugCount = 0;
			document.getElementById("debug"+this.UID).innerHTML = "--DEBUG OUTPUT--<br/>";
		}
	}

	scrollBox.prototype.sMouseDown = function(e){
		this.stopScroll();
		var me = this.name;
		this.mouseDown = true;
		if(!e){ e = window.event ; }
		document.onselectstart = function () { return false; };
		document.onmousedown = function () { return false; };
		document.onmousemove = function(e){ if(!e){ e=window.event; } window[me].trackMouse(e); };
		document.onmouseup = function(){ window[me].sMouseUp(); }
		this.trackMouse(e);
	}
	
	scrollBox.prototype.sMouseUp = function(){
		this.mouseDown = false;
		document.onmousemove = null;
		document.onmouseup = null;
		document.onselectstart = null;
		document.onmousedown = null;
		this.origTarget = null;
		this.transViewPos(parseInt(this.tC.style.top.replace("px","")));
	}
	
	scrollBox.prototype.trackMouse = function(e){
		if(!e){ e = window.event; }
		if(this.mouseDown){
			if(this.origTarget == null){
				this.origTarget = e.target != null ? e.target : e.srcElement;
				if(!e.pageY){
					this.offsetErr = this.getOffset(this.origTarget) - (e.clientY + document.documentElement.scrollTop - e.offsetY);
				}
			}
			this.addOffset = this.getOffset(this.origTarget) - this.offsetErr;
			var mouseY = (e.pageY?(e.pageY-this.addOffset-1):e.clientY + document.documentElement.scrollTop - this.addOffset)-8;
			mouseY = mouseY<0?0:mouseY>(this.viewHeight-15)?(this.viewHeight-15):mouseY;
			document.getElementById("slider"+this.UID).style.top = mouseY+"px";
			this.transSliderPos(mouseY);
		}
	}
	
	scrollBox.prototype.transSliderPos = function(slideTop){
		var spacing = Math.floor((this.viewHeight/this.entries)+.5);
		var framePos = Math.ceil(((slideTop+1)*this.entries/this.viewHeight))-1;
		var topVal = (framePos*-this.viewHeight);
		this.tC.style.top = topVal+"px";
		this.indexLocation = framePos;
		this.checkArrows();
		this.setExpand();
	}
	
	scrollBox.prototype.transViewPos = function(currTop){
		var slidePercent = Math.abs(currTop/(this.tCHeight-this.viewHeight));
		var newTop = Math.floor(slidePercent*(this.viewHeight-15));
		newTop = newTop<0?0:newTop>(this.viewHeight-15)?(this.viewHeight-15):newTop;
		document.getElementById("slider"+this.UID).style.top = newTop+"px";
	}
	
	scrollBox.prototype.getOffset = function(Element){
		var addOffset = 0;
		while (Element.offsetParent){
			addOffset += Element.offsetTop;
			Element = Element.offsetParent;
		}
		return addOffset;
	}
	
	scrollBox.prototype.setExpand = function(){
		if(this.extraData[this.indexLocation]!=null){
			this.expand.setInHtml(this.extraData[this.indexLocation]);
			this.expand.showBox();
			if(this.expand.isOpen()){
				this.expand.setOpen();
			}
		}
		else{
			this.expand.hideBox();
			this.expand.setClosed();
		}
	}

	scrollBox.prototype.scrollDown = function(){
		if(this.allowDown && this.allowClick && this.letClick){
			this.stopScroll();
			this.allowClick = false;
			this.arrows("up"+this.UID,true);
			this.indexLocation = Math.abs((this.boxScroller.currValue()-this.viewHeight)/this.viewHeight);
			this.setExpand();
			this.boxScroller.moveByAmount(-200);
		}
	}
	
	scrollBox.prototype.scrollUp = function(){
		if(this.allowUp && this.allowClick && this.letClick){
			this.stopScroll();
			this.allowClick = false;
			this.arrows("down"+this.UID,true);
			this.indexLocation = Math.abs((this.boxScroller.currValue()+this.viewHeight)/this.viewHeight);
			this.setExpand();
			this.boxScroller.moveByAmount(200);
		}
	}
	
	scrollBox.prototype.stopScroll = function(){
		this.boxScroller.terminate();
		this.allowClick = true;
	}
	
	scrollBox.prototype.checkArrows = function(){
		this.debugOP("checking arrows: "+this.indexLocation);
		if(this.indexLocation==0){
			this.arrows("up",false);
			this.arrows("down",true);
		}
		else if(this.indexLocation==this.entries-1){
			this.arrows("up",true);
			this.arrows("down",false);
		}
		else{
			this.arrows("up",true);
			this.arrows("down",true);
		}
	}
	
	scrollBox.prototype.arrows = function(id,mod){
		id = id.replace(this.UID,"");
		if(!mod){
			document.getElementById(id+this.UID).src = this.blank;
		}
		switch(id){
			case "up":
				this.allowUp=mod;
				if(mod){
					document.getElementById(id+this.UID).src = this.upNorm;
				}
				break;
			case "down":
				this.allowDown=mod;
				if(mod){
					document.getElementById(id+this.UID).src = this.downNorm;
				}
				break;
			default:
				break;
		}
		this.fixTrans(id+this.UID);
	}

	scrollBox.prototype.swapImage = function(imgid,newsrc){
		if(imgid!='up'+this.UID && imgid!='down'+this.UID){
			document[imgid].src = newsrc;
		}
		else if(imgid=='up'+this.UID && this.allowUp || imgid==('down'+this.UID) && this.allowDown){
			document[imgid].src = newsrc;
		}
		this.fixTrans(imgid);
	}

	scrollBox.prototype.jumpTo = function(index){
		if(index>=0 && index<this.entries){
			var newTop = -1*this.viewHeight*index;
			this.tC.style.top = newTop+"px";
			this.transViewPos(newTop);
			this.indexLocation = index;
			this.checkArrows();
			this.setExpand();
		}
	}
	
	scrollBox.prototype.fixTrans = function(imgId){
		var ie6 = (window.external && typeof window.XMLHttpRequest == "undefined");
		var imgElm = document.getElementById(imgId);
		var imgSrc = imgElm.src;
		if(/\.png$/.test( imgSrc.toLowerCase())&&ie6){
			imgElm.src = this.blank;
			imgElm.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+imgSrc+"',sizingMethod='scale')";
		}
		else if(ie6){
			imgElm.runtimeStyle.filter = "";
		}
	}

	scrollBox.prototype.addExtraInfo = function(index, inHtml){
		if(index<=this.entries && index>0){
			index--;
			this.extraData[index] = inHtml;
			this.setExpand();
		}
	}

	scrollBox.prototype.preloadImages = function(){
		var toLoad = new Array();
		for(var i=0;i<this.imgArray.length;i++){
			toLoad[i] = new Image();
			toLoad[i].src = this.imgArray[i];
		}
	}

	scrollBox.prototype.getUID = function(){
		return this.UID;
	}
	
	scrollBox.prototype.getTotalHeight = function(){
		return this.tCHeight;
	}
	
	scrollBox.prototype.getViewHeight = function(){
		return this.viewHeight;
	}
	
	scrollBox.prototype.getName = function(){
		return this.name;
	}
	
	scrollBox.prototype.setRate = function(newRate){
		this.step = newRate;
	}
	
	scrollBox.prototype.setNewInterval = function(newInterval){
		this.rate = newInterval;
	}

	scrollBox.prototype.getArgs = function(){
		try{
			var args = document.location.href.split("?")[1].split("&");
			for(var i=0;i<args.length;i++){
				var line = args[i].split("=");
				if(line[0]==this.name){
					line = line[1].split('.');
					var index = parseInt(line[0])-1;
					this.jumpTo(index);
					if(line.length>1){
						var isOpen = line[1];
						if(isOpen == "true" && this.extraData[index]!=null){
							this.expand.clicked();
						}
					}
				}
			}
		}
		catch(err){
		}
	}