Ext原码学习之Ext.js
阅读原文时间:2023年07月11日阅读:2

1 // JavaScript Document
2 //定义全局Ext变量
3 var Ext = Ext ||{};
4 Ext._startTime = new Date().getTime();
5 (function(){
6 var global = this,
7 objectPrototype = Object.prototype,
8 toString = objectPrototype.toString,
9 //是否支持for循环可枚举
10 enumerables = true,
11 enumberablesTest = {toString:1},
12 //定义空函数
13 emptyFn = function(){},
14
15 //调用被子类覆盖的父方法
16 callOverrideParent = function(){
17 //返回方法调用者
18 var method = callOverrideParent.caller.caller;
19
20 //调用父类方法
21 return method.$owner.prototype[method.name].apply(this,arguments);
22 },
23 i,
24 nonWhitespaceRe = /\S/,
25 ExtApp,
26 iterableRe = /\[object\s*(?:Array|Arguments|\w*Collection|\w*List|Html\s+document\.all\s+class)\]/;
27
28 Function.prototype.$extIsFunciton = true,
29 Ext.global = global;
30
31 for(i in enumberablesTest)
32 {
33 enumberables = null;
34 }
35
36 if(enumberables)
37 {
38 enumberables = ['hasOwnProperty','valueOf','isPrototypeOf','propertyIsEnumberable','toLocaleString','toString','constructor'];
39 }
40
41 Ext.enumberables = enumberables;
42
43 //Ext 潜拷贝
44 Ext.apply = function(object,config,defaults)
45 {
46 if(defaults)
47 {
48 Ext.apply(object,defaults);
49 }
50
51 if(object && config && typeof config === 'object')
52 {
53 var i , j ,k;
54 for(i in config)
55 {
56 object[i] = config[i];
57 }
58
59 if(enumberables)
60 {
61 for(j=enumerables.length;j--;)
62 {
63 k = enumberables[j];
64 if(config.hasOwnProperty(k))
65 {
66 object[k] = config[k];
67 }
68 }
69 }
70 }
71
72 return object;
73
74 }
75
76 //设置css前缀
77 Ext.buildSettings = Ext.apply({
78 baseCSSPrefix : 'x-'
79 },Ext.buildSettings ||{});
80
81 //扩展Ext基本属性 name,emptyFn identifyFn,emptyString
82 Ext.apply(Ext,{
83
84 name:Ext.sandboxName || 'Ext',
85
86 emptyFn:emptyFn,
87
88 identifyFn:function(o){
89 return o;
90 },
91
92 //空字符串
93 emptyString:new String(),
94
95 baseCssPrefix:Ext.buildSettings.baseCSSPrefix,
96
97 //copy 若目标对象中没有此属性 则从原对象中复制属性
98 applyIf:function(object,config){
99 var property;
100
101 if(object){
102 for(property in config){
103 if(object[property] === undefined)
104 {
105 object[property] = config[property];
106 }
107 }
108 }
109
110 return object;
111 },
112
113 //test Ext.applyOf
114 //var aaa = {a:123},bbb={a:1,b:12};
115 //console.log(Ext.apply(aaa,bbb));
116 //console.log(Ext.applyIf(aaa,bbb));
117
118 //遍历 array or object
119 iterate:function(object,fn,scop)
120 {
121 if(Ext.isEmpty(object))
122 {
123 return;
124 }
125
126 if(scope === undefined)
127 {
128 scope = object;
129 }
130
131 //判断对象是否为Array
132 if(Ext.isIterator(object))
133 {
134 Ext.Array.each.call(Ext.Array,object,fn,scope);
135 }
136 else
137 {
138 Ext.Object.each.call(Ext.Object,object,fn,scope);
139 }
140
141 }
142
143 });
144
145
146 Ext.apply(Ext,{
147
148 //此方法已被Ext.define 代替
149 extend:(function(){
150 var objectConstructor = objectPrototype.constructor,
151 inlineOverrides = function(o){
152 for(var m in o){
153 if(o.hasOwnProperty(m))
154 {
155 this[m]=o[m];
156 }
157 }
158 };
159
160 return function(subclass,supperclass,overrides){
161 if(Ext.isObject(supperclass))
162 {
163 overrides = supperclass;
164 supperclass = subclass;
165 subclass = overrides.constructor != objectConstructor ? overrides.constructor:function(){
166 supperclass.apply(this,arguments);
167 }
168 }
169 if(!supperclass){
170 Ext.Error.raise({
171 sourceClass:'Ext',
172 sourceMethod:'extend',
173 msg:'页面未加载完成进行调用'
174 });
175 }
176
177 var F = function(){},
178 subclassProto,superclassProto = superclass.prototype;
179
180 F.prototype = supperclassProto;
181 subclassProto = subclass.prototype=new F();
182 subclass.supperclass = supperclassProto;
183
184 if(superclassProto.constructor === objectConstructor){
185 supperclassProto.constructor = supperclass;
186 }
187
188 subclass.override = function(overrides){
189 Ext.override(subclass,overrides);
190 };
191
192
193 subclassProto.override = inlineOverrides;
194
195 subclassProto.proto = subclassProto;
196
197 subclass.verride(overrides);
198
199 subclass.extend = function(o)
200 {
201 return Ext.extend(subclass,o);
202 }
203
204 return subclass;
205
206 }
207 })(),
208
209 override:function(target,overrides)
210 {
211 if(target.$isClass)
212 {
213 target.override(overrides);
214 }
215 else if(typeof target == 'function')
216 {
217 Ext.apply(target.prototype,overrides);
218 }
219 else
220 {
221 var owner = target.self,name,value;
222
223 if(owner && owner.$isClass)
224 {
225 for(name in overrides)
226 {
227 if(overrides.hasOwnProperty(name))
228 {
229 value = overrides[name];
230
231 if(typeof value == 'function')
232 {
233 if(owner.$className){
234 value.displayName = owner.$className +"#"+name;
235 }
236 value.$name = name;
237
238 value.$owner = owner;
239
240 value.$previous = target.hasOwnProperty(name)?target[name] : callOverrideParent;
241 }
242 target[name] = value;
243 }
244 }
245 }
246 else
247 {
248 Ext.apply(target,overrides);
249 }
250 }
251
252 return target;
253 }
254
255 });
256
257 //添加静态方法
258 Ext.apply(Ext,{
259
260 valueForm:function(value,defaultValue,allowBlank)
261 {
262 return Ext.isEmpay(value,allowBlank) ? defaultValue : value;
263 },
264
265 typeOf:function(value)
266 {
267 var type,typeToString;
268
269 if(value===null)
270 {
271 return 'null';
272 }
273
274 type = typeof value;
275
276 if(type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean')
277 {
278 return type;
279 }
280
281 typeToString = toString.call(value);
282
283 switch(typeToString)
284 {
285 case '[object Array]':
286 return 'array';
287 case '[object Date]':
288 return 'date';
289 case '[object Bollean]':
290 return 'boolean';
291 case '[object Number]':
292 return 'number';
293 case '[object RegExp]':
294 return 'regexp';
295 }
296
297 if(type === 'function')
298 {
299 return 'function';
300 }
301
302 if(type === 'object')
303 {
304 if(value.nodeType !== undefined)
305 {
306 if(value.nodeType === 3)
307 {
308 return (nonWhitespaceRe).test(value.nodeValue)?'textnode':'whitespace';
309 }
310 else
311 {
312 return 'element';
313 }
314 }
315
316 return 'object';
317 }
318 },
319 coerce:function(from,to)
320 {
321 var fromType = Ext.typeOf(from),
322 toType = Ext.typeOf(to),
323 isString = typeof from === 'string';
324
325 if(fromType !== toType)
326 {
327 switch(toType)
328 {
329 case 'string':
330 return String(from);
331 case 'number':
332 return Number(from);
333 case 'boolean':
334 return isString && (!from || from==='false') ? false :Boolean(from);
335 case 'null':
336 return isString && (!form || from=== 'null') ? null :from;
337 case 'undefined':
338 return isString && (!from || from==='undefinded')?'undefined':from;
339 case 'date':
340 return isString && isNaN(from) ? Ext.Date.parse(from,Ext.Date.defaultFormat):Date(Number(from));
341 }
342 }
343
344 return from;
345 },
346 //判断字符串是否为空,数组是否有数据
347 isEmpty:function(value,allowEmptyString)
348 {
349 return (value===null) || (value=== undefined) || (!allowEmptyString ? value==='' :false)||(Ext.isArray(value) && value.length===0);
350 },
351 //判断数组
352 isArray:('isArray' in Array) ? Array.isArray:function(value)
353 {
354 return toString.call(value) === '[object Array]';
355 },
356 isDate:function(value)
357 {
358 return Ext.typeOf(value) === 'date';
359 },
360 isObject:function(value)
361 {
362 return Ext.typeOf(value)=='object';
363 },
364 isSimpleObject:function(value)
365 {
366 return value instanceof Object && value.constructor === Object;
367 },
368 //判断基本数据类型,
369 isPrimitive:function(value)
370 {
371 var type = typeof value;
372 return type === 'string' || type==='number' || type ==='boolean';
373 },
374 isFunction:function(value)
375 {
376 return !!(value && value.$extIsFunction);
377 },
378 isNumber:function(value)
379 {
380 return typeof value ==='number' && isFinite(value);
381 },
382 isNumberic:function(value)
383 {
384 return !isNaN(parseFlost(value)) && isFinite(value);
385 },
386 isString:function(value)
387 {
388 return Ext.typeOf(value) ==='string';
389 },
390 isBoolean:function(value)
391 {
392 return Ext.typeOf(value) ==='boolean';
393 },
394 isElement:function(value)
395 {
396 return Ext.typeOf(value) === 'element';
397 },
398 isTextNode:function(value)
399 {
400 return Ext.typeOf(value) === 'textnode' || Ext.typeOf(value)==='whitespace'
401 },
402 isDefined:function(value)
403 {
404 return Ext.typeOf(value) !== 'undefined';
405 },
406 isIterable:function(value)
407 {
408 if(!value || typeof value.length !== 'number' || typeof value==='string' || value.$extIsFunction)
409 {
410 return false;
411 }
412
413 if(!value.propertyIsEnumberable)
414 {
415 return !!value.item;
416 }
417
418 if(value.hasOwnProperty('length') && !value.propertyIsEnumberable('length'))
419 {
420 return true;
421 }
422
423 return iterableRe.test(toString.call(value));
424 }
425
426 //console.log(Ext.isIterable(new Date()));
427 });
428
429
430 Ext.apply(Ext,{
431 clone:function(item)
432 {
433 var type,i,j,k,clone,key;
434 if(item === null || item === undefined)
435 {
436 return item;
437 }
438
439 //clone document element
440 if(item.nodeType && item.cloneNode)
441 {
442 return item.cloneNode(true);
443 }
444
445 type = Ext.typeOf(item);
446 if(type==='date')
447 {
448 return new Date(item.getTime());
449 }
450
451 if(type==='array')
452 {
453 i = item.length;
454 clone = [];
455 while(i--)
456 {
457 clone[i] = Ext.clone(item[i]);
458 }
459
460 }
461 else if(type==='object' && item.construcator === Object)
462 {
463 clone = {};
464 for(key in item)
465 {
466 clone[key] = Ext.clone(item[key]);
467 }
468
469 if(enumberables)
470 {
471 for(j=enumberables.length;j--;)
472 {
473 k = enumberables[j];
474 if(item.hasOwnProperty(k))
475 {
476 clone[k]=item[k];
477 }
478 }
479 }
480 }
481 return clone || item;
482
483 },
484 //生成唯一的命名空间
485 getUniqueGlobalNamespace :function(){
486 var uniqueGlobalNamespace = this.uniqueGlobalNamespace,i;
487 if(uniqueGlobalNamespace === undefined)
488 {
489 i = 0;
490
491 do{
492 uniqueGlobalNamespace = 'ExtBox'+(++i);
493 }while(Ext.global[uniqueGlobalNamespace]!==undefined);
494
495 Ext.global[uniqueGlobalNamespace]=Ext;
496
497 this.uniqueGlobalNamespace = uniqueGlobalNamespace;
498 }
499 return uniqueGlobalNamespace;
500 },
501 functionFactoryCache:{},
502 cacheableFunctionFactory:function(){
503 var me = this,args = Array.prototype.slice.call(arguments),
504 cache = me.functionFactoryCache,idx,fn,ln;
505
506 if(Ext.isSandboxed)
507 {
508 ln - args.length;
509 if(ln>0)
510 {
511 ln--;
512 args[ln]='var Ext=window.'+Ext.name+';'+args[ln];
513 }
514 }
515 idx = args.join('');
516 fn=cache[idx];
517
518 if(!fn)
519 {
520 fn = Function.prototype.constructor.apply(Function.prototype,args);
521 cache[idx]=fn;
522 }
523 return fn;
524 },
525 functionFactory:function(){
526 var me = this,args = Array.prototype.slice.call(arguments),ln;
527 if(Ext.isSandboxed)
528 {
529 ln = args.length;
530 if(ln >0 )
531 {
532 ln--;
533 args[ln] = 'var Ext = window.'+Ext.name +';'+args[ln];
534 }
535 }
536
537 return Function.prototype.constructor.apply(Function.prototype,args);
538 },
539 Logger:{
540 varbose:emptyFn,
541 log:emptyFn,
542 info:emptyFn,
543 warn:emptyFn,
544 error:function(message)
545 {
546 throw new Error(message);
547 },
548 deprecate:emptyFn
549
550 }
551 });
552
553 Ext.type = Ext.typeOf;
554
555 ExtApp = Ext.app;
556 if(!ExtApp)
557 {
558 ExtApp = Ext.app = {};
559 }
560
561 Ext.apply(ExtApp,{
562 namespaces:{},
563 collectNamespaces:function(paths)
564 {
565 var namespaces = Ext.app.namespaces,path;
566 for(path in paths)
567 {
568 if(paths.hasOwnProperty(path))
569 {
570 namespaces[path] = true;
571 }
572 }
573 },
574 addNamespaces:function(ns)
575 {
576 var namespaces = Ext.app.namespaces,i,l;
577 if(!Ext.isArray(ns))
578 {
579 ns = [ns];
580 }
581
582 for(i =0,l = ns.length;ideepestPrefix.length && (prefix+'.' === className.substring(0,prefix.length +1)))
597 {
598 deepestPrefix = prefix;
599 }
600 }
601
602 return deepestPrefix === '' ?undefined : deepestPrefix;
603 }
604 });
605
606 })()
607
608 Ext.globalEval = Ext.global.execScript ? function(code){
609 execScript(code);
610 }:function($$code)
611 {
612 (function(){
613 var Ext = this.Ext;
614 eval($$code);
615 })();
616 }
617
618 //test typeof
619 //var obj = {};
620 //console.log(typeof obj);
621
622
623
624
625
626
627