-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathcold.js
461 lines (442 loc) · 11.4 KB
/
cold.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
//Cold.js
(function(){
//伪onload,在add函数中执行
var _onAdd = function(node, callback){
var old = node.callback;
node.callback = node.onerror = function(){
node.callback = node.onerror = null;
old && old();
callback && callback();
};
};
var _checkNs = function(ns){
if(!/^\s*Cold/.test(ns)) return 'Cold.' + ns;
return ns;
};
var _getUrl = function(ns){
var url = ns, debug = Cold.DEBUG ? '/src' : '/build';
if(!(/app|component|util|task|other/g.test(ns))){
url = ns.replace(/cold/i,'cold.core');
}
url = url.replace(/\./g,'/');
return Cold.BaseURL + url.replace(/cold/i, 'cold' + debug) + '.js';
};
var _checkReq = function(ns, req){
var i, l, cr = Cold.reqList;
ns = _checkNs(ns);
cr[ns] = cr[ns] || [];
//1.检查ns对应的reqList中是否同req重复
for(i=0, l=req.length; i<l; i++){
req[i] = _checkNs(req[i]);
_exist(cr[ns], req[i]) && req.splice(i, 1); //如果有,删掉对应的req
}
//2.检查req中是否同ns重复,如果有,删掉对应的req
var num = _exist(req, ns);
num && req.splice(num-1, 1); //如果有,删掉对应的req
//3.把ns及其reqList一起加到每个req对应的reqList中
for(i=0,l=req.length; i<l; i++){
cr[req[i]] = cr[req[i]] || [];
cr[req[i]].push(ns);
cr[req[i]] = cr[req[i]].concat(cr[ns]);
}
};
var _baseReplace = function(reqList){
var replace = false, cs = Cold.scripts;
if(reqList.length && cs['Cold.base'] && /loaded|loading/i.test(cs['Cold.base'])){
for(var i=0; i<reqList.length; i++){
if(/(Cold\.)?[browser|anim|ajax|event|dom|base]/i.test(reqList[i])){
reqList.splice(i--, 1);
replace = true;
}
}
replace && ( reqList[reqList.length] = 'Cold.base' );
}
};
var _exist = function(list, item){
if(list){
for(var i=0,l=list.length; i<l; i++){
if(list[i] === item)
return i+1;
}
}
return false;
};
window['Cold'] = {
/**
* 当前版本
* @type String
*/
VERSION: '0.0.1',
/**
* 调试模式(true调用未压缩版本并输出调试信息)
* @type Boolean
*/
DEBUG: true,
/**
* cold文件夹所在的路径
* @type String
*/
BaseURL: (function(){
var scripts = document.getElementsByTagName('script'),
str = scripts[scripts.length - 1].src,
re_base = /(.*)cold\/cold(-min)?\.js/i;
return (str.match(re_base) || window.location.href.match(re_base))[1];
})(),
/**
* 各种对象的缓存区,尚未好好利用
* @type Object
*/
cache: {},
/**
* 存储模块状态
* loadingN : 表示当前正在载入的模块数
* nodes : 存储模块所对应的script节点
* @type Object
*/
scripts: {
'loadingN': 0,
'nodes' : {}
},
/**
* 存储依赖关系
* @type Object
*/
reqList: {},
/**
* 扩展对象
* @type method
* @param {Object} obj 表示被扩展的对象
* @param {Object} exobj 扩展对象
* @param {Boolean} overwrite 是否复写同名属性
* @return {void}
*/
extend: function(obj, exobj, overwrite){
obj = obj || {};
exobj = exobj || {};
overwrite = overwrite || false;
for(var p in exobj){
if(overwrite){
obj[p] = exobj[p];
}
else{
if(!obj[p] && obj[p] !== false) obj[p] = exobj[p];
else continue;
}
}
return obj;
},
/**
* 模块定义
* @type method
* @param {String} namespace 模块名,模块命名空间
* @param {Array|Function} req 依赖模块表,或doFunc
* @param {Function} doFunc 模块执行函数,返回值用于扩展namespace对应的对象
× @example
* Cold.add('Cold.dom', ['Cold.browser'], function(){
* //...
* });
* @return Cold
*/
add: function(namespace, req, doFunc){
var ns = _checkNs(namespace),
names = ns.split('.'),
namesLen = names.length,
space = window,
cs = Cold.scripts,
node = cs.nodes[_getUrl(ns)];
var func = (function(f){
return function(){
if(f['done']) return; //此函数只执行一次
var obj = typeof f === 'function' && f();
if(obj != null) { //当add里的函数无返回值时,不在namespace上附加属性
if(!(names[0] in window)){
window[names[0]] = {};
}
for(var i = 0, n; i < namesLen; i++){
n = names[i];
if(i === namesLen - 1){
if(space[n]) Cold.extend(space[n], obj);
else space[n] = obj;
break;
}
(!space[n]) && ( space[n] = {} );
space = space[n];
}
}
node && node.callback && node.callback();
cs[ns] = 'attached';
f['done'] = true;
};
})(typeof req === 'function' ? req : doFunc);
//js file loaded
if(cs[ns]) cs[ns] = 'loaded';
if(typeof req !== 'function' && req.length > 0){
_checkReq(ns, req);
}
if(typeof req !== 'function' && req.length > 0){
return Cold.loadReq(req, func);
}
func();
return Cold;
},
/**
* 生成全局空间对象
* @type method
* @param {string} namespace 命名空间对象字符串
* @param {function} fn 生成的对象赋值
× @example
* Cold.namespace('obj.abc');
* @return Cold
*/
namespace : function(namespace, fn) {
var space = window, i, array = namespace.split('.');
for(i=0; i<array.length; i++) {
if(i == array.length - 1) {
space[array[i]] = fn;
return;
}
space[array[i]] = space[array[i]] || {};
space = space[array[i]];
}
return space;
},
/**
* 依赖于某些模块的执行代码,不需要等到domReady就可以执行
* @type method
* @param {Array|Function} req 依赖模块表,或doFunc
* @param {Function} doFunc 具体执行代码,不需要有返回值
× @example
* Cold.task(['dom', 'ajax'], function(){
* //...
* });
* @return Cold
*/
task: function(req, doFunc){
if(typeof req === 'function'){
req();
}
else if(req.length > 0){
return Cold.loadReq(req, doFunc);
}
else{
doFunc && doFunc();
}
return Cold;
},
loadReq : function(req, func){
_baseReplace(req);
var reqNum = req.length;
return Cold.load(req, function(){
--reqNum === 0 && func && func();
});
},
/**
* 动态载入js文件
* @type method
* @param {String} url js文件url
* @param {Function} onComplete 回调函数,伪回调,只有当js文件中有Cold.add函数时才会处理回调。因此不建议外部使用这个函数载入js文件
× @example
* Cold.addScript('http://someurl.com/cold/core/dom.js', function(){
* //...
* });
* @return Cold
*/
addScript: function(url, onComplete){
var s = document.createElement('script'),
head = document.getElementsByTagName('head')[0],
cs = Cold.scripts;
s.setAttribute('type', 'text/javascript');
s.setAttribute('src', url);
//for firefox 3.6
s.setAttribute('async', true);
head.appendChild(s);
_onAdd(s, function(){
onComplete && onComplete.call();
head.removeChild(s);
});
cs.nodes[url] = s;
return Cold;
},
/**
* 载入单个模块
* @type method
* @param {String} namespace 模块名
* @param {Function} callback 回调函数(放在对应script节点的callback属性中,由add函数进行调用)
* @return Cold
*/
loadSingle: function(namespace, callback){
var ns = _checkNs(namespace),
cs = Cold.scripts,
URL = _getUrl(ns),
node = cs.nodes[URL];
//当状态为attached时,依赖项已经存在,直接执行便可
if(cs[ns] === 'attached'){
typeof callback === 'function' && callback.call();
}
//通过缓存所有script节点,给正在载入的script添加onload事件
//从而避免了重复请求的问题,感谢kissy loader的方法
else if(cs[ns] === 'loading' || cs[ns] === 'loaded'){
node && _onAdd(node, function(){
callback && callback.call();
});
}
else{
cs[ns] = 'loading';
cs['loadingN']
? (cs['loadingN'] += 1)
: (cs['loadingN'] = 1);
Cold.addScript(URL, function(){
typeof callback === 'function' && callback();
cs[ns] = 'attached';
cs['loadingN'] -= 1;
});
}
return Cold;
},
/**
* 载入模块,可能是多个
* @type method
* @param {String|Array} ns 模块名
* @param {Function} callback 回调函数
* @return Cold
*/
load: function(ns, callback){
ns = ns || [];
if(typeof ns === 'string'){
return Cold.loadSingle(ns, callback);
}
else{
for(var i=0, len = ns.length; i<len; i++){
ns[i] && Cold.loadSingle(ns[i], function(){
typeof callback === 'function' && callback.call();
});
}
}
return Cold;
}
};
/**
* 输出调试信息,调用console.log;没有console对象时为空函数
* @type method
*/
Cold.log = ( Cold.DEBUG && window.console ) ? function(msg){ console.log(msg); } : function(){};
/* 用于保存某些数据 */
window['cold'] = {};
try{
document.domain = window.location.href.match(/http:\/\/(www\.)?([^\/]*)\//)[2];
document.execCommand("BackgroundImageCache", false, true);
}catch(e){}
})();
Cold.add('Cold', function(){
var funcList = [],
timer = null,
executed = false;
var _isComplete = function(){
return (Cold.scripts['loadingN'] === 0);
};
var _execReady = function(){
if(executed === true){
return;
}
executed = true;
for(var i=0, l=funcList.length; i < l; i++){
funcList[i](Cold);
}
funcList = [];
};
var _ColdReady = function(){
if(executed === true){
return;
}
if(_isComplete() === false){
timer = setTimeout(arguments.callee, 5);
return;
}
timer && clearTimeout(timer);
_execReady.call();
//Cold.scripts.nodes = {};
Cold.reqList = {};
};
var _readyBounded = (function(){
if(_readyBounded){
return;
}
var dscroll = document.documentElement.doScroll;
//w3c mode
if(document.addEventListener){
document.addEventListener('DOMContentLoaded', _ColdReady, false);
window.addEventListener('load', _ColdReady, false);
}
//ie mode
else{
document.attachEvent('onreadystatechange', _ColdReady);
window.attachEvent('onload', _ColdReady);
if(dscroll && window == window.top){
(function(){
try{
dscroll('left');
}
catch(ex){
setTimeout(arguments.callee, 0);
}
})();
}
}
return true;
})();
/**
* 定义dom ready且Cold对象Ready时执行的代码
* @type method
* @param {Function} func 执行函数
* @example
* Cold.ready(function(){ ... });
*/
var ready = function(func){
if(typeof func !== 'function'){
return;
}
if(executed === true || (/loaded|complete/).test(document.readyState.toLowerCase())){
func(Cold);
}
else{
funcList.push(func);
}
};
/**
* 用于对元素集合执行函数
* @type method
* @param {Function} func 执行函数
* @example
* Cold.each(items, function(item){ ... });
*/
var each = function(items, func){
if(!items.length) return;
for(var i=0, l=items.length; i<l; i++){
if(func.call(null, items[i], i) === false) return;
}
};
/**
* 对象包括四个函数isArray、isFunction、isString、isNumber,意义明确
* @type Object
*/
var type = {};
(function(){
var _toString = Object.prototype.toString;
var objTypes = ['Array', 'Function', 'String', 'Number'];
for(var i=0, l=objTypes.length; i<l; i++){
(function(i){
type["is" + objTypes[i]] = function(obj){
return _toString.call(obj) === '[object ' + objTypes[i] + ']';
};
})(i);
}
})();
return {
isArray : type.isArray,
isFunction : type.isFunction,
isString : type.isString,
isNumber : type.isNumber,
ready : ready,
each : each
};
});