1 /**
  2  * @fileOverview mix loader into S and infer KISSy baseUrl if not set
  3  * @author lifesinger@gmail.com,yiminghe@gmail.com
  4  */
  5 (function (S) {
  6 
  7     if (typeof require !== 'undefined') {
  8         return;
  9     }
 10 
 11     var Loader = S.Loader,
 12         utils = Loader.Utils,
 13         ComboLoader = S.Loader.Combo;
 14 
 15     S.mix(S,
 16         /**
 17          * @lends KISSY
 18          */
 19         {
 20             /**
 21              * Registers a module with the KISSY global.
 22              * @param {String} [name] module name.
 23              * it must be set if combine is true in {@link KISSY.config}
 24              * @param {Function} fn module definition function that is used to return
 25              * this module value
 26              * @param {KISSY} fn.S KISSY global instance
 27              * @param fn.x... this module's required modules' value
 28              * @param {Object} [cfg] module optional config data
 29              * @param {String[]} cfg.requires this module's required module name list
 30              * @example
 31              * // dom module's definition
 32              * <code>
 33              * KISSY.add("dom",function(S,UA){
 34              *  return { css:function(el,name,val){} };
 35              * },{
 36              *  requires:["ua"]
 37              * });
 38              * </code>
 39              */
 40             add:function (name, fn, cfg) {
 41                 this.getLoader().add(name, fn, cfg);
 42             },
 43             /**
 44              * Attached one or more modules to global KISSY instance.
 45              * @param {String|String[]} names moduleNames. 1-n modules to bind(use comma to separate)
 46              * @param {Function} callback callback function executed
 47              * when KISSY has the required functionality.
 48              * @param {KISSY} callback.S KISSY instance
 49              * @param callback.x... used module values
 50              * @example
 51              * // loads and attached overlay,dd and its dependencies
 52              * KISSY.use("overlay,dd",function(S,Overlay){});
 53              */
 54             use:function (names, callback) {
 55                 this.getLoader().use(names, callback);
 56             },
 57             /**
 58              * get KISSY's loader instance
 59              * @returns {KISSY.Loader}
 60              */
 61             getLoader:function () {
 62                 var self = this, env = self.Env;
 63                 if (self.Config.combine) {
 64                     return env._comboLoader;
 65                 } else {
 66                     return env._loader;
 67                 }
 68             },
 69             /**
 70              * get module value defined by define function
 71              * @param {string} moduleName
 72              * @private
 73              */
 74             require:function (moduleName) {
 75                 var self = this,
 76                     mods = self.Env.mods,
 77                     mod = mods[moduleName];
 78                 return mod && mod.value;
 79             }
 80         });
 81 
 82     function returnJson(s) {
 83         return (new Function("return " + s))();
 84     }
 85 
 86     /**
 87      * get base from seed/kissy.js
 88      * @return base for kissy
 89      * @private
 90      * @example
 91      * <pre>
 92      *   http://a.tbcdn.cn/s/kissy/1.1.6/??kissy-min.js,suggest/suggest-pkg-min.js
 93      *   http://a.tbcdn.cn/??s/kissy/1.1.6/kissy-min.js,s/kissy/1.1.5/suggest/suggest-pkg-min.js
 94      *   http://a.tbcdn.cn/??s/kissy/1.1.6/suggest/suggest-pkg-min.js,s/kissy/1.1.5/kissy-min.js
 95      *   http://a.tbcdn.cn/s/kissy/1.1.6/kissy-min.js?t=20101215.js
 96      *   note about custom combo rules, such as yui3:
 97      *   <script src="path/to/kissy" data-combo-prefix="combo?" data-combo-sep="&"></script>
 98      * <pre>
 99      */
100     function getBaseInfo() {
101         // get base from current script file path
102         // notice: timestamp
103         var baseReg = /^(.*)(seed|kissy)(-aio)?(-min)?\.js[^/]*/i,
104             baseTestReg = /(seed|kissy)(-aio)?(-min)?\.js/i,
105             scripts = S.Env.host.document.getElementsByTagName('script'),
106             script = scripts[scripts.length - 1],
107             src = utils.absoluteFilePath(script.src),
108             baseInfo = script.getAttribute("data-config");
109         if (baseInfo) {
110             baseInfo = returnJson(baseInfo);
111         } else {
112             baseInfo = {};
113         }
114         baseInfo.comboPrefix = baseInfo.comboPrefix || '??';
115         baseInfo.comboSep = baseInfo.comboSep || ',';
116 
117         var comboPrefix = baseInfo.comboPrefix,
118             comboSep = baseInfo.comboSep,
119             parts = src.split(comboSep),
120             base,
121             part0 = parts[0],
122             part01,
123             index = part0.indexOf(comboPrefix);
124 
125         // no combo
126         if (index == -1) {
127             base = src.replace(baseReg, '$1');
128         } else {
129             base = part0.substring(0, index);
130             part01 = part0.substring(index + 2, part0.length);
131             // combo first
132             // notice use match better than test
133             if (part01.match(baseTestReg)) {
134                 base += part01.replace(baseReg, '$1');
135             }
136             // combo after first
137             else {
138                 S.each(parts, function (part) {
139                     if (part.match(baseTestReg)) {
140                         base += part.replace(baseReg, '$1');
141                         return false;
142                     }
143                 });
144             }
145         }
146         return S.mix({
147             base:base
148         }, baseInfo);
149     }
150 
151     S.config(S.mix({
152         comboMaxUrlLength:1024,
153         charset:'utf-8',
154         tag:'@TIMESTAMP@'
155     }, getBaseInfo()));
156 
157     /**
158      * Initializes loader.
159      */
160     (function () {
161         var env = S.Env;
162         env.mods = env.mods || {}; // all added mods
163         env._loader = new Loader(S);
164         env._comboLoader = new ComboLoader(S);
165     })();
166 
167 })(KISSY);