Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

loader.js 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /* global defaultModules, vendor */
  2. /* Magic Mirror
  3. * Module and File loaders.
  4. *
  5. * By Michael Teeuw https://michaelteeuw.nl
  6. * MIT Licensed.
  7. */
  8. const Loader = (function () {
  9. /* Create helper variables */
  10. const loadedModuleFiles = [];
  11. const loadedFiles = [];
  12. const moduleObjects = [];
  13. /* Private Methods */
  14. /**
  15. * Loops thru all modules and requests load for every module.
  16. */
  17. const loadModules = function () {
  18. let moduleData = getModuleData();
  19. const loadNextModule = function () {
  20. if (moduleData.length > 0) {
  21. const nextModule = moduleData[0];
  22. loadModule(nextModule, function () {
  23. moduleData = moduleData.slice(1);
  24. loadNextModule();
  25. });
  26. } else {
  27. // All modules loaded. Load custom.css
  28. // This is done after all the modules so we can
  29. // overwrite all the defined styles.
  30. loadFile(config.customCss, function () {
  31. // custom.css loaded. Start all modules.
  32. startModules();
  33. });
  34. }
  35. };
  36. loadNextModule();
  37. };
  38. /**
  39. * Loops thru all modules and requests start for every module.
  40. */
  41. const startModules = function () {
  42. for (const module of moduleObjects) {
  43. module.start();
  44. }
  45. // Notify core of loaded modules.
  46. MM.modulesStarted(moduleObjects);
  47. // Starting modules also hides any modules that have requested to be initially hidden
  48. for (const thisModule of moduleObjects) {
  49. if (thisModule.data.hiddenOnStartup) {
  50. Log.info("Initially hiding " + thisModule.name);
  51. thisModule.hide();
  52. }
  53. }
  54. };
  55. /**
  56. * Retrieve list of all modules.
  57. *
  58. * @returns {object[]} module data as configured in config
  59. */
  60. const getAllModules = function () {
  61. return config.modules;
  62. };
  63. /**
  64. * Generate array with module information including module paths.
  65. *
  66. * @returns {object[]} Module information.
  67. */
  68. const getModuleData = function () {
  69. const modules = getAllModules();
  70. const moduleFiles = [];
  71. modules.forEach(function (moduleData, index) {
  72. const module = moduleData.module;
  73. const elements = module.split("/");
  74. const moduleName = elements[elements.length - 1];
  75. let moduleFolder = config.paths.modules + "/" + module;
  76. if (defaultModules.indexOf(moduleName) !== -1) {
  77. moduleFolder = config.paths.modules + "/default/" + module;
  78. }
  79. if (moduleData.disabled === true) {
  80. return;
  81. }
  82. moduleFiles.push({
  83. index: index,
  84. identifier: "module_" + index + "_" + module,
  85. name: moduleName,
  86. path: moduleFolder + "/",
  87. file: moduleName + ".js",
  88. position: moduleData.position,
  89. hiddenOnStartup: moduleData.hiddenOnStartup,
  90. header: moduleData.header,
  91. configDeepMerge: typeof moduleData.configDeepMerge === "boolean" ? moduleData.configDeepMerge : false,
  92. config: moduleData.config,
  93. classes: typeof moduleData.classes !== "undefined" ? moduleData.classes + " " + module : module
  94. });
  95. });
  96. return moduleFiles;
  97. };
  98. /**
  99. * Load modules via ajax request and create module objects.s
  100. *
  101. * @param {object} module Information about the module we want to load.
  102. * @param {Function} callback Function called when done.
  103. */
  104. const loadModule = function (module, callback) {
  105. const url = module.path + module.file;
  106. const afterLoad = function () {
  107. const moduleObject = Module.create(module.name);
  108. if (moduleObject) {
  109. bootstrapModule(module, moduleObject, function () {
  110. callback();
  111. });
  112. } else {
  113. callback();
  114. }
  115. };
  116. if (loadedModuleFiles.indexOf(url) !== -1) {
  117. afterLoad();
  118. } else {
  119. loadFile(url, function () {
  120. loadedModuleFiles.push(url);
  121. afterLoad();
  122. });
  123. }
  124. };
  125. /**
  126. * Bootstrap modules by setting the module data and loading the scripts & styles.
  127. *
  128. * @param {object} module Information about the module we want to load.
  129. * @param {Module} mObj Modules instance.
  130. * @param {Function} callback Function called when done.
  131. */
  132. const bootstrapModule = function (module, mObj, callback) {
  133. Log.info("Bootstrapping module: " + module.name);
  134. mObj.setData(module);
  135. mObj.loadScripts(function () {
  136. Log.log("Scripts loaded for: " + module.name);
  137. mObj.loadStyles(function () {
  138. Log.log("Styles loaded for: " + module.name);
  139. mObj.loadTranslations(function () {
  140. Log.log("Translations loaded for: " + module.name);
  141. moduleObjects.push(mObj);
  142. callback();
  143. });
  144. });
  145. });
  146. };
  147. /**
  148. * Load a script or stylesheet by adding it to the dom.
  149. *
  150. * @param {string} fileName Path of the file we want to load.
  151. * @param {Function} callback Function called when done.
  152. */
  153. const loadFile = function (fileName, callback) {
  154. const extension = fileName.slice((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1);
  155. let script, stylesheet;
  156. switch (extension.toLowerCase()) {
  157. case "js":
  158. Log.log("Load script: " + fileName);
  159. script = document.createElement("script");
  160. script.type = "text/javascript";
  161. script.src = fileName;
  162. script.onload = function () {
  163. if (typeof callback === "function") {
  164. callback();
  165. }
  166. };
  167. script.onerror = function () {
  168. Log.error("Error on loading script:", fileName);
  169. if (typeof callback === "function") {
  170. callback();
  171. }
  172. };
  173. document.getElementsByTagName("body")[0].appendChild(script);
  174. break;
  175. case "css":
  176. Log.log("Load stylesheet: " + fileName);
  177. stylesheet = document.createElement("link");
  178. stylesheet.rel = "stylesheet";
  179. stylesheet.type = "text/css";
  180. stylesheet.href = fileName;
  181. stylesheet.onload = function () {
  182. if (typeof callback === "function") {
  183. callback();
  184. }
  185. };
  186. stylesheet.onerror = function () {
  187. Log.error("Error on loading stylesheet:", fileName);
  188. if (typeof callback === "function") {
  189. callback();
  190. }
  191. };
  192. document.getElementsByTagName("head")[0].appendChild(stylesheet);
  193. break;
  194. }
  195. };
  196. /* Public Methods */
  197. return {
  198. /**
  199. * Load all modules as defined in the config.
  200. */
  201. loadModules: function () {
  202. loadModules();
  203. },
  204. /**
  205. * Load a file (script or stylesheet).
  206. * Prevent double loading and search for files in the vendor folder.
  207. *
  208. * @param {string} fileName Path of the file we want to load.
  209. * @param {Module} module The module that calls the loadFile function.
  210. * @param {Function} callback Function called when done.
  211. */
  212. loadFile: function (fileName, module, callback) {
  213. if (loadedFiles.indexOf(fileName.toLowerCase()) !== -1) {
  214. Log.log("File already loaded: " + fileName);
  215. callback();
  216. return;
  217. }
  218. if (fileName.indexOf("http://") === 0 || fileName.indexOf("https://") === 0 || fileName.indexOf("/") !== -1) {
  219. // This is an absolute or relative path.
  220. // Load it and then return.
  221. loadedFiles.push(fileName.toLowerCase());
  222. loadFile(fileName, callback);
  223. return;
  224. }
  225. if (vendor[fileName] !== undefined) {
  226. // This file is available in the vendor folder.
  227. // Load it from this vendor folder.
  228. loadedFiles.push(fileName.toLowerCase());
  229. loadFile(config.paths.vendor + "/" + vendor[fileName], callback);
  230. return;
  231. }
  232. // File not loaded yet.
  233. // Load it based on the module path.
  234. loadedFiles.push(fileName.toLowerCase());
  235. loadFile(module.file(fileName), callback);
  236. }
  237. };
  238. })();