/** * The main namespace. **/ var Vn = { Config: {} ,includes: {} ,cssIncludes: {} ,xmlIncludes: {} ,tmpIncludes: [] ,tmpDefine: null ,customTags: {} ,head: document.getElementsByTagName ('head')[0] ,isMobileCached: null /** * Includes a new CSS stylesheet in the current document, if the stylesheet * is already included, does nothing. * * @param {string} fileName The stylesheet file name **/ ,includeCss: function (fileName) { var cssData = this.cssIncludes[fileName]; if (!cssData) { var link = document.createElement ('link'); link.rel = 'stylesheet'; link.type = 'text/css'; link.href = fileName +'?'+ Vn.Cookie.get ('hedera_version'); this.head.appendChild (link); this.cssIncludes[fileName] = { included: true ,link: link }; } else if (!cssData.included) { cssData.link.disabled = false; cssData.included = true; } } /** * Excludes a CSS stylesheet from the current document. * * @param {string} fileName The stylesheet file name **/ ,excludeCss: function (fileName) { var cssData = this.cssIncludes[fileName]; if (cssData && cssData.included) { cssData.link.disabled = true; cssData.included = false; } } /** * Initializes the library and calls the passed function when all * includes and its dependencies are resolved. * Should be called on the last statically incuded script. * * @param {Function} callback The main function **/ ,main: function (callback) { if (this.mainCalled) { Vn.warning ("Vn: main method should be called only once"); return; } this.mainCalled = true; this.mainCallback = callback; var basePath = location.protocol +'//'+ location.host; basePath += location.port ? ':'+ location.port : ''; basePath += location.pathname; var scripts = this.head.getElementsByTagName ('script'); var includes = this.tmpIncludes; for (var i = 0; i < scripts.length; i++) { var relPath = scripts[i].src.substr (basePath.length); relPath = relPath.substr (0, relPath.indexOf ('.js')); var includeData = this.includes[relPath]; if (includeData === undefined) { includeData = { depCount: 0 ,callbacks: [] ,loaded: true ,dependants: [] ,success: true }; this.includes[relPath] = includeData; } if (i == scripts.length - 1) includeData.callbacks.push (this._onMainDepsLoad.bind (this)); this.tmpIncludes = includes; this._onScriptLoad (includeData, true); } window.addEventListener ('load', this._onWindowLoad.bind (this)); } ,_onMainDepsLoad: function () { this.mainDepsLoaded = true; this._callMain (); } ,_onWindowLoad: function () { this.windowReady = true; this._callMain (); } ,_callMain: function () { if (this.mainCallback && this.windowReady && this.mainDepsLoaded) this.mainCallback (); } ,_handleCallback: function (includeData, callback) { if (!callback) return; if (includeData.loaded) callback (includeData.success); else includeData.callbacks.push (callback); } /** * Includes a set of javascript files and sets it as dependecies of the * current script. * * @param {...} The list of files as function arguments **/ ,include: function () { for (var i = 0; i < arguments.length; i++) { var includeData = this._realIncludeJs (arguments[i] +'.js'); if (!includeData.loaded) this.tmpIncludes.push (includeData); } } /** * Downloads a set of resources and sets it as dependecies of the * current script. * * @param {...} The list of files as function arguments **/ ,resource: function () { for (var i = 0; i < arguments.length; i++) { var includeData = this._realLoadXml (arguments[i]); if (!includeData.loaded) this.tmpIncludes.push (includeData); } } /** * Sets the function that will be called when current script dependencies * are resolved. * * @param {Function} callback The callback function **/ ,define: function (callback) { this.tmpDefine = callback; } /** * Includes an entire Javascript library including it's localized file. * * @param {string} libName The folder of the library * @param {Array} files Array with every library file name **/ ,includeLib: function (libName, files) { Vn.Locale.loadScript ('js/'+ libName +'.js'); for (var i = 0; i < files.length; i++) this.include ('js/'+ libName +'/'+ files[i]); } /** * Includes a new Javascript in the current document, if the script * is already included, does nothing and calls the callback. * * @param {string} fileName The script file name * @param {Function} callback The function to call when script is * downloaded and included **/ ,includeJs: function (fileName, callback, skipVersion) { var includeData = this._realIncludeJs (fileName, skipVersion); this._handleCallback (includeData, callback); } ,_realIncludeJs: function (fileName, skipVersion) { var includeData = this.includes[fileName]; if (includeData === undefined) { var src = fileName; if (!skipVersion) src = src +'?'+ Vn.Cookie.get ('hedera_version'); var script = document.createElement ('script'); script.type = 'text/javascript'; script.async = false; script.src = src; includeData = { depCount: 0 ,callbacks: [] ,loaded: false ,dependants: [] ,success: false }; script.onload = this._onScriptLoad.bind (this, includeData, true); script.onerror = this._onScriptLoad.bind (this, includeData, false); script.onreadystatechange = this._onScriptStateChange.bind (this, includeData, script); this.includes[fileName] = includeData; this.head.appendChild (script); } return includeData; } ,_onScriptStateChange: function (includeData, script) { if (script.readyState == 'complete') this._onScriptLoad (includeData, true); } ,_onScriptLoad: function (includeData, success) { includeData.success = success; if (success) { if (this.tmpDefine) includeData.callbacks.push (this.tmpDefine); var includes = this.tmpIncludes; if (includes && includes.length > 0) { includeData.depCount = includes.length; for (var i = 0; i < includes.length; i++) includes[i].dependants.push (includeData); } else this.resolveDeps (includeData); } else this.resolveDeps (includeData); this.tmpIncludes = []; this.tmpDefine = null; } ,resolveDeps: function (includeData) { includeData.loaded = true; var callbacks = includeData.callbacks; for (var i = 0; i < callbacks.length; i++) callbacks[i] (includeData.success); var dependants = includeData.dependants; for (var i = 0; i < dependants.length; i++) { var dependant = dependants[i]; dependant.depCount--; if (dependant.depCount == 0) this.resolveDeps (dependant); } delete includeData.callbacks; } /** * Request an XML file. * * @param {string} path The file path * @param {Function} callback The function to call when file is downloaded **/ ,loadXml: function (path, callback) { var includeData = this._realLoadXml (path); this._handleCallback (includeData, callback); } ,_realLoadXml: function (path) { var includeData = this.includes[path]; if (includeData === undefined) { includeData = { callbacks: [] ,loaded: false ,dependants: [] ,depCount: 0 ,success: false ,xml: null }; var request = new XMLHttpRequest (); request.onreadystatechange = this._onXmlReady.bind (this, includeData, request); request.open ('get', path +'?'+ Vn.Cookie.get ('hedera_version'), true); request.send (); this.includes[path] = includeData; } return includeData; } ,_onXmlReady: function (includeData, request) { if (request.readyState != 4) return; includeData.success = request.status == 200; if (includeData.success) includeData.xml = request.responseXML; this.resolveDeps (includeData); } /** * Gets the DOM object from an included XML file. * * @param {string} path The file path * @return {Object} The DOM object **/ ,getXml: function (path) { var includeData = this.includes[path]; if (!(includeData && includeData.success)) return null; return includeData.xml; } /** * Checks if user is using a mobile browser. * * return {boolean} %true if is mobile, %false otherwise. **/ ,isMobile: function () { if (this.isMobileCached === null) { var regExp = /(Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone)/i; this.isMobileCached = navigator.userAgent.match (regExp); } return this.isMobileCached; } };