(function(){window.ensure = function( data, callback, scope )
{if( typeof jQuery == "undefined" && typeof Sys == "undefined" && typeof Prototype == "undefined" )
return alert("jQuery, Microsoft ASP.NET AJAX or Prototype library not found. One must be present for ensure to work");if( typeof data.test != "undefined" )
{var test = function() {return data.test };if( typeof data.test == "string" )
{test = function() 
{return !(eval( "typeof " + data.test ) == "undefined" 
&& document.getElementById(data.test) == null);}
}    
else if( typeof data.test == "function" )      
{test = data.test;}
if( test() === false || typeof test() == "undefined" || test() == null ) 
new ensureExecutor(data, callback, scope);else
callback();}
else
{new ensureExecutor(data, callback, scope);}
}
window.ensureExecutor = function(data, callback, scope)
{this.data = this.clone(data);this.callback = (typeof scope == "undefined" || null == scope ? callback : this.delegate(callback, scope));this.loadStack = [];if( data.js && data.js.constructor != Array ) this.data.js = [data.js];if( data.html && data.html.constructor != Array ) this.data.html = [data.html];if( data.css && data.css.constructor != Array ) this.data.css = [data.css];if( typeof data.js == "undefined" ) this.data.js = [];if( typeof data.html == "undefined" ) this.data.html = [];if( typeof data.css == "undefined" ) this.data.css = [];this.init();this.load();}
window.ensureExecutor.prototype = {init : function()
{if( typeof jQuery != "undefined" )
{this.getJS = HttpLibrary.loadJavascript_jQuery;this.httpGet = HttpLibrary.httpGet_jQuery;}
else if( typeof Prototype != "undefined" )
{this.getJS = HttpLibrary.loadJavascript_Prototype;this.httpGet = HttpLibrary.httpGet_Prototype;}
else if( typeof Sys != "undefined" )
{this.getJS = HttpLibrary.loadJavascript_MSAJAX;this.httpGet = HttpLibrary.httpGet_MSAJAX;}
else
{throw "jQuery, Prototype or MS AJAX framework not found";}        
},
getJS : function(data)
{},
httpGet : function(url, callback)
{},    
load : function()
{this.loadJavascripts( this.delegate( function() {this.loadCSS( this.delegate( function() {this.loadHtml( this.delegate( function() {this.callback() 
} ) ) 
} ) ) 
} ) );},
loadJavascripts : function(complete)
{var scriptsToLoad = this.data.js.length;if( 0 === scriptsToLoad ) return complete();this.forEach(this.data.js, function(href)
{if( HttpLibrary.isUrlLoaded(href) || this.isTagLoaded('script', 'src', href) )
{scriptsToLoad --;}
else
{this.getJS({url:        href, 
success:    this.delegate(function(content)
{scriptsToLoad --;HttpLibrary.registerUrl(href);}), 
error:      this.delegate(function(msg)
{scriptsToLoad --;if(typeof this.data.error == "function") this.data.error(href, msg);})
});}            
});this.until({test:       function() {return scriptsToLoad === 0;}, 
delay:      50,
callback:   this.delegate(function()
{complete();})
});},    
loadCSS : function(complete)
{if( 0 === this.data.css.length ) return complete();var head = HttpLibrary.getHead();this.forEach(this.data.css, function(href)
{if( HttpLibrary.isUrlLoaded(href) || this.isTagLoaded('link', 'href', href) )
{}
else
{var self = this;try
{(function(href, head)
{var link = document.createElement('link');link.setAttribute("href", href);link.setAttribute("rel", "Stylesheet");link.setAttribute("type", "text/css");head.appendChild(link);HttpLibrary.registerUrl(href);}).apply(window, [href, head]);}
catch(e)
{if(typeof self.data.error == "function") self.data.error(href, e.message);}                
}
});complete();},
loadHtml : function(complete)
{var htmlToDownload = this.data.html.length;if( 0 === htmlToDownload ) return complete();this.forEach(this.data.html, function(href)
{if( HttpLibrary.isUrlLoaded(href) )
{htmlToDownload --;}
else
{this.httpGet({url:        href, 
success:    this.delegate(function(content)
{htmlToDownload --;HttpLibrary.registerUrl(href);var parent = (this.data.parent || document.body.appendChild(document.createElement("div")));if( typeof parent == "string" ) parent = document.getElementById(parent);parent.innerHTML = content;}), 
error:      this.delegate(function(msg)
{htmlToDownload --;if(typeof this.data.error == "function") this.data.error(href, msg);})
});}            
});this.until({test:       function() {return htmlToDownload === 0;}, 
delay:      50,
callback:   this.delegate(function()
{complete();})
});},
clone : function(obj)
{var cloned = {};for( var p in obj )
{var x = obj[p];if( typeof x == "object" )
{if( x.constructor == Array )
{var a = [];for( var i = 0;i < x.length;i ++ ) a.push(x[i]);cloned[p] = a;}
else
{cloned[p] = this.clone(x);}
}
else
cloned[p] = x;}
return cloned;},
forEach : function(arr, callback)
{var self = this;for( var i = 0;i < arr.length;i ++ )
callback.apply(self, [arr[i]]);},
delegate : function( func, obj )
{var context = obj || this;return function() {func.apply(context, arguments);}
},
until : function(o /* o = {test: function(){...}, delay:100, callback: function(){...} } */)
{if( o.test() === true ) o.callback();else window.setTimeout( this.delegate( function() {this.until(o);} ), o.delay || 50);},
isTagLoaded : function(tagName, attName, value)
{var tag = document.createElement(tagName);tag[attName] = value;var tagFound = false;var tags = document.getElementsByTagName(tagName);this.forEach(tags, function(t) 
{if( tag[attName] === t[attName] ) {tagFound = true;return false } 
});return tagFound;}
}
var userAgent = navigator.userAgent.toLowerCase();var HttpLibrary = {browser : {version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
safari: /webkit/.test( userAgent ),
opera: /opera/.test( userAgent ),
msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
},
loadedUrls : {},
isUrlLoaded : function(url)
{return HttpLibrary.loadedUrls[url] === true;},
unregisterUrl : function(url)
{HttpLibrary.loadedUrls[url] = false;},
registerUrl : function(url)
{HttpLibrary.loadedUrls[url] = true;},
createScriptTag : function(url, success, error)
{var scriptTag = document.createElement("script");scriptTag.setAttribute("type", "text/javascript");scriptTag.setAttribute("src", url);scriptTag.onload = scriptTag.onreadystatechange = function()
{if ( (!this.readyState || 
this.readyState == "loaded" || this.readyState == "complete") ) {success();}
};scriptTag.onerror = function()
{error(data.url + " failed to load");};var head = HttpLibrary.getHead();head.appendChild(scriptTag);},
getHead : function()
{return document.getElementsByTagName("head")[0] || document.documentElement
},
globalEval : function(data)
{var script = document.createElement("script");script.type = "text/javascript";if ( HttpLibrary.browser.msie )
script.text = data;else
script.appendChild( document.createTextNode( data ) );var head = HttpLibrary.getHead();head.appendChild( script );},
loadJavascript_jQuery : function(data)
{if( HttpLibrary.browser.safari )
{return jQuery.ajax({type:       "GET",
url:        data.url,
data:       null,
success:    function(content)
{HttpLibrary.globalEval(content);data.success();},
error:      function(xml, status, e) 
{if( xml && xml.responseText )
data.error(xml.responseText);else
data.error(url +'\n' + e.message);},
dataType: "html"
});}
else
{HttpLibrary.createScriptTag(data.url, data.success, data.error);}
},    
loadJavascript_MSAJAX : function(data)
{if( HttpLibrary.browser.safari )
{var params = 
{url: data.url, 
success: function(content)
{HttpLibrary.globalEval(content);data.success(content);},
error : data.error 
};HttpLibrary.httpGet_MSAJAX(params);}
else
{HttpLibrary.createScriptTag(data.url, data.success, data.error);}
},
loadJavascript_Prototype : function(data)
{if( HttpLibrary.browser.safari )
{var params = 
{url: data.url, 
success: function(content)
{HttpLibrary.globalEval(content);data.success(content);},
error : data.error 
};HttpLibrary.httpGet_Prototype(params);}
else
{HttpLibrary.createScriptTag(data.url, data.success, data.error);}        
},
httpGet_jQuery : function(data)
{return jQuery.ajax({type:       "GET",
url:        data.url,
data:       null,
success:    data.success,
error:      function(xml, status, e) 
{if( xml && xml.responseText )
data.error(xml.responseText);else
data.error("Error occured while loading: " + url +'\n' + e.message);},
dataType: data.type || "html"
});},
httpGet_MSAJAX : function(data)
{var _wRequest =  new Sys.Net.WebRequest();_wRequest.set_url(data.url);_wRequest.set_httpVerb("GET");_wRequest.add_completed(function (result) 
{var errorMsg = "Failed to load:" + data.url;if (result.get_timedOut()) {errorMsg = "Timed out";}
if (result.get_aborted()) {errorMsg = "Aborted";}
if (result.get_responseAvailable()) data.success( result.get_responseData() );else data.error( errorMsg );});var executor = new Sys.Net.XMLHttpExecutor();_wRequest.set_executor(executor);executor.executeRequest();},
httpGet_Prototype : function(data)
{new Ajax.Request(data.url, {method:     'get',
evalJS:     false,  
onSuccess:  function(transport, json)
{data.success(transport.responseText || "");},
onFailure : data.error
});}
};})();

