1 /** 2 * Jx loader module 3 * */ 4 Jx().$package(function(J){ 5 var depends={}, //key:module name, value:array of module name 6 sheet2Module={}, 7 module2Sheet={}; 8 moduleLoaded={}; 9 var included, 10 processing; 11 /** 12 * @namespace 13 * @name loader 14 */ 15 var $L = J.loader = J.loader || {}; 16 /** 17 * @param {string} url 18 * @param {function} callback 19 */ 20 var loadScript = function(url,callback){ 21 var node=document.createElement('script'); 22 node.onload=node.onreadystatechange=function(){ 23 var rs=node.readyState; 24 if('undefined'===typeof rs || 'loaded'===rs || 'complete'===rs){ 25 try{ 26 callback && callback(J); 27 }finally{ 28 node.onload=node.onreadystatechange=null; 29 node=null; 30 } 31 } 32 }; 33 node.async=true; 34 node.charset='utf-8'; 35 node.src=url; 36 (document.head || document.documentElement).appendChild(node); 37 }; 38 /** 39 * @param {string} key 模块名称 40 * @return {array} 依赖模块名称 41 */ 42 var getDepend = function(key){ 43 if(depends.hasOwnProperty(key)){ 44 return depends[key]; 45 } 46 return []; 47 }; 48 /** 49 * @method addDepend 50 * @memberOf loader 51 * @param {string} key 模块名称 52 * @param {array} list 依赖模块名称 53 */ 54 var addDepend = function(key,list){ 55 if('string'===typeof list){ 56 list=Array.prototype.slice.call(arguments,1); 57 } 58 if(!depends.hasOwnProperty(key)){ 59 depends[key]=list.slice(0); 60 }else{ 61 depends[key]=depends[key].concat(list); 62 } 63 depends[key].sort(); 64 }; 65 /** 66 * @method addDepends 67 * @memberOf loader 68 * @param {object} depends {key:list,...} 69 */ 70 var addDepends = function(depends){ 71 for(var key in depends){ 72 if(depends.hasOwnProperty(key)){ 73 addDepend(key,depends[key]); 74 } 75 } 76 }; 77 /** 78 * @method addSheet 79 * @memberOf loader 80 * @param {string} sheet 样式表名称 81 * @param {string} module 对应的模块,没有对应模块填null 82 */ 83 var addSheet = function(sheet,module){ 84 sheet2Module[sheet]=module; 85 if(module){ 86 module2Sheet[module]=sheet; 87 } 88 }; 89 /** 90 * @method addSheets 91 * @memberOf loader 92 * @param {object} sheets {sheet:module,...} 93 */ 94 var addSheets = function(sheets){ 95 for(var sheet in sheets){ 96 if(sheets.hasOwnProperty(sheet)){ 97 addSheet(sheet,sheets[sheet]); 98 } 99 } 100 }; 101 /** 102 * @param {string} name 模块名称 103 * @return {boolean} 是否已加载 104 */ 105 var isModuleLoaded = function(name){ 106 if(moduleLoaded[name.toLowerCase()]){ 107 return true; 108 }else{ 109 if('function'===typeof $L.featureDetect){ 110 return moduleLoaded[name.toLowerCase()]=$L.featureDetect(name); 111 } 112 return false; 113 } 114 }; 115 /** 116 * @param {string} name 模块名称 117 */ 118 var markModuleLoaded = function(name){ 119 moduleLoaded[name.toLowerCase()]=true; 120 }; 121 /** 122 * @memberOf loader 123 * @method require 124 * @param {array} modules 请求的模块 125 * @param {function} callback 126 * @example 127 * Jx().$require(['dom'],function(J){ 128 * var $D=J.dom, 129 * node=$D.node('div'); 130 * }); 131 */ 132 var require = function(modules,callback){ 133 if('string'===typeof(modules)){ 134 modules=Array.prototype.slice.call(arguments,0,-1); 135 callback=arguments[arguments.length-1]; 136 } 137 var list=getRequiredList(modules), 138 cssList=[], 139 sheet; 140 for(var i=0,len=list.length;i<len;i++){ 141 if(sheet=module2Sheet[list[i]]){ 142 cssList.push(sheet+'.css'); 143 } 144 } 145 if(list.length){ 146 var url=$L.joinUrlByList(cssList.concat(list)); 147 loadScript(url,callback); 148 }else{ 149 try{ 150 callback && callback(J); 151 }finally{} 152 } 153 }; 154 /** 155 * @param {array} modules 156 * @return {array} require list 157 */ 158 var getRequiredList = function(modules){ 159 modules.sort(); 160 processing={}; 161 included={}; 162 var result=deepSearch(modules); 163 processing=included=null; 164 return result; 165 }; 166 /** 167 * @param {array} modules 168 * @return {array} require list 169 */ 170 var deepSearch = function(modules){ 171 var module, 172 dependList, 173 resList, 174 result=[]; 175 for(var i=0,l=modules.length;i<l;i++){ 176 module=modules[i]; 177 if(processing[module]){ 178 throw new Error('Dependency error in ['+module+'] module!'); //出现环,不合理的模块依赖关系 179 } 180 if(isModuleLoaded(module) || included[module]){ 181 182 }else{ 183 var dependList=getDepend(module); 184 if(dependList.length){ 185 processing[module]=true; 186 resList=deepSearch(dependList); 187 result=result.concat(resList); 188 delete processing[module]; 189 } 190 result.push(module); 191 included[module]=true; 192 } 193 } 194 return result; 195 }; 196 /** 197 * @param {array} require list 198 * @return {string} script url 199 */ 200 var joinUrlByList = function(list){ 201 throw new Error('[loader] module needs your own joinUrlByList method!'); 202 }; 203 $L.addDepend = addDepend; 204 $L.addDepends = addDepends; 205 $L.addSheet = addSheet; 206 $L.addSheets = addSheets; 207 $L.joinUrlByList = joinUrlByList; 208 $L.featureDetect = null; 209 $L.markModuleLoaded = markModuleLoaded; 210 J.$require = $L.require = require; 211 });