/* global config, vendor, MM, Log, Module */ /* jshint unused:false */ /* jshint -W061 */ /* Magic Mirror * Module and File loaders. * * By Michael Teeuw http://michaelteeuw.nl * MIT Licensed. */ var Loader = (function() { /* Create helper valiables */ var loadedModuleFiles = []; var loadedFiles = []; var moduleObjects = []; /* Private Methods */ /* loadModules() * Loops thru all modules and requests load for every module. */ var loadModules = function() { var moduleData = getModuleData(); var loadNextModule = function() { if (moduleData.length > 0) { var nextModule = moduleData[0]; loadModule(nextModule, function() { moduleData = moduleData.slice(1); loadNextModule(); }); } else { startModules(); } }; loadNextModule(); }; /* startModules() * Loops thru all modules and requests start for every module. */ var startModules = function() { for (var m in moduleObjects) { var module = moduleObjects[m]; module.start(); } // Notifiy core of loded modules. MM.modulesStarted(moduleObjects); }; /* getAllModules() * Retrieve list of all modules. * * return array - module data as configured in config */ var getAllModules = function() { return config.modules; }; /* getModuleData() * Generate array with module information including module paths. * * return array - Module information. */ var getModuleData = function() { var modules = getAllModules(); var moduleFiles = []; for (var m in modules) { var moduleData = modules[m]; var module = moduleData.module; moduleFiles.push({ index: m, identifier: 'module_' + m + '_' + module, name: module, path: config.paths.modules + '/' + module, file: module + '.js', position: moduleData.position, header: moduleData.header, config: moduleData.config }); } return moduleFiles; }; /* loadModule(module) * Load modules via ajax request and create module objects. * * argument callback function - Function called when done. * argument module object - Information about the module we want to load. */ var loadModule = function(module, callback) { var url = module.path + '/' + module.file; var afterLoad = function() { var moduleObject = Module.create(module.name); bootstrapModule(module, moduleObject, function() { callback(); }); }; if (loadedModuleFiles.indexOf(url) !== -1) { afterLoad(); } else { loadFile(url, function() { loadedModuleFiles.push(url); afterLoad(); }); } }; /* bootstrapModule(module, mObj) * Bootstrap modules by setting the module data and loading the scripts & styles. * * argument module object - Information about the module we want to load. * argument mObj object - Modules instance. * argument callback function - Function called when done. */ var bootstrapModule = function(module, mObj, callback) { Log.info('Bootstrapping module: ' + module.name); mObj.setData(module); mObj.loadScripts(function() { Log.log('Scripts loaded for: ' + module.name); mObj.loadStyles(function(){ Log.log('Styles loaded for: ' + module.name); callback(); }); }); moduleObjects.push(mObj); }; /* loadFile(fileName) * Load a script or stylesheet by adding it to the dom. * * argument fileName string - Path of the file we want to load. * argument callback function - Function called when done. */ var loadFile = function(fileName, callback) { var extension = fileName.slice((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1); switch (extension.toLowerCase()) { case "js": Log.log('Load script: ' + fileName); var script = document.createElement("script"); script.type = "text/javascript"; script.src = fileName; script.onload = function() { if (typeof callback === 'function') {callback();} }; document.getElementsByTagName("body")[0].appendChild(script); break; case "css": Log.log('Load stylesheet: ' + fileName); var stylesheet = document.createElement("link"); stylesheet.rel = "stylesheet"; stylesheet.type = "text/css"; stylesheet.href = fileName; stylesheet.onload = function() { if (typeof callback === 'function') {callback();} }; document.getElementsByTagName("head")[0].appendChild(stylesheet); break; } }; /* Public Methods */ return { /* loadModules() * Load all modules as defined in the config. */ loadModules: function() { loadModules(); }, /* loadFile() * Load a file (script or stylesheet). * Prevent double loading and search for files in the vendor folder. * * argument fileName string - Path of the file we want to load. * argument module Module Object - the module that calls the loadFile function. * argument callback function - Function called when done. */ loadFile: function(fileName, module, callback) { if (loadedFiles.indexOf(fileName.toLowerCase()) !== -1) { Log.log('File already loaded: ' + fileName); callback(); return; } if (fileName.indexOf('http://') === 0 || fileName.indexOf('https://') === 0 || fileName.indexOf('/') !== -1) { // This is an absolute or relative path. // Load it and then return. loadedFiles.push(fileName.toLowerCase()); loadFile(fileName, callback); return; } if (vendor[fileName] !== undefined) { // This file is available in the vendor folder. // Load it from this vendor folder. loadedFiles.push(fileName.toLowerCase()); loadFile(config.paths.vendor+'/'+vendor[fileName], callback); return; } // File not loaded yet. // Load it based on the module path. loadedFiles.push(fileName.toLowerCase()); loadFile(module.file(fileName), callback); } }; })();