1 /** 2 * @fileOverview simple loader from KISSY<=1.2 3 * @author yiminghe@gmail.com 4 */ 5 (function (S, undefined) { 6 7 if (typeof require !== 'undefined') { 8 return; 9 } 10 11 var Loader = S.Loader, 12 utils = Loader.Utils; 13 14 15 S.augment(Loader, 16 Loader.Target, 17 { 18 19 //firefox,ie9,chrome 如果add没有模块名,模块定义先暂存这里 20 __currentModule:null, 21 22 //ie6,7,8开始载入脚本的时间 23 __startLoadTime:0, 24 25 //ie6,7,8开始载入脚本对应的模块名 26 __startLoadModuleName:null, 27 28 /** 29 * Registers a module. 30 * @param {String|Object} [name] module name 31 * @param {Function|Object} [fn] entry point into the module that is used to bind module to KISSY 32 * @param {Object} [config] special config for this add 33 * @param {String[]} [config.requires] array of mod's name that current module requires 34 * @example 35 * <code> 36 * KISSY.add('module-name', function(S){ }, {requires: ['mod1']}); 37 * </code> 38 */ 39 add:function (name, fn, config) { 40 var self = this, 41 SS = self.SS, 42 mod, 43 requires, 44 mods = SS.Env.mods; 45 46 // 兼容 1.3.0pr1 47 if (S.isPlainObject(name)) { 48 return SS.config({ 49 modules:name 50 }); 51 } 52 53 // S.add(name[, fn[, config]]) 54 if (S.isString(name)) { 55 56 utils.registerModule(SS, name, fn, config); 57 58 mod = mods[name]; 59 60 // 显示指定 add 不 attach 61 if (config && config['attach'] === false) { 62 return; 63 } 64 65 if (config) { 66 requires = utils.normalizeModNames(SS, config.requires, name); 67 } 68 69 if (!requires || utils.isAttached(SS, requires)) { 70 utils.attachMod(SS, mod); 71 } 72 73 return; 74 } 75 // S.add(fn,config); 76 else if (S.isFunction(name)) { 77 config = fn; 78 fn = name; 79 if (utils.IE) { 80 /* 81 Kris Zyp 82 2010年10月21日, 上午11时34分 83 We actually had some discussions off-list, as it turns out the required 84 technique is a little different than described in this thread. Briefly, 85 to identify anonymous modules from scripts: 86 * In non-IE browsers, the onload event is sufficient, it always fires 87 immediately after the script is executed. 88 * In IE, if the script is in the cache, it actually executes *during* 89 the DOM insertion of the script tag, so you can keep track of which 90 script is being requested in case define() is called during the DOM 91 insertion. 92 * In IE, if the script is not in the cache, when define() is called you 93 can iterate through the script tags and the currently executing one will 94 have a script.readyState == "interactive" 95 See RequireJS source code if you need more hints. 96 Anyway, the bottom line from a spec perspective is that it is 97 implemented, it works, and it is possible. Hope that helps. 98 Kris 99 */ 100 // http://groups.google.com/group/commonjs/browse_thread/thread/5a3358ece35e688e/43145ceccfb1dc02#43145ceccfb1dc02 101 // use onload to get module name is not right in ie 102 name = findModuleNameByInteractive(self); 103 S.log("old_ie get modName by interactive : " + name); 104 utils.registerModule(SS, name, fn, config); 105 self.__startLoadModuleName = null; 106 self.__startLoadTime = 0; 107 } else { 108 // 其他浏览器 onload 时,关联模块名与模块定义 109 self.__currentModule = { 110 fn:fn, 111 config:config 112 }; 113 } 114 return; 115 } 116 S.log("invalid format for KISSY.add !", "error"); 117 } 118 }); 119 120 121 // ie 特有,找到当前正在交互的脚本,根据脚本名确定模块名 122 // 如果找不到,返回发送前那个脚本 123 function findModuleNameByInteractive(self) { 124 var SS = self.SS, 125 base, 126 scripts = S.Env.host.document.getElementsByTagName("script"), 127 re, 128 script; 129 130 for (var i = 0; i < scripts.length; i++) { 131 script = scripts[i]; 132 if (script.readyState == "interactive") { 133 re = script; 134 break; 135 } 136 } 137 if (!re) { 138 // sometimes when read module file from cache , interactive status is not triggered 139 // module code is executed right after inserting into dom 140 // i has to preserve module name before insert module script into dom , then get it back here 141 S.log("can not find interactive script,time diff : " + (+new Date() - self.__startLoadTime), "error"); 142 S.log("old_ie get modname from cache : " + self.__startLoadModuleName); 143 return self.__startLoadModuleName; 144 //S.error("找不到 interactive 状态的 script"); 145 } 146 147 // src 必定是绝对路径 148 // or re.hasAttribute ? re.src : re.getAttribute('src', 4); 149 // http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx 150 // note: 151 // <script src='/x.js'></script> 152 // ie6-8 => re.src == '/x.js' 153 // ie9 or firefox/chrome => re.src == 'http://localhost/x.js' 154 var src = utils.absoluteFilePath(re.src); 155 // 注意:模块名不包含后缀名以及参数,所以去除 156 // 系统模块去除系统路径 157 // 需要 base norm , 防止 base 被指定为相对路径 158 // configs 统一处理 159 // SS.Config.base = SS.normalBasePath(self.Config.base); 160 if (src.lastIndexOf(base = SS.Config.base, 0) === 0) { 161 return utils.removePostfix(src.substring(base.length)); 162 } 163 var packages = SS.Env.packages, 164 finalPackagePath, 165 finalPackageLength = -1; 166 // 外部模块去除包路径,得到模块名 167 for (var p in packages) { 168 if (packages.hasOwnProperty(p)) { 169 var packageBase = packages[p].base; 170 if (packages.hasOwnProperty(p) && 171 src.lastIndexOf(packageBase, 0) === 0) { 172 // longest match 173 if (packageBase.length > finalPackageLength) { 174 finalPackageLength = packageBase.length; 175 finalPackagePath = packageBase; 176 } 177 } 178 } 179 } 180 if (finalPackagePath) { 181 return utils.removePostfix(src.substring(finalPackagePath.length)); 182 } 183 S.log("interactive script does not have package config :" + src, "error"); 184 return undefined; 185 } 186 187 })(KISSY); 188 189 /** 190 * 2012-02-21 yiminghe@gmail.com refactor: 191 * 192 * 拆分 ComboLoader 与 Loader 193 * 194 * 2011-01-04 chengyu<yiminghe@gmail.com> refactor: 195 * 196 * adopt requirejs : 197 * 198 * 1. packages(cfg) , cfg :{ 199 * name : 包名,用于指定业务模块前缀 200 * path: 前缀包名对应的路径 201 * charset: 该包下所有文件的编码 202 * 203 * 2. add(moduleName,function(S,depModule){return function(){}},{requires:["depModuleName"]}); 204 * moduleName add 时可以不写 205 * depModuleName 可以写相对地址 (./ , ../),相对于 moduleName 206 * 207 * 3. S.use(["dom"],function(S,DOM){ 208 * }); 209 * 依赖注入,发生于 add 和 use 时期 210 * 211 * 4. add,use 不支持 css loader ,getScript 仍然保留支持 212 * 213 * 5. 部分更新模块文件代码 x/y?t=2011 ,加载过程中注意去除事件戳,仅在载入文件时使用 214 * 215 * demo : http://lite-ext.googlecode.com/svn/trunk/lite-ext/playground/module_package/index.html 216 * 217 * 2011-03-01 yiminghe@gmail.com note: 218 * 219 * compatibility 220 * 221 * 1. 保持兼容性,不得已而为之 222 * 支持 { host : } 223 * 如果 requires 都已经 attached,支持 add 后立即 attach 224 * 支持 { attach : false } 显示控制 add 时是否 attach 225 * 支持 { global : Editor } 指明模块来源 226 * 227 * 2011-05-04 初步拆分文件,tmd 乱了 228 */ 229