/**================================================================== Configuration file for MMOE Selects and loads... - Libraries - Plugins - Application * BRIEF DESCRIPTION * Ideally, the config.js will not be static, and instead will be generated from an API Application (written in a web language such as PHP, Perl, ASP, JSP, or Python). This will allow users to login seperately (which is required by mmoe's auth features), select custom plugins -- and for the server itself to specify what game and what libraries are required to load. * LOADING EXTERNAL FILES * Because of the way mmoe works to be flexible and easy-to-change, you often will have to include several default scripts and stylesheets, at least half a dozen library files for the application, any user or default selected plugin files, and the application itself --- all this not included whatever styles or scripts the individual files load. HTTP requests could number to about 50 or more on sophisticated systems. For this reason we recommend you host them on seperate DNS's to pass through the DNS limit feature of the browser, and to alleviate load on your servers. * COMPATIBILITY TESTING * Works (and tested) in: - Firefox 2.0 /Gecko - Safari 3 /WebKit Build 420 or > - Opera 9 - IE 6 - IE 7 Works (with bugs or workarounds) in: - Safari 2 /WebKit Build < 420 - Konqueror /KDE (Similar to Safari 2) * Both browsers are unable to detect when an external file has loaded, making loading screens and such useless. * IMPORTANT NOTE * -------------------------------------------------------------- The configurational file also includes a few library functions that are necessary, and are not needed to be created elsewhere -------------------------------------------------------------- - Importing External Files - Debug function - Extends the ARRAY Object .last(): Returns the last object in the array .forEach(): For browsers without native implementation - Extends the STRING Object .extension(): Returns the file extension of a string - document.head will reference the <head> element==================================================================**/var Config = { /** Edited by Server ***********************************************/ Libraries: [ /* {name: "Name of Library", path: "Path to library", icon: "icon for splash}," */ {name: "Object Oriented Programming", path: "../libs/lib-oop.js", icon: "../libs/lib-oop/icon.png"}, {name: "Networking", path: "../libs/lib-networking.js", icon: "../libs/lib-networking/icon.png"}, {name: "Storage", path: "../libs/lib-storage.js", icon: "../libs/lib-storage/icon.png"} ], Plugins: [ /* {name: "Some-Green", path: "../plugins/something.js", icon: "../plugins/something/icon.png"}, {name: "Else-Red", path: "../plugins/else.js", icon: "../plugins/else/icon.png"}, {name: "More-Blue", path: "../plugins/more.js", icon: "../plugins/more/icon.png"} */ ], Application: { name: "MMOE Demo - Web Chat", version: "0.01 Alpha", path: "../apps/simple-web-chat.js", icon: "../apps/simple-web-chat/icon.png" }, /** === END === Edited by Server ************************************/ Splash: { Design: "", Todo: 0, Did: 0, /** ============================================================== @method: Config.Splash.onLoad() @param: Object <item loaded> Automatically called whenever a module of the application loads, automatically giving it the icon as a paramter, the name of it as a parameter, and the function itself will calculate a percentage done. =============================================================== **/ onLoad: function(item){ Config.Splash.Did++; // Update progress bar var percentDone = (Math.round((Config.Splash.Did / Config.Splash.Todo) * 100)); Config._dom.progressBar.style.width = percentDone + "%"; // Get Variables var name = item.name; var icon = item.icon; var path = item.path; // Highlight the icon specified var icons = Config._dom.splashIconWrapper.childNodes; for (var i=(Browser.ie) ? 0 : 1;i<icons.length;i++){ if (icons[i].tagName.toUpperCase() == "SPAN"){ if (icons[i]._imgSrc == icon){ icons[i].className = "splash-icon done"; break; } } } // Update Text Config._dom.progressText.innerHTML = "Module loaded: " + item.name + " [" + item.path + "]"; // [Todo] } }, /** ============================================================== @method: Config.Startup() Run automatically when all initial files are loaded =============================================================== **/ _dom: {}, Startup: function(){ // 0.) Get some DOM's into memory // A.) getElementById() Config._dom.splashIconWrapper = document.getElementById("splash-icon-wrapper"); Config._dom.progressBar = document.getElementById("splash-progress-bar"); Config._dom.progressText = document.getElementById("splash-progress-text"); // B.) Set body.id to the current browser for (browser in Browser) if (Browser[browser]) document.body.id = browser; // 1.) Show Application Information document.title = Config.Application.name + " - Powered by MMOE"; document.getElementById("splash-header").innerHTML = Config.Application.name; // 2.) Identify number of modules required to load Config.Splash.Todo = Config.Plugins.length + Config.Libraries.length + 1; Debug("Analyzing modules to load: " + Config.Splash.Todo); // 3.) Preload Icons for Splashscreen // A.) Retrieve all Names Debug("Preloading splash-screen images..."); var icons = []; Config.Libraries.forEach(function (item){icons.push(item.icon);}); Config.Plugins.forEach(function (item){icons.push(item.icon);}); icons.push(Config.Application.icon); // B.) Create Splashscreen Image holders icons.forEach(function (item){ var splashIcon = document.createElement("span"); splashIcon._imgSrc = item; splashIcon.className = "splash-icon"; splashIcon.style.backgroundImage = "url("+item+")"; Config._dom.splashIconWrapper.appendChild(splashIcon); }); // C.) On completion of icons Config.Import.images(icons, function(){ // 4.) Load and Pass to onLoad Debug("All icons are loaded, now start script loading..."); // A.) Libraries Config.Libraries.forEach(function (item){ Debug("Preparing to load library: " + item.name); Config.Import.file(item.path, function(){ Debug("Library [" + item.name + "]: Loaded!"); Config.Splash.onLoad(item); }); }); // B.) Plugins Config.Plugins.forEach(function (item){ Debug("Preparing to load plugin: " + item.name); Config.Import.file(item.path, function(){ Debug("Plugin [" + item.name + "]: Loaded!"); Config.Splash.onLoad(item); }); }); // C.) The Application Itself Config.Import.file(Config.Application.path, function(){ Debug("Application [" + Config.Application.name + "]: Loaded!"); Config.Splash.onLoad(Config.Application); }); }); }, Import: { /** ============================================================== @method: Config.Import.file() @param: String <filePath> @param: Function <callback> Load an external file on-the-fly. Function automatically parses the extension, and loads accordingly - passing the function to a sub-function. @return: Object <The actual Image or HTMLElement> =============================================================== **/ file: function(path, func){ switch (path.extension()){ case "js": var Loading = Config.Import.js(path, func); break; case "css": var Loading = Config.Import.css(path, func); break; } var Loading = Config.Import.image(path, func); Loading.onload = func; return Loading; }, /** ============================================================== @method: Config.Import.css() @param: String <filePath> @param: Function <callback> Loads an external stylesheet and adds it to the DOM @return: Object <HTMLElement> *NOTE* If you wish the stylesheet to be disabled upon load, make sure you set .disabled = true to the returning object. =============================================================== **/ css: function(path, func){ var link = document.createElement("script"); link.type = "text/css"; link.href = path; link.rel = "stylesheet"; document.head.appendChild(link); Config.Import.onLoad(css, func); return link; }, /** ============================================================== @method: Config.Import.js() @param: String <filePath> @param: Function <callback> Loads an external JavaScript and adds it to the DOM @return: Object <HTMLElement> =============================================================== **/ js: function(path, func){ var script = document.createElement("script"); script.type = "text/javascript"; script.src = path; document.head.appendChild(script); Config.Import.onLoad(script, func); return script; }, /** ============================================================== @method: Config.Import.images() @param: Array <filePaths> @param: Function <callback> Loads a number of image files into memory, running the callback function when all of them are completed. (Nothing returned) =============================================================== **/ images: function(paths, func){ var todo = paths.length; // Load all images paths.forEach(function (item){ var img = Config.Import.image(item); Config.Import.onLoad(img, function(){; todo--; if (todo == 0) func(); }); }); }, /** ============================================================== @method: Config.Import.image() @param: String <filePath> @param: Function <callback> Loads an image into memory (preload) @return: Object <Image> =============================================================== **/ image: function(path, func){ var image = new Image(); image.src = path; Config.Import.onLoad(image, func); return image; }, /** ============================================================== @method: Config.Import.onLoad() @param: Object <Any loadable external source> @param: Function <callback> Helper function for the other Config.Import.* functions, but can also be used elsewhere. It's a cross-browser and cross-element callback implementation for the successful loading of HTML Elements (Script & Link) or Image objects. ---- Brief Overview of Features: Gecko Engine and WebKit 420+ (Safari 3): Uses the <object>.onload callback natively Internet Explorer 6 & 7 Uses the <object>.onreadystate callback automatically, but we wait for readyState of "loaded" or "complete" to continue - semi-native. Opera (9 tested): Objects have a .readyState, but no callback function, so we set a 100ms interval to check for its loading. KDE and WebKit 419- (Safari 2): Impossible to detect, runs callback automatically. If you require something to be loaded you will have to check by other means. =============================================================== **/ onLoad: function(obj, func){ if (!func) return; // Gecko Engine and Newer WebKits if (Browser.gecko || Browser.webkit420){ obj.onload = func; return; } // Works with Internet Explorer if (Browser.ie){ obj.onreadystatechange=function(){ // Works for Script, Link, and Image elements if (obj.readyState == "loaded" || obj.readyState == "complete" && !func._failSafe){ func._failSafe = true; func(); } } return; } // Works with Opera if (Browser.opera) { // Images won't showup with a readyState var ext = (obj.src) ? obj.src.extension() : obj.href.extension(); if (ext != "css" && ext != "js") return func(); var timer = setInterval(function(){ if (obj.readyState == "loaded" || obj.readyState == "complete"){ clearInterval(timer); func(); } }, 100); return; } // Older WebKits/KDE... Just pretend its ready? if (!func._failSafe ){ setTimeout(function(){ func._failSafe = true; func(); }, 1000); } } }, _failSafes: []}/** ============================================================== Basic Library Includes Requiured for Module Make sure not to duplicate them elsewhere.=============================================================== **//** Debugging Module ***********************************************/function Debug(text){if (document.console) document.console.innerHTML = "<br />" +text + document.console.innerHTML;}/** Makes work easier **********************************************/Array.prototype.last=function(){return this[this.length - 1];};String.prototype.extension=function(){return this.split(".").last();};if (!Array.prototype.forEach)Array.prototype.forEach=function(func){var l=this.length; if (!l) return; for (var i=0;i<l;i++) func(this[i]);}/** Bootup *********************************************************/document.head=document.getElementsByTagName("head")[0];if (window.addEventListener) window.addEventListener("load", Config.Startup, false);else window.attachEvent("onload", Config.Startup);