123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- /* global defaultModules, vendor */
-
- /* Magic Mirror
- * Module and File loaders.
- *
- * By Michael Teeuw https://michaelteeuw.nl
- * MIT Licensed.
- */
- const Loader = (function () {
- /* Create helper variables */
-
- const loadedModuleFiles = [];
- const loadedFiles = [];
- const moduleObjects = [];
-
- /* Private Methods */
-
- /**
- * Loops thru all modules and requests load for every module.
- */
- const loadModules = function () {
- let moduleData = getModuleData();
-
- const loadNextModule = function () {
- if (moduleData.length > 0) {
- const nextModule = moduleData[0];
- loadModule(nextModule, function () {
- moduleData = moduleData.slice(1);
- loadNextModule();
- });
- } else {
- // All modules loaded. Load custom.css
- // This is done after all the modules so we can
- // overwrite all the defined styles.
-
- loadFile(config.customCss, function () {
- // custom.css loaded. Start all modules.
- startModules();
- });
- }
- };
-
- loadNextModule();
- };
-
- /**
- * Loops thru all modules and requests start for every module.
- */
- const startModules = function () {
- for (const module of moduleObjects) {
- module.start();
- }
-
- // Notify core of loaded modules.
- MM.modulesStarted(moduleObjects);
-
- // Starting modules also hides any modules that have requested to be initially hidden
- for (const thisModule of moduleObjects) {
- if (thisModule.data.hiddenOnStartup) {
- Log.info("Initially hiding " + thisModule.name);
- thisModule.hide();
- }
- }
- };
-
- /**
- * Retrieve list of all modules.
- *
- * @returns {object[]} module data as configured in config
- */
- const getAllModules = function () {
- return config.modules;
- };
-
- /**
- * Generate array with module information including module paths.
- *
- * @returns {object[]} Module information.
- */
- const getModuleData = function () {
- const modules = getAllModules();
- const moduleFiles = [];
-
- modules.forEach(function (moduleData, index) {
- const module = moduleData.module;
-
- const elements = module.split("/");
- const moduleName = elements[elements.length - 1];
- let moduleFolder = config.paths.modules + "/" + module;
-
- if (defaultModules.indexOf(moduleName) !== -1) {
- moduleFolder = config.paths.modules + "/default/" + module;
- }
-
- if (moduleData.disabled === true) {
- return;
- }
-
- moduleFiles.push({
- index: index,
- identifier: "module_" + index + "_" + module,
- name: moduleName,
- path: moduleFolder + "/",
- file: moduleName + ".js",
- position: moduleData.position,
- hiddenOnStartup: moduleData.hiddenOnStartup,
- header: moduleData.header,
- configDeepMerge: typeof moduleData.configDeepMerge === "boolean" ? moduleData.configDeepMerge : false,
- config: moduleData.config,
- classes: typeof moduleData.classes !== "undefined" ? moduleData.classes + " " + module : module
- });
- });
-
- return moduleFiles;
- };
-
- /**
- * Load modules via ajax request and create module objects.s
- *
- * @param {object} module Information about the module we want to load.
- * @param {Function} callback Function called when done.
- */
- const loadModule = function (module, callback) {
- const url = module.path + module.file;
-
- const afterLoad = function () {
- const moduleObject = Module.create(module.name);
- if (moduleObject) {
- bootstrapModule(module, moduleObject, function () {
- callback();
- });
- } else {
- callback();
- }
- };
-
- if (loadedModuleFiles.indexOf(url) !== -1) {
- afterLoad();
- } else {
- loadFile(url, function () {
- loadedModuleFiles.push(url);
- afterLoad();
- });
- }
- };
-
- /**
- * Bootstrap modules by setting the module data and loading the scripts & styles.
- *
- * @param {object} module Information about the module we want to load.
- * @param {Module} mObj Modules instance.
- * @param {Function} callback Function called when done.
- */
- const 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);
- mObj.loadTranslations(function () {
- Log.log("Translations loaded for: " + module.name);
- moduleObjects.push(mObj);
- callback();
- });
- });
- });
- };
-
- /**
- * Load a script or stylesheet by adding it to the dom.
- *
- * @param {string} fileName Path of the file we want to load.
- * @param {Function} callback Function called when done.
- */
- const loadFile = function (fileName, callback) {
- const extension = fileName.slice((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1);
- let script, stylesheet;
-
- switch (extension.toLowerCase()) {
- case "js":
- Log.log("Load script: " + fileName);
- script = document.createElement("script");
- script.type = "text/javascript";
- script.src = fileName;
- script.onload = function () {
- if (typeof callback === "function") {
- callback();
- }
- };
- script.onerror = function () {
- Log.error("Error on loading script:", fileName);
- if (typeof callback === "function") {
- callback();
- }
- };
-
- document.getElementsByTagName("body")[0].appendChild(script);
- break;
- case "css":
- Log.log("Load stylesheet: " + fileName);
- stylesheet = document.createElement("link");
- stylesheet.rel = "stylesheet";
- stylesheet.type = "text/css";
- stylesheet.href = fileName;
- stylesheet.onload = function () {
- if (typeof callback === "function") {
- callback();
- }
- };
- stylesheet.onerror = function () {
- Log.error("Error on loading stylesheet:", fileName);
- if (typeof callback === "function") {
- callback();
- }
- };
-
- document.getElementsByTagName("head")[0].appendChild(stylesheet);
- break;
- }
- };
-
- /* Public Methods */
- return {
- /**
- * Load all modules as defined in the config.
- */
- loadModules: function () {
- loadModules();
- },
-
- /**
- * Load a file (script or stylesheet).
- * Prevent double loading and search for files in the vendor folder.
- *
- * @param {string} fileName Path of the file we want to load.
- * @param {Module} module The module that calls the loadFile function.
- * @param {Function} callback 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);
- }
- };
- })();
|