/*********** Article Navigation App Javascript File ****************
 Author: Carl Pryke
 Date: 11/05/2011
 Version: 1.0 
 Description: This defines the functionality of the article navigation application,
 allows for users to scroll through a list of article images and get further information
 on in a window to the right. Will automatically scroll through articles on a timer if
 necessary.
 
 Technical Notes: There are major issues that occur with using setTimeout() with object functions,
 it does not seem capable of handling it, hence the half-scripting, half-object-oriented code.
 
 Development Notes:
 
 1 - More should be done to tweak the timing of events for various browsers. We could have a function
 to detect browser type and re-assign values to variables that affect the speed of events.
 
 2 - Parameters should be passed into the load function, in a way that would make updating easy.
 *************************************************************/ 
 
 /*************** Scripting Variables *************************/
var scrollTimer;
var jumpTimer;
var scrollTime = 10;
var fadeTime = 10;
var jumpTime = 1;
var jumpRate = -9;
var fadeValue = 10;
var autoTime = 20000;
var fadeTimer;
var targetId;
var articleRequest = false;
var articleNav;
var autoTimer;


/*************** Scripting Functions *************************/
//autoTimer = setTimeout("nextArticle()", autoTime);

/**
Makes a request from the server to get the appropriate XML file for the article navigation application
Param: File Path - XML file path from the hosting XHTML file's location.
**/
function requestArticleData(str){
	if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
  		articleRequest = new XMLHttpRequest();
  	}
  	else{// code for IE6, IE5
      	articleRequest = new ActiveXObject("Microsoft.XMLHTTP");
	}
	articleRequest.open("GET", str, true);
	articleRequest.onreadystatechange = getArticleData; // Loads the resultant XML file into Article Navigation Object
	articleRequest.send(null);
}

/**
Called upon successfull retrieval of the article data from the server. Will create a new article Navigation object.
**/
function getArticleData(){
	if(articleRequest.readyState == 4 && articleRequest.status==200){
		articleNav = new articleNavigation(articleRequest.responseXML); // Specify the XML file to use here.*/
        loadArticleNavigation();
	}
}

/**
Load function, content cannot be loaded until browser loads HTML document. This is called in the body's onload 
event listener and makes sure that content is loaded in IE8 and earlier.
**/
function loadArticleNavigation(){
	articleNav.loadThumbs();
}

/**
Gets the thumb panel to scroll upward when the mouse if over the upwards arrow.
**/
function setScrollUp(){
	if(!articleNav.scrollUp()){
		scrollTimer = setTimeout("setScrollUp()", scrollTime);
	}
	else{
		stopScrollUp();	
	}
}

/**
Stops the scrolling of the thumb panel when the mouse exits an arrow control
**/
function stopScroll(){
	clearTimeout(scrollTimer);
}

/**
Gets the thumb panel to scroll downward when the mouse if over the upwards arrow.
**/
function setScrollDown(){
	if(!articleNav.scrollDown()){
		scrollTimer = setTimeout("setScrollDown()", scrollTime);
	}
	else{
		stopScrollDown();	
	}
}

/**
When the mouse is clicked, a jump mechanism takes place to simulate the effects
of a touchscreen scroller. This is mainly so the user can navigate through what could
potentially be a lot of articles quicker.
**/
function jumpScroller(){
	if(jumpRate < 50){
		articleNav.scrollRate = 50 - Math.sqrt(jumpRate * jumpRate);
		if(jumpRate < -20){
			jumpRate += 20;
		}
		else{
			jumpRate += 1;	
		}
		jumpTimer = setTimeout("jumpScroller()", jumpTime);
	}
	else{
		jumpRate = -50;
		clearTimeout(jumpTimer);
	}
}


/**
Begins the switching of an article based on user input. This function is embedded into the
onclick listener of each thumb and will send the id of the div which can be used to identify which
article to switch to.
Param: Id - the id of the div which contains the article index.
**/
function articleSwitch(id){
	    articleNav.switchCurrentArticle(id);
	    targetId = id;
	    fadeOut();
	    resetTimer();
    
}

/**
Fades out the current article, adds a nice animated feel to whenever an article is changed.
**/
function fadeOut(){
	if(fadeValue > -1){
		articleNav.fadeArticleImage(fadeValue);
		fadeValue -= 1;
		fadeTimer = setTimeout("fadeOut()", fadeTime);
	}
	else{
		clearTimeout(fadeTimer);
		articleNav.getArticle(targetId);
		fadeValue = 0;
		fadeIn();
	}
}

/**
Fades the next article into the page.
**/
function fadeIn(){
	if(fadeValue <= 10){	
		articleNav.fadeArticleImage(fadeValue);
		fadeValue += 1;
		fadeTimer = setTimeout("fadeIn()", fadeTime);
	}
	else{
		clearTimeout(fadeTimer);
		fadeValue = 10;
	}
}

/**
Used for automatic scrolling. If the user does not interact for a while then the
navigation app automatically updates the current article being displayed, scrolling
down the page.
**/
function nextArticle(){
	targetId = articleNav.getNextArticle();
	resetTimer();
	fadeOut();
	articleNav.switchCurrentArticle(targetId);
}

/**
Used to set the timer back to the beginning. This is used whenever the article is changed
either by user input or by the automatic scrolling facility itself.
**/
function resetTimer(){
	clearTimeout(autoTimer);
	//autoTimer = setTimeout("nextArticle()", autoTime);
}
 
/****************** Article Navigation App Class Definition ******************/
function articleNavigation(XMLDocument){
	/********************** Variable / Constant declaration ******************/
 	this.scrollContentHeight; // monitors the height of the scroll content panel to stop scrolling.
 	this.categoryTarget = "articleCategory";
 	this.thumbTarget = "scrollContent"; // the target div id to render thumbs to.
	this.infoTarget = "infoPanel";
	this.imageTarget = "articleImage"; // the target div id to render images to.
	this.topIndex = 0; // The top margin of the scroll content div.
	this.scrollRate = 1; // the number of pixels the scroller will move each update.
	this.currentArticle = "scroller0"; // the current article being displayed. Default is the first in the array.
	this.XMLDocument = XMLDocument; // the data file in XML format
	this.articleNum = 0; // Used to know when the auto-scroller should go back to the top of the article list.
    this.video = false;

	/********************** function declaration *****************************/
	this.loadThumbs = loadThumbs;
	this.getArticle = getArticle;
	this.scrollDown = scrollDown;
	this.scrollUp = scrollUp;
	this.switchCurrentArticle = switchCurrentArticle;
	this.fadeArticleImage = fadeArticleImage;
	this.getNextArticle = getNextArticle;
	this.setArticle = setArticle;
    this.isOnVideo = isOnVideo;
	/********************** function definitions *****************************/
	
	/**
	Reads in all the data from the XML document and places into the document. Will produce a list of
	thumb divs to embed in the HTML page so that the articles can be navigated dynamically.
	**/
	function loadThumbs(){

		var HTMLString = "";
		var articles = XMLDocument.documentElement.getElementsByTagName("article");
		this.scrollContentHeight = (articles.length-1) * 90;
		for(var i=0; i < articles.length; i++){
		   var image = articles[i].getElementsByTagName("image");
		   HTMLString += "<div class=\"scrollThumb\" id=\"scroller" + i + "\" style=\"background-image: url(images/thumbs/";
		   HTMLString += image[0].firstChild.nodeValue;
		   HTMLString += ")\" ";
		   HTMLString += "onclick=\"articleSwitch(this.id)\"></div>";
		}
		document.getElementById(this.thumbTarget).style.height = this.scrollContentHeight + "px";
		document.getElementById(this.thumbTarget).style.clip = "rect(0px, 200px, 340px, 0px)";
		document.getElementById(this.thumbTarget).innerHTML = HTMLString;
		document.getElementById("scroller0").className = "scrollThumbFixed";
		this.articleNum = articles.length;
		this.getArticle("scroller0");
	}
	
	/**
	Prints an article to the page upon request, target article argument is the id of the clicked thumb,
	which contains at the end of the string the article index.
	**/
	function getArticle(target){
		var id = parseInt(target.substr(8));
		var articles = XMLDocument.documentElement.getElementsByTagName("article");
		var image = articles[id].getElementsByTagName("image")[0].firstChild.nodeValue;
        var video = articles[id].getElementsByTagName("video")[0].firstChild.nodeValue;
        var url = articles[id].getElementsByTagName("url")[0].firstChild.nodeValue;
        var HTMLString = "";
        if(video == "none"){
            document.getElementById(this.imageTarget).style.backgroundImage = "url(images/" + image + ")";
            document.getElementById(this.imageTarget).innerHTML = "";
            this.video = false;
        }
        else{
            HTMLString = "<object class=\"youTubePlayer\" id=\"hello\">";
            HTMLString += "<param name=\"movie\" value=\"http://www.youtube.com/v/" + video + "?version=3\">";
            HTMLString += "<param name=\"allowFullScreen\" value=\"true\">";
            HTMLString += "<param name=\"allowFullScreen\" value=\"true\">";
            HTMLString += "<param name=\"allowScriptAccess\" value=\"always\">";
            HTMLString += "<param name=\"wmode\" value=\"transparent\" />";
            HTMLString += "<embed src=\"http://www.youtube.com/v/" + video + "?version=3\" wmode=\"transparent\" type=\"application/x-shockwave-flash\" allowfullscreen=\"true\" allowScriptAccess=\"always\" width=\"595\" height=\"398\"></object>";
            document.getElementById(this.imageTarget).style.backgroundImage = "";
            document.getElementById(this.imageTarget).innerHTML = HTMLString;
            this.video = true;
        }
	}
 
 	/**
	Moves the clip down along the scroll content pane, while moving the top margin up at the same rate. Goes downwards
	**/
 	function scrollDown(){
		var cannotMove = false;
		if(this.topIndex + this.scrollRate + 270 < this.scrollContentHeight){
			this.topIndex += this.scrollRate;
			document.getElementById(this.thumbTarget).style.clip = "rect(" + this.topIndex + "px, 200px, " + (this.topIndex + 340) + "px, 0px)";
			document.getElementById(this.thumbTarget).style.marginTop = (30 - this.topIndex) + "px";
		}
		else{
			cannotMove = true;
		}
		return cannotMove;
 	}
 
  	/**
	Moves the clip down along the scroll content pane, while moving the top margin up at the same rate. Goes Upwards
	**/
	function scrollUp(){
		var cannotMove = false;
		if(this.topIndex - this.scrollRate > 0){
	 		this.topIndex -= this.scrollRate;
			document.getElementById(this.thumbTarget).style.clip = "rect(" + this.topIndex + "px, 200px, " + (this.topIndex + 340) + "px, 0px)";
			document.getElementById(this.thumbTarget).style.marginTop = (30 - this.topIndex) + "px";
		}
		else{
			cannotMove = true;
		}
		return cannotMove;
 	}
	
	/**
	Changes the current article and marks this by highlighting the thumb of the article.
	**/
	function switchCurrentArticle(target){
	    document.getElementById(this.currentArticle).className = "scrollThumb";
	    document.getElementById(target).className = "scrollThumbFixed";
	    this.currentArticle = target;
	}
	
	/**
	Changes the opacity of the image.
	**/
	function fadeArticleImage(value){
		document.getElementById(this.infoTarget).style.opacity = (value / 10); // Firefox & Rest
		document.getElementById(this.infoTarget).style.filter = "alpha(opacity=" + (value * 10) + ")"; // IE9 and predecessors
	}
	
	/**
	Returns the next article in the article array for the auto-scroller.
	**/
	function getNextArticle(){
		var id = parseInt(this.currentArticle.substr(8));
		var next = "";
		if((id + 1) < this.articleNum){
		   next = "scroller" + (id + 1);
		}
		else{
		   next = "scroller0";	
		}
		return next;
	}
	
	/**
	Sets the current article of the Navigation App.
	**/
	function setArticle(t){
		this.currentArticle = t;	
	}
    
    function isOnVideo(){
        return this.video;
    }
}


