/**
 * Loads scripts into a page, calling events if an error occurs or when all scripts have loaded
 *
 * @title		Script Loader
 * @author		Colin Nolan
 * @version		v0.9.4
 * @created		08/04/11 (v0.5.0)
 * @updated		11/08/11 (v0.9.4), 08/08/11 (v0.9.3), 26/07/11 (v0.9.0)
 * @requires	LoadTask
 *				JavascriptLoader
 *
 * @param	{int} customRetries	(Optional) Number of times to retry loading a script before it is considered to have failed
 * @param	{int} customTimeout	(Optional) Maximum number of scripts that can be loaded at one time
 * @param	{int} customMaxParallelLoads	(Optional) Maximum number of scripts that can be loaded at one time
 */
var ScriptLoader=function(customRetries,customTimeout,customMaxParallelLoads){var STANDARD_MAX_PARALLEL_LOADS=10;var retries;var timeout;var maxParallelLoads;var loadQueueJS=new Array();var loadingJS=new Array();function construct(){timeout=customTimeout||null;retries=customRetries||null;maxParallelLoads=customMaxParallelLoads||STANDARD_MAX_PARALLEL_LOADS};this.loadJS=function(src,onload,onerror){loadQueueJS.push(new LoadTask("javascript",src,function(task){removeFromArray(task,loadingJS);if(onload){onload(task.getSrc())}loadNext()},function(task){removeFromArray(task,loadingJS);if(onerror){onerror(task.getSrc())}loadNext()},retries,timeout));loadNext()};this.loadMultipleJS=function(scripts,onAllLoad,onerror){onAllLoad=onAllLoad||function(){};onerror=onerror||function(){};if(scripts.length==0){onAllLoad()}else{var loaded=0;for(var i=0;i<scripts.length;i++){this.loadJS(scripts[i],function(){loaded++;if(loaded==scripts.length){onAllLoad()}},function(src){onerror(src)})}}};var loadNext=function(){if(loadingJS.length<maxParallelLoads&&loadQueueJS.length!=0){var task=loadQueueJS.splice(0,1)[0];loadingJS.push(task);task.execute()}};var removeFromArray=function(el,array){var i=0;while(i<array.length){if(array[i]==el){array.splice(i,1);i=array.length}i++}};construct()};
var LoadTask=function(type,src,onload,onerror,maxRetries,timeout){var STANDARD_RETRIES=1;var that=this;var loader;var retryTime=0;(function(){maxRetries=maxRetries||STANDARD_RETRIES})();this.getSrc=function(){return src};this.execute=function(){if(type=="javascript"){loader=new JavascriptLoader(src,function(){onload(that)},onerrorHandler,timeout)}};this.removeLoadElement=function(){if(loader){loader.removeScriptElement()}};var onerrorHandler=function(){if(retryTime<maxRetries){retryTime++;that.execute()}else{onerror(that)}}};
var JavascriptLoader=function(src,onload,onerror,customTimeout){var STANDARD_TIMEOUT=3000;var that=this;var timeout;var loadElement;var loadTimeout;var construct=function(){onload=onload||function(){};onerror=onerror||function(){};timeout=customTimeout||STANDARD_TIMEOUT;loadElement=createDOMElement();addToDOM(loadElement);startTimeout()};this.removeLoadElement=function(){removeFromDOM(loadElement)};var createDOMElement=function(){var onScriptLoad=function(){stopTimeout();onload()};var onScriptError=function(){stopTimeout();that.removeLoadElement();onerror()};var el=window.document.createElement("script");el.type="text/javascript";el.src=src;el.onerror=onScriptError;if(el.readyState){el.onreadystatechange=function(){if(el.readyState=="loaded"||el.readyState=="complete"){el.onreadystatechange=null;onScriptLoad()}}}else{el.onload=onScriptLoad}return el};var addToDOM=function(el){document.getElementsByTagName("head")[0].appendChild(el)};var removeFromDOM=function(el){try{el.onload=function(){};el.onerror=function(){};el.src="about:blank";el.parentNode.removeChild(el)}catch(e){throw new Error("ScriptLoader->JavascriptLoader: Cannot remove script element from the page:\n"+e);}};var startTimeout=function(){loadTimeout=window.setTimeout(function(){that.removeLoadElement();onerror()},timeout)};var stopTimeout=function(){window.clearTimeout(loadTimeout)};construct()};
