load-module.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import { getWindow, getDocument } from 'ssr-window';
  2. import { id } from '../../shared/utils.js';
  3. import $ from '../../shared/dom7.js';
  4. const fetchedModules = [];
  5. function loadModule(moduleToLoad) {
  6. const Framework7 = this;
  7. const window = getWindow();
  8. const document = getDocument();
  9. return new Promise((resolve, reject) => {
  10. const app = Framework7.instance;
  11. let modulePath;
  12. let moduleObj;
  13. let moduleFunc;
  14. if (!moduleToLoad) {
  15. reject(new Error('Framework7: Lazy module must be specified'));
  16. return;
  17. }
  18. function install(module) {
  19. Framework7.use(module);
  20. if (app) {
  21. app.useModuleParams(module, app.params);
  22. app.useModule(module);
  23. }
  24. }
  25. if (typeof moduleToLoad === 'string') {
  26. const matchNamePattern = moduleToLoad.match(/([a-z0-9-]*)/i);
  27. if (moduleToLoad.indexOf('.') < 0 && matchNamePattern && matchNamePattern[0].length === moduleToLoad.length) {
  28. if (!app || app && !app.params.lazyModulesPath) {
  29. reject(new Error('Framework7: "lazyModulesPath" app parameter must be specified to fetch module by name'));
  30. return;
  31. }
  32. modulePath = `${app.params.lazyModulesPath}/${moduleToLoad}/${moduleToLoad}.lazy.js`;
  33. } else {
  34. modulePath = moduleToLoad;
  35. }
  36. } else if (typeof moduleToLoad === 'function') {
  37. moduleFunc = moduleToLoad;
  38. } else {
  39. // considering F7-Plugin object
  40. moduleObj = moduleToLoad;
  41. }
  42. if (moduleFunc) {
  43. const module = moduleFunc(Framework7, false);
  44. if (!module) {
  45. reject(new Error("Framework7: Can't find Framework7 component in specified component function"));
  46. return;
  47. } // Check if it was added
  48. if (Framework7.prototype.modules && Framework7.prototype.modules[module.name]) {
  49. resolve();
  50. return;
  51. } // Install It
  52. install(module);
  53. resolve();
  54. }
  55. if (moduleObj) {
  56. const module = moduleObj;
  57. if (!module) {
  58. reject(new Error("Framework7: Can't find Framework7 component in specified component"));
  59. return;
  60. } // Check if it was added
  61. if (Framework7.prototype.modules && Framework7.prototype.modules[module.name]) {
  62. resolve();
  63. return;
  64. } // Install It
  65. install(module);
  66. resolve();
  67. }
  68. if (modulePath) {
  69. if (fetchedModules.indexOf(modulePath) >= 0) {
  70. resolve();
  71. return;
  72. }
  73. fetchedModules.push(modulePath);
  74. const scriptLoad = new Promise((resolveScript, rejectScript) => {
  75. Framework7.request.get(modulePath, scriptContent => {
  76. const callbackId = id();
  77. const callbackLoadName = `f7_component_loader_callback_${callbackId}`;
  78. const scriptEl = document.createElement('script');
  79. scriptEl.innerHTML = `window.${callbackLoadName} = function (Framework7, Framework7AutoInstallComponent) {return ${scriptContent.trim()}}`;
  80. $('head').append(scriptEl);
  81. const componentLoader = window[callbackLoadName];
  82. delete window[callbackLoadName];
  83. $(scriptEl).remove();
  84. const module = componentLoader(Framework7, false);
  85. if (!module) {
  86. rejectScript(new Error(`Framework7: Can't find Framework7 component in ${modulePath} file`));
  87. return;
  88. } // Check if it was added
  89. if (Framework7.prototype.modules && Framework7.prototype.modules[module.name]) {
  90. resolveScript();
  91. return;
  92. } // Install It
  93. install(module);
  94. resolveScript();
  95. }, (xhr, status) => {
  96. rejectScript(xhr, status);
  97. });
  98. });
  99. const styleLoad = new Promise(resolveStyle => {
  100. Framework7.request.get(modulePath.replace('.lazy.js', app.rtl ? '.rtl.css' : '.css').replace('.js', app.rtl ? '.rtl.css' : '.css'), styleContent => {
  101. const styleEl = document.createElement('style');
  102. styleEl.innerHTML = styleContent;
  103. $('head').append(styleEl);
  104. resolveStyle();
  105. }, () => {
  106. resolveStyle();
  107. });
  108. });
  109. Promise.all([scriptLoad, styleLoad]).then(() => {
  110. resolve();
  111. }).catch(err => {
  112. reject(err);
  113. });
  114. }
  115. });
  116. }
  117. export default loadModule;