/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
(function () {
if (typeof (WebCom) == 'undefined') {
WebCom = {};
}
/*private class*/ function Resource (/*RC_TYPE*/ type, /*ResourceLocator*/ locator, /*Object*/ _statusHandler) {
this.type = type;
this.locator = locator;
var statusHandler = _statusHandler;
this.getURL = function () {
return this.locator.getURL();
};
this.getStatusHandler = function() {
return statusHandler;
}
};
/*private class*/ function ResourceLocator (baseURL, fileName) {
this.baseURL = baseURL;
this.fileName = fileName;
this.getBaseURL = function() {
return this.baseURL;
};
this.getURL = function () {
if (this.fileName != "") {
return this.baseURL + "/" + this.fileName;
} else {
return this.baseURL;
}
};
};
/*private class*/ function LibraryWrapper(_libHandle) {
var libHandle = _libHandle;
this.getResourceURL = function (/*String*/ resourcePath) {
return libHandle.getResourceURL(resourcePath);
};
this.loadResource = function (/*String*/ resourcePath, /*String*/ resourceType) {
return libHandle.getResourceURL(resourcePath, resourceType);
};
};
/*public class*/ function Library(/* [String runtimeName], String packageName, String version, String[] scripts, String[] styles*/) {
var args = Array.prototype.slice.call(arguments);
if (args.length == 5) {
this.runtimeName = args.shift();
WebCom.ResourceLoader.makeNameSpace(this.runtimeName);
//var libWrapper = new LibraryWrapper(this);
//var constructorName = parts.join("_");
//eval(constructorName + ".prototype = libWrapper;"); //
//eval(this.runtimeName + "= new " + constructorName + "();");
}
this.packageName = args[0];
this.version = args[1];
this.scripts = args[2];
this.styles = args[3];
this.getRuntimeName = function () {
return this.runtimeName;
}
this.getPackageName = function () {
return this.packageName;
};
this.getVersion = function () {
return this.version;
};
this.getScripts = function () {
return this.scripts;
};
this.getStyles = function () {
return this.styles;
};
this.getResourceURL = function (/*String*/ resourcePath) {
return WebCom.ResourceLoader.getResourceURL(resourcePath, this);
};
//TODO: review if we need to expose the defer flag as well
this.loadResource = function (/*String*/ resourcePath, /*Object*/ statusHandler, /*String*/ _resourceType) {
if (resourcePath == null) {
throw new Error("resource path cannot be empty");
}
var resourceType = _resourceType;
if (resourceType != null) {
if (!WebCom.ResourceLoader.isResourceSupported(resourceType)) {
throw new Error("Unsuported resource type " + resourceType );
}
} else {
resourceType = WebCom.ResourceLoader.getResourceType(resourcePath);
}
//load it now. no deferral!
WebCom.ResourceLoader._loadResource(this.packageName, this.version, resourceType, null, resourcePath, false, statusHandler);
};
};
function WebCom_ResourceLoader() {
var counter = 0;
var RC_TYPE = { SCRIPT : "SCRIPT",
STYLE : "STYLE"
};
this.RC_TYPE = RC_TYPE;
var C_LATEST_VERSION_IDENTIFIER = "latest";
var SHARED_URL = "http://assets.webservices.websitepros.com";
var SHARED_SECURE_URL = "https://secure.websitepros.com/assets.webservices.websitepros.com";
var versionsMixEnabled = false;
var isShared = true;
var isSecure = false;
var resourceCache = {};
var librariesRegistry = {};
var resourcesQueue = [];
var isDocumentClosed = false;
var userAgent = navigator.userAgent.toLowerCase();
var browser = {msie: /msie/.test( userAgent ) && !/opera/.test( userAgent )};
var privateURI = "";
var queueInProgress = false;
//holds the default extension per resource type
var rcExtensionMap = {};
rcExtensionMap[RC_TYPE.SCRIPT] = "js";
rcExtensionMap[RC_TYPE.STYLE] = "css";
//holds the starting URI per resource type
var rcBaseURIMap = {};
rcBaseURIMap[RC_TYPE.SCRIPT] = "javascript";
/**
* Builds the locator for given named versioned resource. If _isShared
* is not set then the loader's isShared member value is used. If shared the
* resource will be relative to a shared URL. Otherwise it will be be relative
* to the host page this loader was referenced from. Locator rules
*
* 1. Folders are per Java package convention
* 2. Top package is appended per resource type (ie js/, css/)
* 3. File name is built from last dot occurence till the end
*
* Examples:
*
* "com.jquery", null , false -> js/com/jquery/latest/jquery.js
* "com.web.coolapp", null , false -> js/com/web/coolapp/coolapp.js
*
* @param name per Java package convention
* @param version if null will default to 'latest' when resolving the URI
* @param type
* @param _isShared if true a shared URL will be used. otherwise the URL will
* be relative to page this loader resides on
*/
/*private ResourceLocator*/ function getResourceLocator(/*string*/name, /*string*/ version, /*RC_TYPE*/ type, /*boolean*/ _isShared) {
if (name == "") {
throw new Error("Resource name cannot be empty!");
}
if (typeof _isShared == 'undefined') {
_isShared = isShared;
}
var url = "";
if (_isShared) {
url = isSecure ? SHARED_SECURE_URL : SHARED_URL;
} else {
if (privateURI != "") {
var location = window.location;
url = location.protocol + "//" + location.host + ":" + location.port + "/" + privateURI;
} else {
url = window.location.toString();
url = url.substring(0, url.lastIndexOf("/"));
}
}
var baseUri = "";
var baseName = "";
if (name.indexOf(".") != -1 ) {
baseUri = name.replace(/\./g, '/');
var parts = name.split(".");
baseName = parts[parts.length - 1];
} else {
baseUri = baseName = name;
}
baseUri = url + "/" + rcBaseURIMap[type] + "/" + baseUri + "/" + version;
return new ResourceLocator(baseUri, baseName + "." + rcExtensionMap[type]);
};
function isResourceSupported(resourceType) {
return resourceType !=null && resourceType.match(/^js|css$/) != null;
};
function getResourceType (/*String*/ resourcePath) {
if (resourcePath == null) {
throw new Error("resource path cannot be empty");
}
var extension;
if (extension = resourcePath.match(/js|css$/) != null) {
return (extension[0] == "js") ? RC_TYPE.SCRIPT : RC_TYPE.STYLE;
} else {
throw new Error("Unsuported resource type " + resourcePath );
}
};
function loadResource(/*string*/ resourcePath) {
var resource = new Resource(RC_TYPE.SCRIPT, new ResourceLocator(this.getResourceURL(resourcePath)));
if (isDocumentClosed) {
injectResourceIntoDOM_createElement(resource);
} else {
resourcesQueue.push( resource );
}
};
/**
* Loads the resource identified by name
, version
* and relativePath into current DOM. If deferred is true the
* loading will occur at a later time when {@link #flushResourcesQueue} is
* invoked.
*
* @param name per Java package convention
* @param version if null will default to 'latest' when resolving the URI
* @param type
* @param _isShared if true a shared URL will be used. otherwise the URL will
* be relative to page this loader resides on
* @param relativePath relative to baseURL of name
/version
* @param deferred whether to inject it now into DOM or deferr it for later
*
* @throws Error if mixing is currently disabled and an attempt to mix
* different version of a library is detected
*/
/*private*/ function _loadResource (/*string*/name, /*string*/ version, /*RC_TYPE*/ type, /*boolean*/ _isShared,
/*string*/ relativePath, /*boolean*/ deferred, /*Object*/ statusHandler) {
if (name == "") {
return; //nothing to do really w/ an empty component
}
if (version == null || version == "") {
version = C_LATEST_VERSION_IDENTIFIER; //empty version we can handle
}
var libraryKey = name + "_" + version;
var resourceKey = (relativePath != null && relativePath.length > 0) ? libraryKey + "_" + relativePath : libraryKey;
if (resourceCache[libraryKey] != null) {
if (!versionsMixEnabled && librariesRegistry[name] != version) {
throw new Error("Version " + librariesRegistry[name] + " of " + name +
" is already loaded. Cannot load " + version + " at the same time!" );
}
if (resourceCache[resourceKey] == null) {
resourceCache[resourceKey] = new ResourceLocator(resourceCache[libraryKey].getBaseURL(), relativePath);
} else {
return;
}
} else {
if (libraryKey != resourceKey) {
throw new Error("A dependent resource cannot be loaded w/o loading its parent library");
}
librariesRegistry[name] = version;
resourceCache[libraryKey] = getResourceLocator(name, version, type, _isShared);
}
if (deferred) {
if (isDocumentClosed) {
throw new Error("Cannot defer after the document is closed");
}
resourcesQueue.push( new Resource(type, resourceCache[resourceKey] ) );
} else {
injectResourceIntoDOM( new Resource(type, resourceCache[resourceKey], statusHandler ) );
}
};
function getResourceURL(/*string*/ resourcePath, /*Library*/ library) {
if (library != null) {
var libraryKey = library.getPackageName() + "_" + library.getVersion();
if (resourceCache[libraryKey] != null) {
return new ResourceLocator(resourceCache[libraryKey].getBaseURL(), resourcePath).getURL();
} else {
throw new Error("Load the library first then ask for a dependent resource!");
}
} else {
return isSecure ? SHARED_SECURE_URL : SHARED_URL + "/" + resourcePath;
}
};
/**
* Injects the resource
into DOM by generating the appropriate
* markup. Currently SCRIPT and STYLE elements are supported.
*
* @param resource
*/
/*private*/ function injectResourceIntoDOM(/*Resource*/ resource) {
(isDocumentClosed) ? injectResourceIntoDOM_createElement(resource) : injectResourceIntoDOM_documentWrite(resource);
};
/*private*/function injectResourceIntoDOM_documentWrite(/*Resource*/ resource) {
if (resource.type == RC_TYPE.SCRIPT) {
document.write("