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