mod.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /**
  2. * @file: mod.js
  3. * @author fis
  4. * ver: 1.0.11
  5. * update: 2015/05/14
  6. * https://github.com/fex-team/mod
  7. */
  8. var require;
  9. /* eslint-disable no-unused-vars */
  10. var define;
  11. (function (global) {
  12. // 避免重复加载而导致已定义模块丢失
  13. if (require) {
  14. return;
  15. }
  16. var head = document.getElementsByTagName('head')[0];
  17. var loadingMap = {};
  18. var factoryMap = {};
  19. var modulesMap = {};
  20. var scriptsMap = {};
  21. var resMap = {};
  22. var pkgMap = {};
  23. var createScript = function (url, onerror) {
  24. if (url in scriptsMap) {
  25. return;
  26. }
  27. scriptsMap[url] = true;
  28. var script = document.createElement('script');
  29. if (onerror) {
  30. var tid = setTimeout(onerror, require.timeout);
  31. script.onerror = function () {
  32. clearTimeout(tid);
  33. onerror();
  34. };
  35. var onload = function () {
  36. clearTimeout(tid);
  37. };
  38. if ('onload' in script) {
  39. script.onload = onload;
  40. }
  41. else {
  42. script.onreadystatechange = function () {
  43. if (this.readyState === 'loaded' || this.readyState === 'complete') {
  44. onload();
  45. }
  46. };
  47. }
  48. }
  49. script.type = 'text/javascript';
  50. script.src = url;
  51. head.appendChild(script);
  52. return script;
  53. };
  54. var loadScript = function (id, callback, onerror) {
  55. var queue = loadingMap[id] || (loadingMap[id] = []);
  56. queue.push(callback);
  57. //
  58. // resource map query
  59. //
  60. var res = resMap[id] || resMap[id + '.js'] || {};
  61. var pkg = res.pkg;
  62. var url;
  63. if (pkg) {
  64. url = pkgMap[pkg].url;
  65. }
  66. else {
  67. url = res.url || id;
  68. }
  69. createScript(url, onerror && function () {
  70. onerror(id);
  71. });
  72. };
  73. define = function (id, factory) {
  74. id = id.replace(/\.js$/i, '');
  75. factoryMap[id] = factory;
  76. var queue = loadingMap[id];
  77. if (queue) {
  78. for (var i = 0, n = queue.length; i < n; i++) {
  79. queue[i]();
  80. }
  81. delete loadingMap[id];
  82. }
  83. };
  84. require = function (id) {
  85. // compatible with require([dep, dep2...]) syntax.
  86. if (id && id.splice) {
  87. return require.async.apply(this, arguments);
  88. }
  89. id = require.alias(id);
  90. var mod = modulesMap[id];
  91. if (mod) {
  92. return mod.exports;
  93. }
  94. //
  95. // init module
  96. //
  97. var factory = factoryMap[id];
  98. if (!factory) {
  99. throw '[ModJS] Cannot find module `' + id + '`';
  100. }
  101. mod = modulesMap[id] = {
  102. exports: {}
  103. };
  104. //
  105. // factory: function OR value
  106. //
  107. var ret = (typeof factory === 'function') ? factory.apply(mod, [require, mod.exports, mod]) : factory;
  108. if (ret) {
  109. mod.exports = ret;
  110. }
  111. if (mod.exports && !mod.exports['default']) {
  112. mod.exports['default'] = mod.exports;
  113. }
  114. return mod.exports;
  115. };
  116. require.async = function (names, onload, onerror) {
  117. if (typeof names === 'string') {
  118. names = [names];
  119. }
  120. var needMap = {};
  121. var needNum = 0;
  122. function findNeed(depArr) {
  123. var child;
  124. for (var i = 0, n = depArr.length; i < n; i++) {
  125. //
  126. // skip loading or loaded
  127. //
  128. var dep = require.alias(depArr[i]);
  129. if (dep in factoryMap) {
  130. // check whether loaded resource's deps is loaded or not
  131. child = resMap[dep] || resMap[dep + '.js'];
  132. if (child && 'deps' in child) {
  133. findNeed(child.deps);
  134. }
  135. continue;
  136. }
  137. if (dep in needMap) {
  138. continue;
  139. }
  140. needMap[dep] = true;
  141. needNum++;
  142. loadScript(dep, updateNeed, onerror);
  143. child = resMap[dep] || resMap[dep + '.js'];
  144. if (child && 'deps' in child) {
  145. findNeed(child.deps);
  146. }
  147. }
  148. }
  149. function updateNeed() {
  150. if (0 === needNum--) {
  151. var args = [];
  152. for (var i = 0, n = names.length; i < n; i++) {
  153. args[i] = require(names[i]);
  154. }
  155. onload && onload.apply(global, args);
  156. }
  157. }
  158. findNeed(names);
  159. updateNeed();
  160. };
  161. require.resourceMap = function (obj) {
  162. var k;
  163. var col;
  164. // merge `res` & `pkg` fields
  165. col = obj.res;
  166. for (k in col) {
  167. if (col.hasOwnProperty(k)) {
  168. resMap[k] = col[k];
  169. }
  170. }
  171. col = obj.pkg;
  172. for (k in col) {
  173. if (col.hasOwnProperty(k)) {
  174. pkgMap[k] = col[k];
  175. }
  176. }
  177. };
  178. require.loadJs = function (url) {
  179. createScript(url);
  180. };
  181. require.loadCss = function (cfg) {
  182. if (cfg.content) {
  183. var sty = document.createElement('style');
  184. sty.type = 'text/css';
  185. if (sty.styleSheet) { // IE
  186. sty.styleSheet.cssText = cfg.content;
  187. }
  188. else {
  189. sty.innerHTML = cfg.content;
  190. }
  191. head.appendChild(sty);
  192. }
  193. else if (cfg.url) {
  194. var link = document.createElement('link');
  195. link.href = cfg.url;
  196. link.rel = 'stylesheet';
  197. link.type = 'text/css';
  198. head.appendChild(link);
  199. }
  200. };
  201. require.alias = function (id) {
  202. return id.replace(/\.js$/i, '');
  203. };
  204. require.timeout = 5000;
  205. })(this);