Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / ext-all-debug.js
1
2
3 (function() {
4     var global = this,
5         objectPrototype = Object.prototype,
6         toString = Object.prototype.toString,
7         enumerables = true,
8         enumerablesTest = { toString: 1 },
9         i;
10
11     if (typeof Ext === 'undefined') {
12         global.Ext = {};
13     }
14
15     Ext.global = global;
16
17     for (i in enumerablesTest) {
18         enumerables = null;
19     }
20
21     if (enumerables) {
22         enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable',
23                        'toLocaleString', 'toString', 'constructor'];
24     }
25
26     
27     Ext.enumerables = enumerables;
28
29     
30     Ext.apply = function(object, config, defaults) {
31         if (defaults) {
32             Ext.apply(object, defaults);
33         }
34
35         if (object && config && typeof config === 'object') {
36             var i, j, k;
37
38             for (i in config) {
39                 object[i] = config[i];
40             }
41
42             if (enumerables) {
43                 for (j = enumerables.length; j--;) {
44                     k = enumerables[j];
45                     if (config.hasOwnProperty(k)) {
46                         object[k] = config[k];
47                     }
48                 }
49             }
50         }
51
52         return object;
53     };
54
55     Ext.buildSettings = Ext.apply({
56         baseCSSPrefix: 'x-',
57         scopeResetCSS: false
58     }, Ext.buildSettings || {});
59
60     Ext.apply(Ext, {
61         
62         emptyFn: function() {},
63
64         baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,
65
66         
67         applyIf: function(object, config) {
68             var property;
69
70             if (object) {
71                 for (property in config) {
72                     if (object[property] === undefined) {
73                         object[property] = config[property];
74                     }
75                 }
76             }
77
78             return object;
79         },
80
81         
82         iterate: function(object, fn, scope) {
83             if (Ext.isEmpty(object)) {
84                 return;
85             }
86
87             if (scope === undefined) {
88                 scope = object;
89             }
90
91             if (Ext.isIterable(object)) {
92                 Ext.Array.each.call(Ext.Array, object, fn, scope);
93             }
94             else {
95                 Ext.Object.each.call(Ext.Object, object, fn, scope);
96             }
97         }
98     });
99
100     Ext.apply(Ext, {
101
102         
103         extend: function() {
104             
105             var objectConstructor = objectPrototype.constructor,
106                 inlineOverrides = function(o) {
107                 for (var m in o) {
108                     if (!o.hasOwnProperty(m)) {
109                         continue;
110                     }
111                     this[m] = o[m];
112                 }
113             };
114
115             return function(subclass, superclass, overrides) {
116                 
117                 if (Ext.isObject(superclass)) {
118                     overrides = superclass;
119                     superclass = subclass;
120                     subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
121                         superclass.apply(this, arguments);
122                     };
123                 }
124
125                 if (!superclass) {
126                     Ext.Error.raise({
127                         sourceClass: 'Ext',
128                         sourceMethod: 'extend',
129                         msg: 'Attempting to extend from a class which has not been loaded on the page.'
130                     });
131                 }
132
133                 
134                 var F = function() {},
135                     subclassProto, superclassProto = superclass.prototype;
136
137                 F.prototype = superclassProto;
138                 subclassProto = subclass.prototype = new F();
139                 subclassProto.constructor = subclass;
140                 subclass.superclass = superclassProto;
141
142                 if (superclassProto.constructor === objectConstructor) {
143                     superclassProto.constructor = superclass;
144                 }
145
146                 subclass.override = function(overrides) {
147                     Ext.override(subclass, overrides);
148                 };
149
150                 subclassProto.override = inlineOverrides;
151                 subclassProto.proto = subclassProto;
152
153                 subclass.override(overrides);
154                 subclass.extend = function(o) {
155                     return Ext.extend(subclass, o);
156                 };
157
158                 return subclass;
159             };
160         }(),
161
162         
163         override: function(cls, overrides) {
164             if (cls.prototype.$className) {
165                 return cls.override(overrides);
166             }
167             else {
168                 Ext.apply(cls.prototype, overrides);
169             }
170         }
171     });
172
173     
174     Ext.apply(Ext, {
175
176         
177         valueFrom: function(value, defaultValue, allowBlank){
178             return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
179         },
180
181         
182         typeOf: function(value) {
183             if (value === null) {
184                 return 'null';
185             }
186
187             var type = typeof value;
188
189             if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') {
190                 return type;
191             }
192
193             var typeToString = toString.call(value);
194
195             switch(typeToString) {
196                 case '[object Array]':
197                     return 'array';
198                 case '[object Date]':
199                     return 'date';
200                 case '[object Boolean]':
201                     return 'boolean';
202                 case '[object Number]':
203                     return 'number';
204                 case '[object RegExp]':
205                     return 'regexp';
206             }
207
208             if (type === 'function') {
209                 return 'function';
210             }
211
212             if (type === 'object') {
213                 if (value.nodeType !== undefined) {
214                     if (value.nodeType === 3) {
215                         return (/\S/).test(value.nodeValue) ? 'textnode' : 'whitespace';
216                     }
217                     else {
218                         return 'element';
219                     }
220                 }
221
222                 return 'object';
223             }
224
225             Ext.Error.raise({
226                 sourceClass: 'Ext',
227                 sourceMethod: 'typeOf',
228                 msg: 'Failed to determine the type of the specified value "' + value + '". This is most likely a bug.'
229             });
230         },
231
232         
233         isEmpty: function(value, allowEmptyString) {
234             return (value === null) || (value === undefined) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);
235         },
236
237         
238         isArray: ('isArray' in Array) ? Array.isArray : function(value) {
239             return toString.call(value) === '[object Array]';
240         },
241
242         
243         isDate: function(value) {
244             return toString.call(value) === '[object Date]';
245         },
246
247         
248         isObject: (toString.call(null) === '[object Object]') ?
249         function(value) {
250             return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.nodeType === undefined;
251         } :
252         function(value) {
253             return toString.call(value) === '[object Object]';
254         },
255
256         
257         isPrimitive: function(value) {
258             var type = typeof value;
259
260             return type === 'string' || type === 'number' || type === 'boolean';
261         },
262
263         
264         isFunction:
265         
266         
267         (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) {
268             return toString.call(value) === '[object Function]';
269         } : function(value) {
270             return typeof value === 'function';
271         },
272
273         
274         isNumber: function(value) {
275             return typeof value === 'number' && isFinite(value);
276         },
277
278         
279         isNumeric: function(value) {
280             return !isNaN(parseFloat(value)) && isFinite(value);
281         },
282
283         
284         isString: function(value) {
285             return typeof value === 'string';
286         },
287
288         
289         isBoolean: function(value) {
290             return typeof value === 'boolean';
291         },
292
293         
294         isElement: function(value) {
295             return value ? value.nodeType !== undefined : false;
296         },
297
298         
299         isTextNode: function(value) {
300             return value ? value.nodeName === "#text" : false;
301         },
302
303         
304         isDefined: function(value) {
305             return typeof value !== 'undefined';
306         },
307
308         
309         isIterable: function(value) {
310             return (value && typeof value !== 'string') ? value.length !== undefined : false;
311         }
312     });
313
314     Ext.apply(Ext, {
315
316         
317         clone: function(item) {
318             if (item === null || item === undefined) {
319                 return item;
320             }
321
322             
323             
324             
325             if (item.nodeType && item.cloneNode) {
326                 return item.cloneNode(true);
327             }
328
329             var type = toString.call(item);
330
331             
332             if (type === '[object Date]') {
333                 return new Date(item.getTime());
334             }
335
336             var i, j, k, clone, key;
337
338             
339             if (type === '[object Array]') {
340                 i = item.length;
341
342                 clone = [];
343
344                 while (i--) {
345                     clone[i] = Ext.clone(item[i]);
346                 }
347             }
348             
349             else if (type === '[object Object]' && item.constructor === Object) {
350                 clone = {};
351
352                 for (key in item) {
353                     clone[key] = Ext.clone(item[key]);
354                 }
355
356                 if (enumerables) {
357                     for (j = enumerables.length; j--;) {
358                         k = enumerables[j];
359                         clone[k] = item[k];
360                     }
361                 }
362             }
363
364             return clone || item;
365         },
366
367         
368         getUniqueGlobalNamespace: function() {
369             var uniqueGlobalNamespace = this.uniqueGlobalNamespace;
370
371             if (uniqueGlobalNamespace === undefined) {
372                 var i = 0;
373
374                 do {
375                     uniqueGlobalNamespace = 'ExtSandbox' + (++i);
376                 } while (Ext.global[uniqueGlobalNamespace] !== undefined);
377
378                 Ext.global[uniqueGlobalNamespace] = Ext;
379                 this.uniqueGlobalNamespace = uniqueGlobalNamespace;
380             }
381
382             return uniqueGlobalNamespace;
383         },
384
385         
386         functionFactory: function() {
387             var args = Array.prototype.slice.call(arguments);
388
389             if (args.length > 0) {
390                 args[args.length - 1] = 'var Ext=window.' + this.getUniqueGlobalNamespace() + ';' +
391                     args[args.length - 1];
392             }
393
394             return Function.prototype.constructor.apply(Function.prototype, args);
395         }
396     });
397
398     
399     Ext.type = Ext.typeOf;
400
401 })();
402
403
404 (function() {
405
406
407 var version = '4.0.0', Version;
408     Ext.Version = Version = Ext.extend(Object, {
409
410         
411         constructor: function(version) {
412             var parts, releaseStartIndex;
413
414             if (version instanceof Version) {
415                 return version;
416             }
417
418             this.version = this.shortVersion = String(version).toLowerCase().replace(/_/g, '.').replace(/[\-+]/g, '');
419
420             releaseStartIndex = this.version.search(/([^\d\.])/);
421
422             if (releaseStartIndex !== -1) {
423                 this.release = this.version.substr(releaseStartIndex, version.length);
424                 this.shortVersion = this.version.substr(0, releaseStartIndex);
425             }
426
427             this.shortVersion = this.shortVersion.replace(/[^\d]/g, '');
428
429             parts = this.version.split('.');
430
431             this.major = parseInt(parts.shift() || 0, 10);
432             this.minor = parseInt(parts.shift() || 0, 10);
433             this.patch = parseInt(parts.shift() || 0, 10);
434             this.build = parseInt(parts.shift() || 0, 10);
435
436             return this;
437         },
438
439         
440         toString: function() {
441             return this.version;
442         },
443
444         
445         valueOf: function() {
446             return this.version;
447         },
448
449         
450         getMajor: function() {
451             return this.major || 0;
452         },
453
454         
455         getMinor: function() {
456             return this.minor || 0;
457         },
458
459         
460         getPatch: function() {
461             return this.patch || 0;
462         },
463
464         
465         getBuild: function() {
466             return this.build || 0;
467         },
468
469         
470         getRelease: function() {
471             return this.release || '';
472         },
473
474         
475         isGreaterThan: function(target) {
476             return Version.compare(this.version, target) === 1;
477         },
478
479         
480         isLessThan: function(target) {
481             return Version.compare(this.version, target) === -1;
482         },
483
484         
485         equals: function(target) {
486             return Version.compare(this.version, target) === 0;
487         },
488
489         
490         match: function(target) {
491             target = String(target);
492             return this.version.substr(0, target.length) === target;
493         },
494
495         
496         toArray: function() {
497             return [this.getMajor(), this.getMinor(), this.getPatch(), this.getBuild(), this.getRelease()];
498         },
499
500         
501         getShortVersion: function() {
502             return this.shortVersion;
503         }
504     });
505
506     Ext.apply(Version, {
507         
508         releaseValueMap: {
509             'dev': -6,
510             'alpha': -5,
511             'a': -5,
512             'beta': -4,
513             'b': -4,
514             'rc': -3,
515             '#': -2,
516             'p': -1,
517             'pl': -1
518         },
519
520         
521         getComponentValue: function(value) {
522             return !value ? 0 : (isNaN(value) ? this.releaseValueMap[value] || value : parseInt(value, 10));
523         },
524
525         
526         compare: function(current, target) {
527             var currentValue, targetValue, i;
528
529             current = new Version(current).toArray();
530             target = new Version(target).toArray();
531
532             for (i = 0; i < Math.max(current.length, target.length); i++) {
533                 currentValue = this.getComponentValue(current[i]);
534                 targetValue = this.getComponentValue(target[i]);
535
536                 if (currentValue < targetValue) {
537                     return -1;
538                 } else if (currentValue > targetValue) {
539                     return 1;
540                 }
541             }
542
543             return 0;
544         }
545     });
546
547     Ext.apply(Ext, {
548         
549         versions: {},
550
551         
552         lastRegisteredVersion: null,
553
554         
555         setVersion: function(packageName, version) {
556             Ext.versions[packageName] = new Version(version);
557             Ext.lastRegisteredVersion = Ext.versions[packageName];
558
559             return this;
560         },
561
562         
563         getVersion: function(packageName) {
564             if (packageName === undefined) {
565                 return Ext.lastRegisteredVersion;
566             }
567
568             return Ext.versions[packageName];
569         },
570
571         
572         deprecate: function(packageName, since, closure, scope) {
573             if (Version.compare(Ext.getVersion(packageName), since) < 1) {
574                 closure.call(scope);
575             }
576         }
577     }); 
578
579     Ext.setVersion('core', version);
580
581 })();
582
583
584
585 Ext.String = {
586     trimRegex: /^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g,
587     escapeRe: /('|\\)/g,
588     formatRe: /\{(\d+)\}/g,
589     escapeRegexRe: /([-.*+?^${}()|[\]\/\\])/g,
590
591     /**
592      * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
593      * @param {String} value The string to encode
594      * @return {String} The encoded text
595      */
596     htmlEncode: (function() {
597         var entities = {
598             '&': '&amp;',
599             '>': '&gt;',
600             '<': '&lt;',
601             '"': '&quot;'
602         }, keys = [], p, regex;
603         
604         for (p in entities) {
605             keys.push(p);
606         }
607         
608         regex = new RegExp('(' + keys.join('|') + ')', 'g');
609         
610         return function(value) {
611             return (!value) ? value : String(value).replace(regex, function(match, capture) {
612                 return entities[capture];    
613             });
614         };
615     })(),
616
617     
618     htmlDecode: (function() {
619         var entities = {
620             '&amp;': '&',
621             '&gt;': '>',
622             '&lt;': '<',
623             '&quot;': '"'
624         }, keys = [], p, regex;
625         
626         for (p in entities) {
627             keys.push(p);
628         }
629         
630         regex = new RegExp('(' + keys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
631         
632         return function(value) {
633             return (!value) ? value : String(value).replace(regex, function(match, capture) {
634                 if (capture in entities) {
635                     return entities[capture];
636                 } else {
637                     return String.fromCharCode(parseInt(capture.substr(2), 10));
638                 }
639             });
640         };
641     })(),
642
643     
644     urlAppend : function(url, string) {
645         if (!Ext.isEmpty(string)) {
646             return url + (url.indexOf('?') === -1 ? '?' : '&') + string;
647         }
648
649         return url;
650     },
651
652     
653     trim: function(string) {
654         return string.replace(Ext.String.trimRegex, "");
655     },
656
657     
658     capitalize: function(string) {
659         return string.charAt(0).toUpperCase() + string.substr(1);
660     },
661
662     
663     ellipsis: function(value, len, word) {
664         if (value && value.length > len) {
665             if (word) {
666                 var vs = value.substr(0, len - 2),
667                 index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
668                 if (index !== -1 && index >= (len - 15)) {
669                     return vs.substr(0, index) + "...";
670                 }
671             }
672             return value.substr(0, len - 3) + "...";
673         }
674         return value;
675     },
676
677     
678     escapeRegex: function(string) {
679         return string.replace(Ext.String.escapeRegexRe, "\\$1");
680     },
681
682     
683     escape: function(string) {
684         return string.replace(Ext.String.escapeRe, "\\$1");
685     },
686
687     
688     toggle: function(string, value, other) {
689         return string === value ? other : value;
690     },
691
692     
693     leftPad: function(string, size, character) {
694         var result = String(string);
695         character = character || " ";
696         while (result.length < size) {
697             result = character + result;
698         }
699         return result;
700     },
701
702     
703     format: function(format) {
704         var args = Ext.Array.toArray(arguments, 1);
705         return format.replace(Ext.String.formatRe, function(m, i) {
706             return args[i];
707         });
708     }
709 };
710
711
712
713 (function() {
714
715 var isToFixedBroken = (0.9).toFixed() !== '1';
716
717 Ext.Number = {
718     
719     constrain: function(number, min, max) {
720         number = parseFloat(number);
721
722         if (!isNaN(min)) {
723             number = Math.max(number, min);
724         }
725         if (!isNaN(max)) {
726             number = Math.min(number, max);
727         }
728         return number;
729     },
730
731     
732     toFixed: function(value, precision) {
733         if (isToFixedBroken) {
734             precision = precision || 0;
735             var pow = Math.pow(10, precision);
736             return (Math.round(value * pow) / pow).toFixed(precision);
737         }
738
739         return value.toFixed(precision);
740     },
741
742     
743     from: function(value, defaultValue) {
744         if (isFinite(value)) {
745             value = parseFloat(value);
746         }
747
748         return !isNaN(value) ? value : defaultValue;
749     }
750 };
751
752 })();
753
754
755 Ext.num = function() {
756     return Ext.Number.from.apply(this, arguments);
757 };
758
759 (function() {
760
761     var arrayPrototype = Array.prototype,
762         slice = arrayPrototype.slice,
763         supportsForEach = 'forEach' in arrayPrototype,
764         supportsMap = 'map' in arrayPrototype,
765         supportsIndexOf = 'indexOf' in arrayPrototype,
766         supportsEvery = 'every' in arrayPrototype,
767         supportsSome = 'some' in arrayPrototype,
768         supportsFilter = 'filter' in arrayPrototype,
769         supportsSort = function() {
770             var a = [1,2,3,4,5].sort(function(){ return 0; });
771             return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
772         }(),
773         supportsSliceOnNodeList = true,
774         ExtArray;
775     try {
776         
777         if (typeof document !== 'undefined') {
778             slice.call(document.getElementsByTagName('body'));
779         }
780     } catch (e) {
781         supportsSliceOnNodeList = false;
782     }
783
784     ExtArray = Ext.Array = {
785         
786         each: function(array, fn, scope, reverse) {
787             array = ExtArray.from(array);
788
789             var i,
790                 ln = array.length;
791
792             if (reverse !== true) {
793                 for (i = 0; i < ln; i++) {
794                     if (fn.call(scope || array[i], array[i], i, array) === false) {
795                         return i;
796                     }
797                 }
798             }
799             else {
800                 for (i = ln - 1; i > -1; i--) {
801                     if (fn.call(scope || array[i], array[i], i, array) === false) {
802                         return i;
803                     }
804                 }
805             }
806
807             return true;
808         },
809
810         
811         forEach: function(array, fn, scope) {
812             if (supportsForEach) {
813                 return array.forEach(fn, scope);
814             }
815
816             var i = 0,
817                 ln = array.length;
818
819             for (; i < ln; i++) {
820                 fn.call(scope, array[i], i, array);
821             }
822         },
823
824         
825         indexOf: function(array, item, from) {
826             if (supportsIndexOf) {
827                 return array.indexOf(item, from);
828             }
829
830             var i, length = array.length;
831
832             for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {
833                 if (array[i] === item) {
834                     return i;
835                 }
836             }
837
838             return -1;
839         },
840
841         
842         contains: function(array, item) {
843             if (supportsIndexOf) {
844                 return array.indexOf(item) !== -1;
845             }
846
847             var i, ln;
848
849             for (i = 0, ln = array.length; i < ln; i++) {
850                 if (array[i] === item) {
851                     return true;
852                 }
853             }
854
855             return false;
856         },
857
858         
859         toArray: function(iterable, start, end){
860             if (!iterable || !iterable.length) {
861                 return [];
862             }
863
864             if (typeof iterable === 'string') {
865                 iterable = iterable.split('');
866             }
867
868             if (supportsSliceOnNodeList) {
869                 return slice.call(iterable, start || 0, end || iterable.length);
870             }
871
872             var array = [],
873                 i;
874
875             start = start || 0;
876             end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;
877
878             for (i = start; i < end; i++) {
879                 array.push(iterable[i]);
880             }
881
882             return array;
883         },
884
885         
886         pluck: function(array, propertyName) {
887             var ret = [],
888                 i, ln, item;
889
890             for (i = 0, ln = array.length; i < ln; i++) {
891                 item = array[i];
892
893                 ret.push(item[propertyName]);
894             }
895
896             return ret;
897         },
898
899         
900         map: function(array, fn, scope) {
901             if (supportsMap) {
902                 return array.map(fn, scope);
903             }
904
905             var results = [],
906                 i = 0,
907                 len = array.length;
908
909             for (; i < len; i++) {
910                 results[i] = fn.call(scope, array[i], i, array);
911             }
912
913             return results;
914         },
915
916         
917         every: function(array, fn, scope) {
918             if (!fn) {
919                 Ext.Error.raise('Ext.Array.every must have a callback function passed as second argument.');
920             }
921             if (supportsEvery) {
922                 return array.every(fn, scope);
923             }
924
925             var i = 0,
926                 ln = array.length;
927
928             for (; i < ln; ++i) {
929                 if (!fn.call(scope, array[i], i, array)) {
930                     return false;
931                 }
932             }
933
934             return true;
935         },
936
937         
938         some: function(array, fn, scope) {
939             if (!fn) {
940                 Ext.Error.raise('Ext.Array.some must have a callback function passed as second argument.');
941             }
942             if (supportsSome) {
943                 return array.some(fn, scope);
944             }
945
946             var i = 0,
947                 ln = array.length;
948
949             for (; i < ln; ++i) {
950                 if (fn.call(scope, array[i], i, array)) {
951                     return true;
952                 }
953             }
954
955             return false;
956         },
957
958         
959         clean: function(array) {
960             var results = [],
961                 i = 0,
962                 ln = array.length,
963                 item;
964
965             for (; i < ln; i++) {
966                 item = array[i];
967
968                 if (!Ext.isEmpty(item)) {
969                     results.push(item);
970                 }
971             }
972
973             return results;
974         },
975
976         
977         unique: function(array) {
978             var clone = [],
979                 i = 0,
980                 ln = array.length,
981                 item;
982
983             for (; i < ln; i++) {
984                 item = array[i];
985
986                 if (ExtArray.indexOf(clone, item) === -1) {
987                     clone.push(item);
988                 }
989             }
990
991             return clone;
992         },
993
994         
995         filter: function(array, fn, scope) {
996             if (supportsFilter) {
997                 return array.filter(fn, scope);
998             }
999
1000             var results = [],
1001                 i = 0,
1002                 ln = array.length;
1003
1004             for (; i < ln; i++) {
1005                 if (fn.call(scope, array[i], i, array)) {
1006                     results.push(array[i]);
1007                 }
1008             }
1009
1010             return results;
1011         },
1012
1013         
1014         from: function(value, newReference) {
1015             if (value === undefined || value === null) {
1016                 return [];
1017             }
1018
1019             if (Ext.isArray(value)) {
1020                 return (newReference) ? slice.call(value) : value;
1021             }
1022
1023             if (value && value.length !== undefined && typeof value !== 'string') {
1024                 return Ext.toArray(value);
1025             }
1026
1027             return [value];
1028         },
1029
1030         
1031         remove: function(array, item) {
1032             var index = ExtArray.indexOf(array, item);
1033
1034             if (index !== -1) {
1035                 array.splice(index, 1);
1036             }
1037
1038             return array;
1039         },
1040
1041         
1042         include: function(array, item) {
1043             if (!ExtArray.contains(array, item)) {
1044                 array.push(item);
1045             }
1046         },
1047
1048         
1049         clone: function(array) {
1050             return slice.call(array);
1051         },
1052
1053         
1054         merge: function() {
1055             var args = slice.call(arguments),
1056                 array = [],
1057                 i, ln;
1058
1059             for (i = 0, ln = args.length; i < ln; i++) {
1060                 array = array.concat(args[i]);
1061             }
1062
1063             return ExtArray.unique(array);
1064         },
1065
1066         
1067         intersect: function() {
1068             var intersect = [],
1069                 arrays = slice.call(arguments),
1070                 i, j, k, minArray, array, x, y, ln, arraysLn, arrayLn;
1071
1072             if (!arrays.length) {
1073                 return intersect;
1074             }
1075
1076             
1077             for (i = x = 0,ln = arrays.length; i < ln,array = arrays[i]; i++) {
1078                 if (!minArray || array.length < minArray.length) {
1079                     minArray = array;
1080                     x = i;
1081                 }
1082             }
1083
1084             minArray = Ext.Array.unique(minArray);
1085             arrays.splice(x, 1);
1086
1087             
1088             
1089             
1090             for (i = 0,ln = minArray.length; i < ln,x = minArray[i]; i++) {
1091                 var count = 0;
1092
1093                 for (j = 0,arraysLn = arrays.length; j < arraysLn,array = arrays[j]; j++) {
1094                     for (k = 0,arrayLn = array.length; k < arrayLn,y = array[k]; k++) {
1095                         if (x === y) {
1096                             count++;
1097                             break;
1098                         }
1099                     }
1100                 }
1101
1102                 if (count === arraysLn) {
1103                     intersect.push(x);
1104                 }
1105             }
1106
1107             return intersect;
1108         },
1109
1110         
1111         difference: function(arrayA, arrayB) {
1112             var clone = slice.call(arrayA),
1113                 ln = clone.length,
1114                 i, j, lnB;
1115
1116             for (i = 0,lnB = arrayB.length; i < lnB; i++) {
1117                 for (j = 0; j < ln; j++) {
1118                     if (clone[j] === arrayB[i]) {
1119                         clone.splice(j, 1);
1120                         j--;
1121                         ln--;
1122                     }
1123                 }
1124             }
1125
1126             return clone;
1127         },
1128
1129         
1130         sort: function(array, sortFn) {
1131             if (supportsSort) {
1132                 if (sortFn) {
1133                     return array.sort(sortFn);
1134                 } else {
1135                     return array.sort();
1136                 }
1137             }
1138
1139             var length = array.length,
1140                 i = 0,
1141                 comparison,
1142                 j, min, tmp;
1143
1144             for (; i < length; i++) {
1145                 min = i;
1146                 for (j = i + 1; j < length; j++) {
1147                     if (sortFn) {
1148                         comparison = sortFn(array[j], array[min]);
1149                         if (comparison < 0) {
1150                             min = j;
1151                         }
1152                     } else if (array[j] < array[min]) {
1153                         min = j;
1154                     }
1155                 }
1156                 if (min !== i) {
1157                     tmp = array[i];
1158                     array[i] = array[min];
1159                     array[min] = tmp;
1160                 }
1161             }
1162
1163             return array;
1164         },
1165
1166         
1167         flatten: function(array) {
1168             var worker = [];
1169
1170             function rFlatten(a) {
1171                 var i, ln, v;
1172
1173                 for (i = 0, ln = a.length; i < ln; i++) {
1174                     v = a[i];
1175
1176                     if (Ext.isArray(v)) {
1177                         rFlatten(v);
1178                     } else {
1179                         worker.push(v);
1180                     }
1181                 }
1182
1183                 return worker;
1184             }
1185
1186             return rFlatten(array);
1187         },
1188
1189         
1190         min: function(array, comparisonFn) {
1191             var min = array[0],
1192                 i, ln, item;
1193
1194             for (i = 0, ln = array.length; i < ln; i++) {
1195                 item = array[i];
1196
1197                 if (comparisonFn) {
1198                     if (comparisonFn(min, item) === 1) {
1199                         min = item;
1200                     }
1201                 }
1202                 else {
1203                     if (item < min) {
1204                         min = item;
1205                     }
1206                 }
1207             }
1208
1209             return min;
1210         },
1211
1212         
1213         max: function(array, comparisonFn) {
1214             var max = array[0],
1215                 i, ln, item;
1216
1217             for (i = 0, ln = array.length; i < ln; i++) {
1218                 item = array[i];
1219
1220                 if (comparisonFn) {
1221                     if (comparisonFn(max, item) === -1) {
1222                         max = item;
1223                     }
1224                 }
1225                 else {
1226                     if (item > max) {
1227                         max = item;
1228                     }
1229                 }
1230             }
1231
1232             return max;
1233         },
1234
1235         
1236         mean: function(array) {
1237             return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;
1238         },
1239
1240         
1241         sum: function(array) {
1242             var sum = 0,
1243                 i, ln, item;
1244
1245             for (i = 0,ln = array.length; i < ln; i++) {
1246                 item = array[i];
1247
1248                 sum += item;
1249             }
1250
1251             return sum;
1252         }
1253
1254     };
1255
1256     
1257     Ext.each = Ext.Array.each;
1258
1259     
1260     Ext.Array.union = Ext.Array.merge;
1261
1262     
1263     Ext.min = Ext.Array.min;
1264
1265     
1266     Ext.max = Ext.Array.max;
1267
1268     
1269     Ext.sum = Ext.Array.sum;
1270
1271     
1272     Ext.mean = Ext.Array.mean;
1273
1274     
1275     Ext.flatten = Ext.Array.flatten;
1276
1277     
1278     Ext.clean = Ext.Array.clean;
1279
1280     
1281     Ext.unique = Ext.Array.unique;
1282
1283     
1284     Ext.pluck = Ext.Array.pluck;
1285
1286     
1287     Ext.toArray = function() {
1288         return ExtArray.toArray.apply(ExtArray, arguments);
1289     }
1290 })();
1291
1292
1293
1294 Ext.Function = {
1295
1296     
1297     flexSetter: function(fn) {
1298         return function(a, b) {
1299             var k, i;
1300
1301             if (a === null) {
1302                 return this;
1303             }
1304
1305             if (typeof a !== 'string') {
1306                 for (k in a) {
1307                     if (a.hasOwnProperty(k)) {
1308                         fn.call(this, k, a[k]);
1309                     }
1310                 }
1311
1312                 if (Ext.enumerables) {
1313                     for (i = Ext.enumerables.length; i--;) {
1314                         k = Ext.enumerables[i];
1315                         if (a.hasOwnProperty(k)) {
1316                             fn.call(this, k, a[k]);
1317                         }
1318                     }
1319                 }
1320             } else {
1321                 fn.call(this, a, b);
1322             }
1323
1324             return this;
1325         };
1326     },
1327
1328    
1329     bind: function(fn, scope, args, appendArgs) {
1330         var method = fn,
1331             applyArgs;
1332
1333         return function() {
1334             var callArgs = args || arguments;
1335
1336             if (appendArgs === true) {
1337                 callArgs = Array.prototype.slice.call(arguments, 0);
1338                 callArgs = callArgs.concat(args);
1339             }
1340             else if (Ext.isNumber(appendArgs)) {
1341                 callArgs = Array.prototype.slice.call(arguments, 0); 
1342                 applyArgs = [appendArgs, 0].concat(args); 
1343                 Array.prototype.splice.apply(callArgs, applyArgs); 
1344             }
1345
1346             return method.apply(scope || window, callArgs);
1347         };
1348     },
1349
1350     
1351     pass: function(fn, args, scope) {
1352         if (args) {
1353             args = Ext.Array.from(args);
1354         }
1355
1356         return function() {
1357             return fn.apply(scope, args.concat(Ext.Array.toArray(arguments)));
1358         };
1359     },
1360
1361     
1362     alias: function(object, methodName) {
1363         return function() {
1364             return object[methodName].apply(object, arguments);
1365         };
1366     },
1367
1368     
1369     createInterceptor: function(origFn, newFn, scope, returnValue) {
1370         var method = origFn;
1371         if (!Ext.isFunction(newFn)) {
1372             return origFn;
1373         }
1374         else {
1375             return function() {
1376                 var me = this,
1377                     args = arguments;
1378                 newFn.target = me;
1379                 newFn.method = origFn;
1380                 return (newFn.apply(scope || me || window, args) !== false) ? origFn.apply(me || window, args) : returnValue || null;
1381             };
1382         }
1383     },
1384
1385     
1386     createDelayed: function(fn, delay, scope, args, appendArgs) {
1387         if (scope || args) {
1388             fn = Ext.Function.bind(fn, scope, args, appendArgs);
1389         }
1390         return function() {
1391             var me = this;
1392             setTimeout(function() {
1393                 fn.apply(me, arguments);
1394             }, delay);
1395         };
1396     },
1397
1398     
1399     defer: function(fn, millis, obj, args, appendArgs) {
1400         fn = Ext.Function.bind(fn, obj, args, appendArgs);
1401         if (millis > 0) {
1402             return setTimeout(fn, millis);
1403         }
1404         fn();
1405         return 0;
1406     },
1407
1408     
1409     createSequence: function(origFn, newFn, scope) {
1410         if (!Ext.isFunction(newFn)) {
1411             return origFn;
1412         }
1413         else {
1414             return function() {
1415                 var retval = origFn.apply(this || window, arguments);
1416                 newFn.apply(scope || this || window, arguments);
1417                 return retval;
1418             };
1419         }
1420     },
1421
1422     
1423     createBuffered: function(fn, buffer, scope, args) {
1424         return function(){
1425             var timerId;
1426             return function() {
1427                 var me = this;
1428                 if (timerId) {
1429                     clearInterval(timerId);
1430                     timerId = null;
1431                 }
1432                 timerId = setTimeout(function(){
1433                     fn.apply(scope || me, args || arguments);
1434                 }, buffer);
1435             };
1436         }();
1437     },
1438
1439     
1440     createThrottled: function(fn, interval, scope) {
1441         var lastCallTime, elapsed, lastArgs, timer, execute = function() {
1442             fn.apply(scope || this, lastArgs);
1443             lastCallTime = new Date().getTime();
1444         };
1445
1446         return function() {
1447             elapsed = new Date().getTime() - lastCallTime;
1448             lastArgs = arguments;
1449
1450             clearTimeout(timer);
1451             if (!lastCallTime || (elapsed >= interval)) {
1452                 execute();
1453             } else {
1454                 timer = setTimeout(execute, interval - elapsed);
1455             }
1456         };
1457     }
1458 };
1459
1460
1461 Ext.defer = Ext.Function.alias(Ext.Function, 'defer');
1462
1463
1464 Ext.pass = Ext.Function.alias(Ext.Function, 'pass');
1465
1466
1467 Ext.bind = Ext.Function.alias(Ext.Function, 'bind');
1468
1469
1470
1471 (function() {
1472
1473 var ExtObject = Ext.Object = {
1474
1475     
1476     toQueryObjects: function(name, value, recursive) {
1477         var self = ExtObject.toQueryObjects,
1478             objects = [],
1479             i, ln;
1480
1481         if (Ext.isArray(value)) {
1482             for (i = 0, ln = value.length; i < ln; i++) {
1483                 if (recursive) {
1484                     objects = objects.concat(self(name + '[' + i + ']', value[i], true));
1485                 }
1486                 else {
1487                     objects.push({
1488                         name: name,
1489                         value: value[i]
1490                     });
1491                 }
1492             }
1493         }
1494         else if (Ext.isObject(value)) {
1495             for (i in value) {
1496                 if (value.hasOwnProperty(i)) {
1497                     if (recursive) {
1498                         objects = objects.concat(self(name + '[' + i + ']', value[i], true));
1499                     }
1500                     else {
1501                         objects.push({
1502                             name: name,
1503                             value: value[i]
1504                         });
1505                     }
1506                 }
1507             }
1508         }
1509         else {
1510             objects.push({
1511                 name: name,
1512                 value: value
1513             });
1514         }
1515
1516         return objects;
1517     },
1518
1519     
1520     toQueryString: function(object, recursive) {
1521         var paramObjects = [],
1522             params = [],
1523             i, j, ln, paramObject, value;
1524
1525         for (i in object) {
1526             if (object.hasOwnProperty(i)) {
1527                 paramObjects = paramObjects.concat(ExtObject.toQueryObjects(i, object[i], recursive));
1528             }
1529         }
1530
1531         for (j = 0, ln = paramObjects.length; j < ln; j++) {
1532             paramObject = paramObjects[j];
1533             value = paramObject.value;
1534
1535             if (Ext.isEmpty(value)) {
1536                 value = '';
1537             }
1538             else if (Ext.isDate(value)) {
1539                 value = Ext.Date.toString(value);
1540             }
1541
1542             params.push(encodeURIComponent(paramObject.name) + '=' + encodeURIComponent(String(value)));
1543         }
1544
1545         return params.join('&');
1546     },
1547
1548     
1549     fromQueryString: function(queryString, recursive) {
1550         var parts = queryString.replace(/^\?/, '').split('&'),
1551             object = {},
1552             temp, components, name, value, i, ln,
1553             part, j, subLn, matchedKeys, matchedName,
1554             keys, key, nextKey;
1555
1556         for (i = 0, ln = parts.length; i < ln; i++) {
1557             part = parts[i];
1558
1559             if (part.length > 0) {
1560                 components = part.split('=');
1561                 name = decodeURIComponent(components[0]);
1562                 value = (components[1] !== undefined) ? decodeURIComponent(components[1]) : '';
1563
1564                 if (!recursive) {
1565                     if (object.hasOwnProperty(name)) {
1566                         if (!Ext.isArray(object[name])) {
1567                             object[name] = [object[name]];
1568                         }
1569
1570                         object[name].push(value);
1571                     }
1572                     else {
1573                         object[name] = value;
1574                     }
1575                 }
1576                 else {
1577                     matchedKeys = name.match(/(\[):?([^\]]*)\]/g);
1578                     matchedName = name.match(/^([^\[]+)/);
1579
1580                     if (!matchedName) {
1581                         Ext.Error.raise({
1582                             sourceClass: "Ext.Object",
1583                             sourceMethod: "fromQueryString",
1584                             queryString: queryString,
1585                             recursive: recursive,
1586                             msg: 'Malformed query string given, failed parsing name from "' + part + '"'
1587                         });
1588                     }
1589
1590                     name = matchedName[0];
1591                     keys = [];
1592
1593                     if (matchedKeys === null) {
1594                         object[name] = value;
1595                         continue;
1596                     }
1597
1598                     for (j = 0, subLn = matchedKeys.length; j < subLn; j++) {
1599                         key = matchedKeys[j];
1600                         key = (key.length === 2) ? '' : key.substring(1, key.length - 1);
1601                         keys.push(key);
1602                     }
1603
1604                     keys.unshift(name);
1605
1606                     temp = object;
1607
1608                     for (j = 0, subLn = keys.length; j < subLn; j++) {
1609                         key = keys[j];
1610
1611                         if (j === subLn - 1) {
1612                             if (Ext.isArray(temp) && key === '') {
1613                                 temp.push(value);
1614                             }
1615                             else {
1616                                 temp[key] = value;
1617                             }
1618                         }
1619                         else {
1620                             if (temp[key] === undefined || typeof temp[key] === 'string') {
1621                                 nextKey = keys[j+1];
1622
1623                                 temp[key] = (Ext.isNumeric(nextKey) || nextKey === '') ? [] : {};
1624                             }
1625
1626                             temp = temp[key];
1627                         }
1628                     }
1629                 }
1630             }
1631         }
1632
1633         return object;
1634     },
1635
1636     
1637     each: function(object, fn, scope) {
1638         for (var property in object) {
1639             if (object.hasOwnProperty(property)) {
1640                 if (fn.call(scope || object, property, object[property], object) === false) {
1641                     return;
1642                 }
1643             }
1644         }
1645     },
1646
1647     
1648     merge: function(source, key, value) {
1649         if (typeof key === 'string') {
1650             if (value && value.constructor === Object) {
1651                 if (source[key] && source[key].constructor === Object) {
1652                     ExtObject.merge(source[key], value);
1653                 }
1654                 else {
1655                     source[key] = Ext.clone(value);
1656                 }
1657             }
1658             else {
1659                 source[key] = value;
1660             }
1661
1662             return source;
1663         }
1664
1665         var i = 1,
1666             ln = arguments.length,
1667             object, property;
1668
1669         for (; i < ln; i++) {
1670             object = arguments[i];
1671
1672             for (property in object) {
1673                 if (object.hasOwnProperty(property)) {
1674                     ExtObject.merge(source, property, object[property]);
1675                 }
1676             }
1677         }
1678
1679         return source;
1680     },
1681
1682     
1683     getKey: function(object, value) {
1684         for (var property in object) {
1685             if (object.hasOwnProperty(property) && object[property] === value) {
1686                 return property;
1687             }
1688         }
1689
1690         return null;
1691     },
1692
1693     
1694     getValues: function(object) {
1695         var values = [],
1696             property;
1697
1698         for (property in object) {
1699             if (object.hasOwnProperty(property)) {
1700                 values.push(object[property]);
1701             }
1702         }
1703
1704         return values;
1705     },
1706
1707     
1708     getKeys: ('keys' in Object.prototype) ? Object.keys : function(object) {
1709         var keys = [],
1710             property;
1711
1712         for (property in object) {
1713             if (object.hasOwnProperty(property)) {
1714                 keys.push(property);
1715             }
1716         }
1717
1718         return keys;
1719     },
1720
1721     
1722     getSize: function(object) {
1723         var size = 0,
1724             property;
1725
1726         for (property in object) {
1727             if (object.hasOwnProperty(property)) {
1728                 size++;
1729             }
1730         }
1731
1732         return size;
1733     }
1734 };
1735
1736
1737
1738 Ext.merge = Ext.Object.merge;
1739
1740
1741 Ext.urlEncode = function() {
1742     var args = Ext.Array.from(arguments),
1743         prefix = '';
1744
1745     
1746     if ((typeof args[1] === 'string')) {
1747         prefix = args[1] + '&';
1748         args[1] = false;
1749     }
1750
1751     return prefix + Ext.Object.toQueryString.apply(Ext.Object, args);
1752 };
1753
1754
1755 Ext.urlDecode = function() {
1756     return Ext.Object.fromQueryString.apply(Ext.Object, arguments);
1757 };
1758
1759 })();
1760
1761
1762
1763
1764
1765 (function() {
1766
1767
1768
1769
1770 function xf(format) {
1771     var args = Array.prototype.slice.call(arguments, 1);
1772     return format.replace(/\{(\d+)\}/g, function(m, i) {
1773         return args[i];
1774     });
1775 }
1776
1777 Ext.Date = {
1778     
1779     now: Date.now || function() {
1780         return +new Date();
1781     },
1782
1783     
1784     toString: function(date) {
1785         var pad = Ext.String.leftPad;
1786
1787         return date.getFullYear() + "-"
1788             + pad(date.getMonth() + 1, 2, '0') + "-"
1789             + pad(date.getDate(), 2, '0') + "T"
1790             + pad(date.getHours(), 2, '0') + ":"
1791             + pad(date.getMinutes(), 2, '0') + ":"
1792             + pad(date.getSeconds(), 2, '0');
1793     },
1794
1795     
1796     getElapsed: function(dateA, dateB) {
1797         return Math.abs(dateA - (dateB || new Date()));
1798     },
1799
1800     
1801     useStrict: false,
1802
1803     
1804     formatCodeToRegex: function(character, currentGroup) {
1805         
1806         var p = utilDate.parseCodes[character];
1807
1808         if (p) {
1809           p = typeof p == 'function'? p() : p;
1810           utilDate.parseCodes[character] = p; 
1811         }
1812
1813         return p ? Ext.applyIf({
1814           c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
1815         }, p) : {
1816             g: 0,
1817             c: null,
1818             s: Ext.String.escapeRegex(character) 
1819         };
1820     },
1821
1822     
1823     parseFunctions: {
1824         "MS": function(input, strict) {
1825             
1826             
1827             var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
1828             var r = (input || '').match(re);
1829             return r? new Date(((r[1] || '') + r[2]) * 1) : null;
1830         }
1831     },
1832     parseRegexes: [],
1833
1834     
1835     formatFunctions: {
1836         "MS": function() {
1837             
1838             return '\\/Date(' + this.getTime() + ')\\/';
1839         }
1840     },
1841
1842     y2kYear : 50,
1843
1844     
1845     MILLI : "ms",
1846
1847     
1848     SECOND : "s",
1849
1850     
1851     MINUTE : "mi",
1852
1853     
1854     HOUR : "h",
1855
1856     
1857     DAY : "d",
1858
1859     
1860     MONTH : "mo",
1861
1862     
1863     YEAR : "y",
1864
1865     
1866     defaults: {},
1867
1868     
1869     dayNames : [
1870         "Sunday",
1871         "Monday",
1872         "Tuesday",
1873         "Wednesday",
1874         "Thursday",
1875         "Friday",
1876         "Saturday"
1877     ],
1878
1879     
1880     monthNames : [
1881         "January",
1882         "February",
1883         "March",
1884         "April",
1885         "May",
1886         "June",
1887         "July",
1888         "August",
1889         "September",
1890         "October",
1891         "November",
1892         "December"
1893     ],
1894
1895     
1896     monthNumbers : {
1897         Jan:0,
1898         Feb:1,
1899         Mar:2,
1900         Apr:3,
1901         May:4,
1902         Jun:5,
1903         Jul:6,
1904         Aug:7,
1905         Sep:8,
1906         Oct:9,
1907         Nov:10,
1908         Dec:11
1909     },
1910     
1911     defaultFormat : "m/d/Y",
1912     
1913     getShortMonthName : function(month) {
1914         return utilDate.monthNames[month].substring(0, 3);
1915     },
1916
1917     
1918     getShortDayName : function(day) {
1919         return utilDate.dayNames[day].substring(0, 3);
1920     },
1921
1922     
1923     getMonthNumber : function(name) {
1924         
1925         return utilDate.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
1926     },
1927
1928     
1929     formatContainsHourInfo : (function(){
1930         var stripEscapeRe = /(\\.)/g,
1931             hourInfoRe = /([gGhHisucUOPZ]|MS)/;
1932         return function(format){
1933             return hourInfoRe.test(format.replace(stripEscapeRe, ''));
1934         };
1935     })(),
1936
1937     
1938     formatContainsDateInfo : (function(){
1939         var stripEscapeRe = /(\\.)/g,
1940             dateInfoRe = /([djzmnYycU]|MS)/;
1941
1942         return function(format){
1943             return dateInfoRe.test(format.replace(stripEscapeRe, ''));
1944         };
1945     })(),
1946
1947     
1948     formatCodes : {
1949         d: "Ext.String.leftPad(this.getDate(), 2, '0')",
1950         D: "Ext.Date.getShortDayName(this.getDay())", 
1951         j: "this.getDate()",
1952         l: "Ext.Date.dayNames[this.getDay()]",
1953         N: "(this.getDay() ? this.getDay() : 7)",
1954         S: "Ext.Date.getSuffix(this)",
1955         w: "this.getDay()",
1956         z: "Ext.Date.getDayOfYear(this)",
1957         W: "Ext.String.leftPad(Ext.Date.getWeekOfYear(this), 2, '0')",
1958         F: "Ext.Date.monthNames[this.getMonth()]",
1959         m: "Ext.String.leftPad(this.getMonth() + 1, 2, '0')",
1960         M: "Ext.Date.getShortMonthName(this.getMonth())", 
1961         n: "(this.getMonth() + 1)",
1962         t: "Ext.Date.getDaysInMonth(this)",
1963         L: "(Ext.Date.isLeapYear(this) ? 1 : 0)",
1964         o: "(this.getFullYear() + (Ext.Date.getWeekOfYear(this) == 1 && this.getMonth() > 0 ? +1 : (Ext.Date.getWeekOfYear(this) >= 52 && this.getMonth() < 11 ? -1 : 0)))",
1965         Y: "Ext.String.leftPad(this.getFullYear(), 4, '0')",
1966         y: "('' + this.getFullYear()).substring(2, 4)",
1967         a: "(this.getHours() < 12 ? 'am' : 'pm')",
1968         A: "(this.getHours() < 12 ? 'AM' : 'PM')",
1969         g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
1970         G: "this.getHours()",
1971         h: "Ext.String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
1972         H: "Ext.String.leftPad(this.getHours(), 2, '0')",
1973         i: "Ext.String.leftPad(this.getMinutes(), 2, '0')",
1974         s: "Ext.String.leftPad(this.getSeconds(), 2, '0')",
1975         u: "Ext.String.leftPad(this.getMilliseconds(), 3, '0')",
1976         O: "Ext.Date.getGMTOffset(this)",
1977         P: "Ext.Date.getGMTOffset(this, true)",
1978         T: "Ext.Date.getTimezone(this)",
1979         Z: "(this.getTimezoneOffset() * -60)",
1980
1981         c: function() { 
1982             for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
1983                 var e = c.charAt(i);
1984                 code.push(e == "T" ? "'T'" : utilDate.getFormatCode(e)); 
1985             }
1986             return code.join(" + ");
1987         },
1988         
1989
1990         U: "Math.round(this.getTime() / 1000)"
1991     },
1992
1993     
1994     isValid : function(y, m, d, h, i, s, ms) {
1995         
1996         h = h || 0;
1997         i = i || 0;
1998         s = s || 0;
1999         ms = ms || 0;
2000
2001         
2002         var dt = utilDate.add(new Date(y < 100 ? 100 : y, m - 1, d, h, i, s, ms), utilDate.YEAR, y < 100 ? y - 100 : 0);
2003
2004         return y == dt.getFullYear() &&
2005             m == dt.getMonth() + 1 &&
2006             d == dt.getDate() &&
2007             h == dt.getHours() &&
2008             i == dt.getMinutes() &&
2009             s == dt.getSeconds() &&
2010             ms == dt.getMilliseconds();
2011     },
2012
2013     
2014     parse : function(input, format, strict) {
2015         var p = utilDate.parseFunctions;
2016         if (p[format] == null) {
2017             utilDate.createParser(format);
2018         }
2019         return p[format](input, Ext.isDefined(strict) ? strict : utilDate.useStrict);
2020     },
2021
2022     
2023     parseDate: function(input, format, strict){
2024         return utilDate.parse(input, format, strict);
2025     },
2026
2027
2028     
2029     getFormatCode : function(character) {
2030         var f = utilDate.formatCodes[character];
2031
2032         if (f) {
2033           f = typeof f == 'function'? f() : f;
2034           utilDate.formatCodes[character] = f; 
2035         }
2036
2037         
2038         return f || ("'" + Ext.String.escape(character) + "'");
2039     },
2040
2041     
2042     createFormat : function(format) {
2043         var code = [],
2044             special = false,
2045             ch = '';
2046
2047         for (var i = 0; i < format.length; ++i) {
2048             ch = format.charAt(i);
2049             if (!special && ch == "\\") {
2050                 special = true;
2051             } else if (special) {
2052                 special = false;
2053                 code.push("'" + Ext.String.escape(ch) + "'");
2054             } else {
2055                 code.push(utilDate.getFormatCode(ch));
2056             }
2057         }
2058         utilDate.formatFunctions[format] = Ext.functionFactory("return " + code.join('+'));
2059     },
2060
2061     
2062     createParser : (function() {
2063         var code = [
2064             "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
2065                 "def = Ext.Date.defaults,",
2066                 "results = String(input).match(Ext.Date.parseRegexes[{0}]);", 
2067
2068             "if(results){",
2069                 "{1}",
2070
2071                 "if(u != null){", 
2072                     "v = new Date(u * 1000);", 
2073                 "}else{",
2074                     
2075                     
2076                     
2077                     "dt = Ext.Date.clearTime(new Date);",
2078
2079                     
2080                     "y = Ext.Number.from(y, Ext.Number.from(def.y, dt.getFullYear()));",
2081                     "m = Ext.Number.from(m, Ext.Number.from(def.m - 1, dt.getMonth()));",
2082                     "d = Ext.Number.from(d, Ext.Number.from(def.d, dt.getDate()));",
2083
2084                     
2085                     "h  = Ext.Number.from(h, Ext.Number.from(def.h, dt.getHours()));",
2086                     "i  = Ext.Number.from(i, Ext.Number.from(def.i, dt.getMinutes()));",
2087                     "s  = Ext.Number.from(s, Ext.Number.from(def.s, dt.getSeconds()));",
2088                     "ms = Ext.Number.from(ms, Ext.Number.from(def.ms, dt.getMilliseconds()));",
2089
2090                     "if(z >= 0 && y >= 0){",
2091                         
2092                         
2093
2094                         
2095                         
2096                         "v = Ext.Date.add(new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);",
2097
2098                         
2099                         "v = !strict? v : (strict === true && (z <= 364 || (Ext.Date.isLeapYear(v) && z <= 365))? Ext.Date.add(v, Ext.Date.DAY, z) : null);",
2100                     "}else if(strict === true && !Ext.Date.isValid(y, m + 1, d, h, i, s, ms)){", 
2101                         "v = null;", 
2102                     "}else{",
2103                         
2104                         
2105                         "v = Ext.Date.add(new Date(y < 100 ? 100 : y, m, d, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);",
2106                     "}",
2107                 "}",
2108             "}",
2109
2110             "if(v){",
2111                 
2112                 "if(zz != null){",
2113                     
2114                     "v = Ext.Date.add(v, Ext.Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
2115                 "}else if(o){",
2116                     
2117                     "v = Ext.Date.add(v, Ext.Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
2118                 "}",
2119             "}",
2120
2121             "return v;"
2122         ].join('\n');
2123
2124         return function(format) {
2125             var regexNum = utilDate.parseRegexes.length,
2126                 currentGroup = 1,
2127                 calc = [],
2128                 regex = [],
2129                 special = false,
2130                 ch = "";
2131
2132             for (var i = 0; i < format.length; ++i) {
2133                 ch = format.charAt(i);
2134                 if (!special && ch == "\\") {
2135                     special = true;
2136                 } else if (special) {
2137                     special = false;
2138                     regex.push(Ext.String.escape(ch));
2139                 } else {
2140                     var obj = utilDate.formatCodeToRegex(ch, currentGroup);
2141                     currentGroup += obj.g;
2142                     regex.push(obj.s);
2143                     if (obj.g && obj.c) {
2144                         calc.push(obj.c);
2145                     }
2146                 }
2147             }
2148
2149             utilDate.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", 'i');
2150             utilDate.parseFunctions[format] = Ext.functionFactory("input", "strict", xf(code, regexNum, calc.join('')));
2151         };
2152     })(),
2153
2154     
2155     parseCodes : {
2156         
2157         d: {
2158             g:1,
2159             c:"d = parseInt(results[{0}], 10);\n",
2160             s:"(\\d{2})" 
2161         },
2162         j: {
2163             g:1,
2164             c:"d = parseInt(results[{0}], 10);\n",
2165             s:"(\\d{1,2})" 
2166         },
2167         D: function() {
2168             for (var a = [], i = 0; i < 7; a.push(utilDate.getShortDayName(i)), ++i); 
2169             return {
2170                 g:0,
2171                 c:null,
2172                 s:"(?:" + a.join("|") +")"
2173             };
2174         },
2175         l: function() {
2176             return {
2177                 g:0,
2178                 c:null,
2179                 s:"(?:" + utilDate.dayNames.join("|") + ")"
2180             };
2181         },
2182         N: {
2183             g:0,
2184             c:null,
2185             s:"[1-7]" 
2186         },
2187         S: {
2188             g:0,
2189             c:null,
2190             s:"(?:st|nd|rd|th)"
2191         },
2192         w: {
2193             g:0,
2194             c:null,
2195             s:"[0-6]" 
2196         },
2197         z: {
2198             g:1,
2199             c:"z = parseInt(results[{0}], 10);\n",
2200             s:"(\\d{1,3})" 
2201         },
2202         W: {
2203             g:0,
2204             c:null,
2205             s:"(?:\\d{2})" 
2206         },
2207         F: function() {
2208             return {
2209                 g:1,
2210                 c:"m = parseInt(Ext.Date.getMonthNumber(results[{0}]), 10);\n", 
2211                 s:"(" + utilDate.monthNames.join("|") + ")"
2212             };
2213         },
2214         M: function() {
2215             for (var a = [], i = 0; i < 12; a.push(utilDate.getShortMonthName(i)), ++i); 
2216             return Ext.applyIf({
2217                 s:"(" + a.join("|") + ")"
2218             }, utilDate.formatCodeToRegex("F"));
2219         },
2220         m: {
2221             g:1,
2222             c:"m = parseInt(results[{0}], 10) - 1;\n",
2223             s:"(\\d{2})" 
2224         },
2225         n: {
2226             g:1,
2227             c:"m = parseInt(results[{0}], 10) - 1;\n",
2228             s:"(\\d{1,2})" 
2229         },
2230         t: {
2231             g:0,
2232             c:null,
2233             s:"(?:\\d{2})" 
2234         },
2235         L: {
2236             g:0,
2237             c:null,
2238             s:"(?:1|0)"
2239         },
2240         o: function() {
2241             return utilDate.formatCodeToRegex("Y");
2242         },
2243         Y: {
2244             g:1,
2245             c:"y = parseInt(results[{0}], 10);\n",
2246             s:"(\\d{4})" 
2247         },
2248         y: {
2249             g:1,
2250             c:"var ty = parseInt(results[{0}], 10);\n"
2251                 + "y = ty > Ext.Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
2252             s:"(\\d{1,2})"
2253         },
2254         
2255         a: {
2256             g:1,
2257             c:"if (/(am)/i.test(results[{0}])) {\n"
2258                 + "if (!h || h == 12) { h = 0; }\n"
2259                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
2260             s:"(am|pm|AM|PM)"
2261         },
2262         A: {
2263             g:1,
2264             c:"if (/(am)/i.test(results[{0}])) {\n"
2265                 + "if (!h || h == 12) { h = 0; }\n"
2266                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
2267             s:"(AM|PM|am|pm)"
2268         },
2269         g: function() {
2270             return utilDate.formatCodeToRegex("G");
2271         },
2272         G: {
2273             g:1,
2274             c:"h = parseInt(results[{0}], 10);\n",
2275             s:"(\\d{1,2})" 
2276         },
2277         h: function() {
2278             return utilDate.formatCodeToRegex("H");
2279         },
2280         H: {
2281             g:1,
2282             c:"h = parseInt(results[{0}], 10);\n",
2283             s:"(\\d{2})" 
2284         },
2285         i: {
2286             g:1,
2287             c:"i = parseInt(results[{0}], 10);\n",
2288             s:"(\\d{2})" 
2289         },
2290         s: {
2291             g:1,
2292             c:"s = parseInt(results[{0}], 10);\n",
2293             s:"(\\d{2})" 
2294         },
2295         u: {
2296             g:1,
2297             c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
2298             s:"(\\d+)" 
2299         },
2300         O: {
2301             g:1,
2302             c:[
2303                 "o = results[{0}];",
2304                 "var sn = o.substring(0,1),", 
2305                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
2306                     "mn = o.substring(3,5) % 60;", 
2307                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n" 
2308             ].join("\n"),
2309             s: "([+\-]\\d{4})" 
2310         },
2311         P: {
2312             g:1,
2313             c:[
2314                 "o = results[{0}];",
2315                 "var sn = o.substring(0,1),", 
2316                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
2317                     "mn = o.substring(4,6) % 60;", 
2318                 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n" 
2319             ].join("\n"),
2320             s: "([+\-]\\d{2}:\\d{2})" 
2321         },
2322         T: {
2323             g:0,
2324             c:null,
2325             s:"[A-Z]{1,4}" 
2326         },
2327         Z: {
2328             g:1,
2329             c:"zz = results[{0}] * 1;\n" 
2330                   + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
2331             s:"([+\-]?\\d{1,5})" 
2332         },
2333         c: function() {
2334             var calc = [],
2335                 arr = [
2336                     utilDate.formatCodeToRegex("Y", 1), 
2337                     utilDate.formatCodeToRegex("m", 2), 
2338                     utilDate.formatCodeToRegex("d", 3), 
2339                     utilDate.formatCodeToRegex("h", 4), 
2340                     utilDate.formatCodeToRegex("i", 5), 
2341                     utilDate.formatCodeToRegex("s", 6), 
2342                     {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
2343                     {c:[ 
2344                         "if(results[8]) {", 
2345                             "if(results[8] == 'Z'){",
2346                                 "zz = 0;", 
2347                             "}else if (results[8].indexOf(':') > -1){",
2348                                 utilDate.formatCodeToRegex("P", 8).c, 
2349                             "}else{",
2350                                 utilDate.formatCodeToRegex("O", 8).c, 
2351                             "}",
2352                         "}"
2353                     ].join('\n')}
2354                 ];
2355
2356             for (var i = 0, l = arr.length; i < l; ++i) {
2357                 calc.push(arr[i].c);
2358             }
2359
2360             return {
2361                 g:1,
2362                 c:calc.join(""),
2363                 s:[
2364                     arr[0].s, 
2365                     "(?:", "-", arr[1].s, 
2366                         "(?:", "-", arr[2].s, 
2367                             "(?:",
2368                                 "(?:T| )?", 
2369                                 arr[3].s, ":", arr[4].s,  
2370                                 "(?::", arr[5].s, ")?", 
2371                                 "(?:(?:\\.|,)(\\d+))?", 
2372                                 "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
2373                             ")?",
2374                         ")?",
2375                     ")?"
2376                 ].join("")
2377             };
2378         },
2379         U: {
2380             g:1,
2381             c:"u = parseInt(results[{0}], 10);\n",
2382             s:"(-?\\d+)" 
2383         }
2384     },
2385
2386     
2387     
2388     dateFormat: function(date, format) {
2389         return utilDate.format(date, format);
2390     },
2391
2392     
2393     format: function(date, format) {
2394         if (utilDate.formatFunctions[format] == null) {
2395             utilDate.createFormat(format);
2396         }
2397         var result = utilDate.formatFunctions[format].call(date);
2398         return result + '';
2399     },
2400
2401     
2402     getTimezone : function(date) {
2403         
2404         
2405         
2406         
2407         
2408         
2409         
2410         
2411         
2412         
2413         
2414         
2415         return date.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
2416     },
2417
2418     
2419     getGMTOffset : function(date, colon) {
2420         var offset = date.getTimezoneOffset();
2421         return (offset > 0 ? "-" : "+")
2422             + Ext.String.leftPad(Math.floor(Math.abs(offset) / 60), 2, "0")
2423             + (colon ? ":" : "")
2424             + Ext.String.leftPad(Math.abs(offset % 60), 2, "0");
2425     },
2426
2427     
2428     getDayOfYear: function(date) {
2429         var num = 0,
2430             d = Ext.Date.clone(date),
2431             m = date.getMonth(),
2432             i;
2433
2434         for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
2435             num += utilDate.getDaysInMonth(d);
2436         }
2437         return num + date.getDate() - 1;
2438     },
2439
2440     
2441     getWeekOfYear : (function() {
2442         
2443         var ms1d = 864e5, 
2444             ms7d = 7 * ms1d; 
2445
2446         return function(date) { 
2447             var DC3 = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate() + 3) / ms1d, 
2448                 AWN = Math.floor(DC3 / 7), 
2449                 Wyr = new Date(AWN * ms7d).getUTCFullYear();
2450
2451             return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
2452         };
2453     })(),
2454
2455     
2456     isLeapYear : function(date) {
2457         var year = date.getFullYear();
2458         return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
2459     },
2460
2461     
2462     getFirstDayOfMonth : function(date) {
2463         var day = (date.getDay() - (date.getDate() - 1)) % 7;
2464         return (day < 0) ? (day + 7) : day;
2465     },
2466
2467     
2468     getLastDayOfMonth : function(date) {
2469         return utilDate.getLastDateOfMonth(date).getDay();
2470     },
2471
2472
2473     
2474     getFirstDateOfMonth : function(date) {
2475         return new Date(date.getFullYear(), date.getMonth(), 1);
2476     },
2477
2478     
2479     getLastDateOfMonth : function(date) {
2480         return new Date(date.getFullYear(), date.getMonth(), utilDate.getDaysInMonth(date));
2481     },
2482
2483     
2484     getDaysInMonth: (function() {
2485         var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
2486
2487         return function(date) { 
2488             var m = date.getMonth();
2489
2490             return m == 1 && utilDate.isLeapYear(date) ? 29 : daysInMonth[m];
2491         };
2492     })(),
2493
2494     
2495     getSuffix : function(date) {
2496         switch (date.getDate()) {
2497             case 1:
2498             case 21:
2499             case 31:
2500                 return "st";
2501             case 2:
2502             case 22:
2503                 return "nd";
2504             case 3:
2505             case 23:
2506                 return "rd";
2507             default:
2508                 return "th";
2509         }
2510     },
2511
2512     
2513     clone : function(date) {
2514         return new Date(date.getTime());
2515     },
2516
2517     
2518     isDST : function(date) {
2519         
2520         
2521         return new Date(date.getFullYear(), 0, 1).getTimezoneOffset() != date.getTimezoneOffset();
2522     },
2523
2524     
2525     clearTime : function(date, clone) {
2526         if (clone) {
2527             return Ext.Date.clearTime(Ext.Date.clone(date));
2528         }
2529
2530         
2531         var d = date.getDate();
2532
2533         
2534         date.setHours(0);
2535         date.setMinutes(0);
2536         date.setSeconds(0);
2537         date.setMilliseconds(0);
2538
2539         if (date.getDate() != d) { 
2540             
2541             
2542
2543             
2544             for (var hr = 1, c = utilDate.add(date, Ext.Date.HOUR, hr); c.getDate() != d; hr++, c = utilDate.add(date, Ext.Date.HOUR, hr));
2545
2546             date.setDate(d);
2547             date.setHours(c.getHours());
2548         }
2549
2550         return date;
2551     },
2552
2553     
2554     add : function(date, interval, value) {
2555         var d = Ext.Date.clone(date),
2556             Date = Ext.Date;
2557         if (!interval || value === 0) return d;
2558
2559         switch(interval.toLowerCase()) {
2560             case Ext.Date.MILLI:
2561                 d.setMilliseconds(d.getMilliseconds() + value);
2562                 break;
2563             case Ext.Date.SECOND:
2564                 d.setSeconds(d.getSeconds() + value);
2565                 break;
2566             case Ext.Date.MINUTE:
2567                 d.setMinutes(d.getMinutes() + value);
2568                 break;
2569             case Ext.Date.HOUR:
2570                 d.setHours(d.getHours() + value);
2571                 break;
2572             case Ext.Date.DAY:
2573                 d.setDate(d.getDate() + value);
2574                 break;
2575             case Ext.Date.MONTH:
2576                 var day = date.getDate();
2577                 if (day > 28) {
2578                     day = Math.min(day, Ext.Date.getLastDateOfMonth(Ext.Date.add(Ext.Date.getFirstDateOfMonth(date), 'mo', value)).getDate());
2579                 }
2580                 d.setDate(day);
2581                 d.setMonth(date.getMonth() + value);
2582                 break;
2583             case Ext.Date.YEAR:
2584                 d.setFullYear(date.getFullYear() + value);
2585                 break;
2586         }
2587         return d;
2588     },
2589
2590     
2591     between : function(date, start, end) {
2592         var t = date.getTime();
2593         return start.getTime() <= t && t <= end.getTime();
2594     },
2595
2596     
2597     compat: function() {
2598         var nativeDate = window.Date,
2599             p, u,
2600             statics = ['useStrict', 'formatCodeToRegex', 'parseFunctions', 'parseRegexes', 'formatFunctions', 'y2kYear', 'MILLI', 'SECOND', 'MINUTE', 'HOUR', 'DAY', 'MONTH', 'YEAR', 'defaults', 'dayNames', 'monthNames', 'monthNumbers', 'getShortMonthName', 'getShortDayName', 'getMonthNumber', 'formatCodes', 'isValid', 'parseDate', 'getFormatCode', 'createFormat', 'createParser', 'parseCodes'],
2601             proto = ['dateFormat', 'format', 'getTimezone', 'getGMTOffset', 'getDayOfYear', 'getWeekOfYear', 'isLeapYear', 'getFirstDayOfMonth', 'getLastDayOfMonth', 'getDaysInMonth', 'getSuffix', 'clone', 'isDST', 'clearTime', 'add', 'between'];
2602
2603         
2604         Ext.Array.forEach(statics, function(s) {
2605             nativeDate[s] = utilDate[s];
2606         });
2607
2608         
2609         Ext.Array.forEach(proto, function(s) {
2610             nativeDate.prototype[s] = function() {
2611                 var args = Array.prototype.slice.call(arguments);
2612                 args.unshift(this);
2613                 return utilDate[s].apply(utilDate, args);
2614             };
2615         });
2616     }
2617 };
2618
2619 var utilDate = Ext.Date;
2620
2621 })();
2622
2623
2624 (function(flexSetter) {
2625
2626 var Base = Ext.Base = function() {};
2627     Base.prototype = {
2628         $className: 'Ext.Base',
2629
2630         $class: Base,
2631
2632         
2633         self: Base,
2634
2635         
2636         constructor: function() {
2637             return this;
2638         },
2639
2640         
2641         initConfig: function(config) {
2642             if (!this.$configInited) {
2643                 this.config = Ext.Object.merge({}, this.config || {}, config || {});
2644
2645                 this.applyConfig(this.config);
2646
2647                 this.$configInited = true;
2648             }
2649
2650             return this;
2651         },
2652
2653         
2654         setConfig: function(config) {
2655             this.applyConfig(config || {});
2656
2657             return this;
2658         },
2659
2660         
2661         applyConfig: flexSetter(function(name, value) {
2662             var setter = 'set' + Ext.String.capitalize(name);
2663
2664             if (typeof this[setter] === 'function') {
2665                 this[setter].call(this, value);
2666             }
2667
2668             return this;
2669         }),
2670
2671         
2672         callParent: function(args) {
2673             var method = this.callParent.caller,
2674                 parentClass, methodName;
2675
2676             if (!method.$owner) {
2677                 if (!method.caller) {
2678                     Ext.Error.raise({
2679                         sourceClass: Ext.getClassName(this),
2680                         sourceMethod: "callParent",
2681                         msg: "Attempting to call a protected method from the public scope, which is not allowed"
2682                     });
2683                 }
2684
2685                 method = method.caller;
2686             }
2687
2688             parentClass = method.$owner.superclass;
2689             methodName = method.$name;
2690
2691             if (!(methodName in parentClass)) {
2692                 Ext.Error.raise({
2693                     sourceClass: Ext.getClassName(this),
2694                     sourceMethod: methodName,
2695                     msg: "this.callParent() was called but there's no such method (" + methodName +
2696                          ") found in the parent class (" + (Ext.getClassName(parentClass) || 'Object') + ")"
2697                  });
2698             }
2699
2700             return parentClass[methodName].apply(this, args || []);
2701         },
2702
2703
2704         
2705         statics: function() {
2706             var method = this.statics.caller,
2707                 self = this.self;
2708
2709             if (!method) {
2710                 return self;
2711             }
2712
2713             return method.$owner;
2714         },
2715
2716         
2717         callOverridden: function(args) {
2718             var method = this.callOverridden.caller;
2719
2720             if (!method.$owner) {
2721                 Ext.Error.raise({
2722                     sourceClass: Ext.getClassName(this),
2723                     sourceMethod: "callOverridden",
2724                     msg: "Attempting to call a protected method from the public scope, which is not allowed"
2725                 });
2726             }
2727
2728             if (!method.$previous) {
2729                 Ext.Error.raise({
2730                     sourceClass: Ext.getClassName(this),
2731                     sourceMethod: "callOverridden",
2732                     msg: "this.callOverridden was called in '" + method.$name +
2733                          "' but this method has never been overridden"
2734                  });
2735             }
2736
2737             return method.$previous.apply(this, args || []);
2738         },
2739
2740         destroy: function() {}
2741     };
2742
2743     
2744     Ext.apply(Ext.Base, {
2745         
2746         create: function() {
2747             return Ext.create.apply(Ext, [this].concat(Array.prototype.slice.call(arguments, 0)));
2748         },
2749
2750         
2751         own: flexSetter(function(name, value) {
2752             if (typeof value === 'function') {
2753                 this.ownMethod(name, value);
2754             }
2755             else {
2756                 this.prototype[name] = value;
2757             }
2758         }),
2759
2760         
2761         ownMethod: function(name, fn) {
2762             var originalFn;
2763
2764             if (fn.$owner !== undefined && fn !== Ext.emptyFn) {
2765                 originalFn = fn;
2766
2767                 fn = function() {
2768                     return originalFn.apply(this, arguments);
2769                 };
2770             }
2771
2772             var className;
2773             className = Ext.getClassName(this);
2774             if (className) {
2775                 fn.displayName = className + '#' + name;
2776             }
2777             fn.$owner = this;
2778             fn.$name = name;
2779
2780             this.prototype[name] = fn;
2781         },
2782
2783         
2784         addStatics: function(members) {
2785             for (var name in members) {
2786                 if (members.hasOwnProperty(name)) {
2787                     this[name] = members[name];
2788                 }
2789             }
2790
2791             return this;
2792         },
2793
2794         
2795         implement: function(members) {
2796             var prototype = this.prototype,
2797                 name, i, member, previous;
2798             var className = Ext.getClassName(this);
2799             for (name in members) {
2800                 if (members.hasOwnProperty(name)) {
2801                     member = members[name];
2802
2803                     if (typeof member === 'function') {
2804                         member.$owner = this;
2805                         member.$name = name;
2806                         if (className) {
2807                             member.displayName = className + '#' + name;
2808                         }
2809                     }
2810
2811                     prototype[name] = member;
2812                 }
2813             }
2814
2815             if (Ext.enumerables) {
2816                 var enumerables = Ext.enumerables;
2817
2818                 for (i = enumerables.length; i--;) {
2819                     name = enumerables[i];
2820
2821                     if (members.hasOwnProperty(name)) {
2822                         member = members[name];
2823                         member.$owner = this;
2824                         member.$name = name;
2825                         prototype[name] = member;
2826                     }
2827                 }
2828             }
2829         },
2830
2831         
2832         borrow: function(fromClass, members) {
2833             var fromPrototype = fromClass.prototype,
2834                 i, ln, member;
2835
2836             members = Ext.Array.from(members);
2837
2838             for (i = 0, ln = members.length; i < ln; i++) {
2839                 member = members[i];
2840
2841                 this.own(member, fromPrototype[member]);
2842             }
2843
2844             return this;
2845         },
2846
2847         
2848         override: function(members) {
2849             var prototype = this.prototype,
2850                 name, i, member, previous;
2851
2852             for (name in members) {
2853                 if (members.hasOwnProperty(name)) {
2854                     member = members[name];
2855
2856                     if (typeof member === 'function') {
2857                         if (typeof prototype[name] === 'function') {
2858                             previous = prototype[name];
2859                             member.$previous = previous;
2860                         }
2861
2862                         this.ownMethod(name, member);
2863                     }
2864                     else {
2865                         prototype[name] = member;
2866                     }
2867                 }
2868             }
2869
2870             if (Ext.enumerables) {
2871                 var enumerables = Ext.enumerables;
2872
2873                 for (i = enumerables.length; i--;) {
2874                     name = enumerables[i];
2875
2876                     if (members.hasOwnProperty(name)) {
2877                         if (prototype[name] !== undefined) {
2878                             previous = prototype[name];
2879                             members[name].$previous = previous;
2880                         }
2881
2882                         this.ownMethod(name, members[name]);
2883                     }
2884                 }
2885             }
2886
2887             return this;
2888         },
2889
2890         
2891         mixin: flexSetter(function(name, cls) {
2892             var mixin = cls.prototype,
2893                 my = this.prototype,
2894                 i, fn;
2895
2896             for (i in mixin) {
2897                 if (mixin.hasOwnProperty(i)) {
2898                     if (my[i] === undefined) {
2899                         if (typeof mixin[i] === 'function') {
2900                             fn = mixin[i];
2901
2902                             if (fn.$owner === undefined) {
2903                                 this.ownMethod(i, fn);
2904                             }
2905                             else {
2906                                 my[i] = fn;
2907                             }
2908                         }
2909                         else {
2910                             my[i] = mixin[i];
2911                         }
2912                     }
2913                     else if (i === 'config' && my.config && mixin.config) {
2914                         Ext.Object.merge(my.config, mixin.config);
2915                     }
2916                 }
2917             }
2918
2919             if (my.mixins === undefined) {
2920                 my.mixins = {};
2921             }
2922
2923             my.mixins[name] = mixin;
2924         }),
2925
2926         
2927         getName: function() {
2928             return Ext.getClassName(this);
2929         },
2930
2931         
2932         createAlias: flexSetter(function(alias, origin) {
2933             this.prototype[alias] = this.prototype[origin];
2934         })
2935     });
2936
2937 })(Ext.Function.flexSetter);
2938
2939
2940 (function() {
2941
2942     var Class,
2943         Base = Ext.Base,
2944         baseStaticProperties = [],
2945         baseStaticProperty;
2946
2947     for (baseStaticProperty in Base) {
2948         if (Base.hasOwnProperty(baseStaticProperty)) {
2949             baseStaticProperties.push(baseStaticProperty);
2950         }
2951     }
2952
2953     
2954     Ext.Class = Class = function(newClass, classData, onClassCreated) {
2955         if (typeof newClass !== 'function') {
2956             onClassCreated = classData;
2957             classData = newClass;
2958             newClass = function() {
2959                 return this.constructor.apply(this, arguments);
2960             };
2961         }
2962
2963         if (!classData) {
2964             classData = {};
2965         }
2966
2967         var preprocessorStack = classData.preprocessors || Class.getDefaultPreprocessors(),
2968             registeredPreprocessors = Class.getPreprocessors(),
2969             index = 0,
2970             preprocessors = [],
2971             preprocessor, preprocessors, staticPropertyName, process, i, j, ln;
2972
2973         for (i = 0, ln = baseStaticProperties.length; i < ln; i++) {
2974             staticPropertyName = baseStaticProperties[i];
2975             newClass[staticPropertyName] = Base[staticPropertyName];
2976         }
2977
2978         delete classData.preprocessors;
2979
2980         for (j = 0, ln = preprocessorStack.length; j < ln; j++) {
2981             preprocessor = preprocessorStack[j];
2982
2983             if (typeof preprocessor === 'string') {
2984                 preprocessor = registeredPreprocessors[preprocessor];
2985
2986                 if (!preprocessor.always) {
2987                     if (classData.hasOwnProperty(preprocessor.name)) {
2988                         preprocessors.push(preprocessor.fn);
2989                     }
2990                 }
2991                 else {
2992                     preprocessors.push(preprocessor.fn);
2993                 }
2994             }
2995             else {
2996                 preprocessors.push(preprocessor);
2997             }
2998         }
2999
3000         classData.onClassCreated = onClassCreated;
3001
3002         classData.onBeforeClassCreated = function(cls, data) {
3003             onClassCreated = data.onClassCreated;
3004
3005             delete data.onBeforeClassCreated;
3006             delete data.onClassCreated;
3007
3008             cls.implement(data);
3009
3010             if (onClassCreated) {
3011                 onClassCreated.call(cls, cls);
3012             }
3013         };
3014
3015         process = function(cls, data) {
3016             preprocessor = preprocessors[index++];
3017
3018             if (!preprocessor) {
3019                 data.onBeforeClassCreated.apply(this, arguments);
3020                 return;
3021             }
3022
3023             if (preprocessor.call(this, cls, data, process) !== false) {
3024                 process.apply(this, arguments);
3025             }
3026         };
3027
3028         process.call(Class, newClass, classData);
3029
3030         return newClass;
3031     };
3032
3033     Ext.apply(Class, {
3034
3035         
3036         preprocessors: {},
3037
3038         
3039         registerPreprocessor: function(name, fn, always) {
3040             this.preprocessors[name] = {
3041                 name: name,
3042                 always: always ||  false,
3043                 fn: fn
3044             };
3045
3046             return this;
3047         },
3048
3049         
3050         getPreprocessor: function(name) {
3051             return this.preprocessors[name];
3052         },
3053
3054         getPreprocessors: function() {
3055             return this.preprocessors;
3056         },
3057
3058         
3059         getDefaultPreprocessors: function() {
3060             return this.defaultPreprocessors || [];
3061         },
3062
3063         
3064         setDefaultPreprocessors: function(preprocessors) {
3065             this.defaultPreprocessors = Ext.Array.from(preprocessors);
3066
3067             return this;
3068         },
3069
3070         
3071         setDefaultPreprocessorPosition: function(name, offset, relativeName) {
3072             var defaultPreprocessors = this.defaultPreprocessors,
3073                 index;
3074
3075             if (typeof offset === 'string') {
3076                 if (offset === 'first') {
3077                     defaultPreprocessors.unshift(name);
3078
3079                     return this;
3080                 }
3081                 else if (offset === 'last') {
3082                     defaultPreprocessors.push(name);
3083
3084                     return this;
3085                 }
3086
3087                 offset = (offset === 'after') ? 1 : -1;
3088             }
3089
3090             index = Ext.Array.indexOf(defaultPreprocessors, relativeName);
3091
3092             if (index !== -1) {
3093                 defaultPreprocessors.splice(Math.max(0, index + offset), 0, name);
3094             }
3095
3096             return this;
3097         }
3098     });
3099
3100     Class.registerPreprocessor('extend', function(cls, data) {
3101         var extend = data.extend,
3102             base = Ext.Base,
3103             basePrototype = base.prototype,
3104             prototype = function() {},
3105             parent, i, k, ln, staticName, parentStatics,
3106             parentPrototype, clsPrototype;
3107
3108         if (extend && extend !== Object) {
3109             parent = extend;
3110         }
3111         else {
3112             parent = base;
3113         }
3114
3115         parentPrototype = parent.prototype;
3116
3117         prototype.prototype = parentPrototype;
3118         clsPrototype = cls.prototype = new prototype();
3119
3120         if (!('$class' in parent)) {
3121             for (i in basePrototype) {
3122                 if (!parentPrototype[i]) {
3123                     parentPrototype[i] = basePrototype[i];
3124                 }
3125             }
3126         }
3127
3128         clsPrototype.self = cls;
3129
3130         cls.superclass = clsPrototype.superclass = parentPrototype;
3131
3132         delete data.extend;
3133
3134         
3135         parentStatics = parentPrototype.$inheritableStatics;
3136
3137         if (parentStatics) {
3138             for (k = 0, ln = parentStatics.length; k < ln; k++) {
3139                 staticName = parentStatics[k];
3140
3141                 if (!cls.hasOwnProperty(staticName)) {
3142                     cls[staticName] = parent[staticName];
3143                 }
3144             }
3145         }
3146
3147         
3148         if (parentPrototype.config) {
3149             clsPrototype.config = Ext.Object.merge({}, parentPrototype.config);
3150         }
3151         else {
3152             clsPrototype.config = {};
3153         }
3154
3155         if (clsPrototype.$onExtended) {
3156             clsPrototype.$onExtended.call(cls, cls, data);
3157         }
3158
3159         if (data.onClassExtended) {
3160             clsPrototype.$onExtended = data.onClassExtended;
3161             delete data.onClassExtended;
3162         }
3163
3164     }, true);
3165
3166     Class.registerPreprocessor('statics', function(cls, data) {
3167         var statics = data.statics,
3168             name;
3169
3170         for (name in statics) {
3171             if (statics.hasOwnProperty(name)) {
3172                 cls[name] = statics[name];
3173             }
3174         }
3175
3176         delete data.statics;
3177     });
3178
3179     Class.registerPreprocessor('inheritableStatics', function(cls, data) {
3180         var statics = data.inheritableStatics,
3181             inheritableStatics,
3182             prototype = cls.prototype,
3183             name;
3184
3185         inheritableStatics = prototype.$inheritableStatics;
3186
3187         if (!inheritableStatics) {
3188             inheritableStatics = prototype.$inheritableStatics = [];
3189         }
3190
3191         for (name in statics) {
3192             if (statics.hasOwnProperty(name)) {
3193                 cls[name] = statics[name];
3194                 inheritableStatics.push(name);
3195             }
3196         }
3197
3198         delete data.inheritableStatics;
3199     });
3200
3201     Class.registerPreprocessor('mixins', function(cls, data) {
3202         cls.mixin(data.mixins);
3203
3204         delete data.mixins;
3205     });
3206
3207     Class.registerPreprocessor('config', function(cls, data) {
3208         var prototype = cls.prototype;
3209
3210         Ext.Object.each(data.config, function(name) {
3211             var cName = name.charAt(0).toUpperCase() + name.substr(1),
3212                 pName = name,
3213                 apply = 'apply' + cName,
3214                 setter = 'set' + cName,
3215                 getter = 'get' + cName;
3216
3217             if (!(apply in prototype) && !data.hasOwnProperty(apply)) {
3218                 data[apply] = function(val) {
3219                     return val;
3220                 };
3221             }
3222
3223             if (!(setter in prototype) && !data.hasOwnProperty(setter)) {
3224                 data[setter] = function(val) {
3225                     var ret = this[apply].call(this, val, this[pName]);
3226
3227                     if (ret !== undefined) {
3228                         this[pName] = ret;
3229                     }
3230
3231                     return this;
3232                 };
3233             }
3234
3235             if (!(getter in prototype) && !data.hasOwnProperty(getter)) {
3236                 data[getter] = function() {
3237                     return this[pName];
3238                 };
3239             }
3240         });
3241
3242         Ext.Object.merge(prototype.config, data.config);
3243         delete data.config;
3244     });
3245
3246     Class.setDefaultPreprocessors(['extend', 'statics', 'inheritableStatics', 'mixins', 'config']);
3247
3248     
3249     Ext.extend = function(subclass, superclass, members) {
3250         if (arguments.length === 2 && Ext.isObject(superclass)) {
3251             members = superclass;
3252             superclass = subclass;
3253             subclass = null;
3254         }
3255
3256         var cls;
3257
3258         if (!superclass) {
3259             Ext.Error.raise("Attempting to extend from a class which has not been loaded on the page.");
3260         }
3261
3262         members.extend = superclass;
3263         members.preprocessors = ['extend', 'mixins', 'config', 'statics'];
3264
3265         if (subclass) {
3266             cls = new Class(subclass, members);
3267         }
3268         else {
3269             cls = new Class(members);
3270         }
3271
3272         cls.prototype.override = function(o) {
3273             for (var m in o) {
3274                 if (o.hasOwnProperty(m)) {
3275                     this[m] = o[m];
3276                 }
3277             }
3278         };
3279
3280         return cls;
3281     };
3282
3283 })();
3284
3285
3286 (function(Class, alias) {
3287
3288     var slice = Array.prototype.slice;
3289
3290     var Manager = Ext.ClassManager = {
3291
3292         
3293         classes: {},
3294
3295         
3296         existCache: {},
3297
3298         
3299         namespaceRewrites: [{
3300             from: 'Ext.',
3301             to: Ext
3302         }],
3303
3304         
3305         maps: {
3306             alternateToName: {},
3307             aliasToName: {},
3308             nameToAliases: {}
3309         },
3310
3311         
3312         enableNamespaceParseCache: true,
3313
3314         
3315         namespaceParseCache: {},
3316
3317         
3318         instantiators: [],
3319
3320         
3321         instantiationCounts: {},
3322
3323         
3324         isCreated: function(className) {
3325             var i, ln, part, root, parts;
3326
3327             if (typeof className !== 'string' || className.length < 1) {
3328                 Ext.Error.raise({
3329                     sourceClass: "Ext.ClassManager",
3330                     sourceMethod: "exist",
3331                     msg: "Invalid classname, must be a string and must not be empty"
3332                 });
3333             }
3334
3335             if (this.classes.hasOwnProperty(className) || this.existCache.hasOwnProperty(className)) {
3336                 return true;
3337             }
3338
3339             root = Ext.global;
3340             parts = this.parseNamespace(className);
3341
3342             for (i = 0, ln = parts.length; i < ln; i++) {
3343                 part = parts[i];
3344
3345                 if (typeof part !== 'string') {
3346                     root = part;
3347                 } else {
3348                     if (!root || !root[part]) {
3349                         return false;
3350                     }
3351
3352                     root = root[part];
3353                 }
3354             }
3355
3356             Ext.Loader.historyPush(className);
3357
3358             this.existCache[className] = true;
3359
3360             return true;
3361         },
3362
3363         
3364         parseNamespace: function(namespace) {
3365             if (typeof namespace !== 'string') {
3366                 Ext.Error.raise({
3367                     sourceClass: "Ext.ClassManager",
3368                     sourceMethod: "parseNamespace",
3369                     msg: "Invalid namespace, must be a string"
3370                 });
3371             }
3372
3373             var cache = this.namespaceParseCache;
3374
3375             if (this.enableNamespaceParseCache) {
3376                 if (cache.hasOwnProperty(namespace)) {
3377                     return cache[namespace];
3378                 }
3379             }
3380
3381             var parts = [],
3382                 rewrites = this.namespaceRewrites,
3383                 rewrite, from, to, i, ln, root = Ext.global;
3384
3385             for (i = 0, ln = rewrites.length; i < ln; i++) {
3386                 rewrite = rewrites[i];
3387                 from = rewrite.from;
3388                 to = rewrite.to;
3389
3390                 if (namespace === from || namespace.substring(0, from.length) === from) {
3391                     namespace = namespace.substring(from.length);
3392
3393                     if (typeof to !== 'string') {
3394                         root = to;
3395                     } else {
3396                         parts = parts.concat(to.split('.'));
3397                     }
3398
3399                     break;
3400                 }
3401             }
3402
3403             parts.push(root);
3404
3405             parts = parts.concat(namespace.split('.'));
3406
3407             if (this.enableNamespaceParseCache) {
3408                 cache[namespace] = parts;
3409             }
3410
3411             return parts;
3412         },
3413
3414         
3415         setNamespace: function(name, value) {
3416             var root = Ext.global,
3417                 parts = this.parseNamespace(name),
3418                 leaf = parts.pop(),
3419                 i, ln, part;
3420
3421             for (i = 0, ln = parts.length; i < ln; i++) {
3422                 part = parts[i];
3423
3424                 if (typeof part !== 'string') {
3425                     root = part;
3426                 } else {
3427                     if (!root[part]) {
3428                         root[part] = {};
3429                     }
3430
3431                     root = root[part];
3432                 }
3433             }
3434
3435             root[leaf] = value;
3436
3437             return root[leaf];
3438         },
3439
3440         
3441         createNamespaces: function() {
3442             var root = Ext.global,
3443                 parts, part, i, j, ln, subLn;
3444
3445             for (i = 0, ln = arguments.length; i < ln; i++) {
3446                 parts = this.parseNamespace(arguments[i]);
3447
3448                 for (j = 0, subLn = parts.length; j < subLn; j++) {
3449                     part = parts[j];
3450
3451                     if (typeof part !== 'string') {
3452                         root = part;
3453                     } else {
3454                         if (!root[part]) {
3455                             root[part] = {};
3456                         }
3457
3458                         root = root[part];
3459                     }
3460                 }
3461             }
3462
3463             return root;
3464         },
3465
3466         
3467         set: function(name, value) {
3468             var targetName = this.getName(value);
3469
3470             this.classes[name] = this.setNamespace(name, value);
3471
3472             if (targetName && targetName !== name) {
3473                 this.maps.alternateToName[name] = targetName;
3474             }
3475
3476             return this;
3477         },
3478
3479         
3480         get: function(name) {
3481             if (this.classes.hasOwnProperty(name)) {
3482                 return this.classes[name];
3483             }
3484
3485             var root = Ext.global,
3486                 parts = this.parseNamespace(name),
3487                 part, i, ln;
3488
3489             for (i = 0, ln = parts.length; i < ln; i++) {
3490                 part = parts[i];
3491
3492                 if (typeof part !== 'string') {
3493                     root = part;
3494                 } else {
3495                     if (!root || !root[part]) {
3496                         return null;
3497                     }
3498
3499                     root = root[part];
3500                 }
3501             }
3502
3503             return root;
3504         },
3505
3506         
3507         setAlias: function(cls, alias) {
3508             var aliasToNameMap = this.maps.aliasToName,
3509                 nameToAliasesMap = this.maps.nameToAliases,
3510                 className;
3511
3512             if (typeof cls === 'string') {
3513                 className = cls;
3514             } else {
3515                 className = this.getName(cls);
3516             }
3517
3518             if (alias && aliasToNameMap[alias] !== className) {
3519                 if (aliasToNameMap.hasOwnProperty(alias) && Ext.isDefined(Ext.global.console)) {
3520                     Ext.global.console.log("[Ext.ClassManager] Overriding existing alias: '" + alias + "' " +
3521                         "of: '" + aliasToNameMap[alias] + "' with: '" + className + "'. Be sure it's intentional.");
3522                 }
3523
3524                 aliasToNameMap[alias] = className;
3525             }
3526
3527             if (!nameToAliasesMap[className]) {
3528                 nameToAliasesMap[className] = [];
3529             }
3530
3531             if (alias) {
3532                 Ext.Array.include(nameToAliasesMap[className], alias);
3533             }
3534
3535             return this;
3536         },
3537
3538         
3539         getByAlias: function(alias) {
3540             return this.get(this.getNameByAlias(alias));
3541         },
3542
3543         
3544         getNameByAlias: function(alias) {
3545             return this.maps.aliasToName[alias] || '';
3546         },
3547
3548         
3549         getNameByAlternate: function(alternate) {
3550             return this.maps.alternateToName[alternate] || '';
3551         },
3552
3553         
3554         getAliasesByName: function(name) {
3555             return this.maps.nameToAliases[name] || [];
3556         },
3557
3558         
3559         getName: function(object) {
3560             return object && object.$className || '';
3561         },
3562
3563         
3564         getClass: function(object) {
3565             return object && object.self || null;
3566         },
3567
3568         
3569         create: function(className, data, createdFn) {
3570             var manager = this;
3571
3572             if (typeof className !== 'string') {
3573                 Ext.Error.raise({
3574                     sourceClass: "Ext",
3575                     sourceMethod: "define",
3576                     msg: "Invalid class name '" + className + "' specified, must be a non-empty string"
3577                 });
3578             }
3579
3580             data.$className = className;
3581
3582             return new Class(data, function() {
3583                 var postprocessorStack = data.postprocessors || manager.defaultPostprocessors,
3584                     registeredPostprocessors = manager.postprocessors,
3585                     index = 0,
3586                     postprocessors = [],
3587                     postprocessor, postprocessors, process, i, ln;
3588
3589                 delete data.postprocessors;
3590
3591                 for (i = 0, ln = postprocessorStack.length; i < ln; i++) {
3592                     postprocessor = postprocessorStack[i];
3593
3594                     if (typeof postprocessor === 'string') {
3595                         postprocessor = registeredPostprocessors[postprocessor];
3596
3597                         if (!postprocessor.always) {
3598                             if (data[postprocessor.name] !== undefined) {
3599                                 postprocessors.push(postprocessor.fn);
3600                             }
3601                         }
3602                         else {
3603                             postprocessors.push(postprocessor.fn);
3604                         }
3605                     }
3606                     else {
3607                         postprocessors.push(postprocessor);
3608                     }
3609                 }
3610
3611                 process = function(clsName, cls, clsData) {
3612                     postprocessor = postprocessors[index++];
3613
3614                     if (!postprocessor) {
3615                         manager.set(className, cls);
3616
3617                         Ext.Loader.historyPush(className);
3618
3619                         if (createdFn) {
3620                             createdFn.call(cls, cls);
3621                         }
3622
3623                         return;
3624                     }
3625
3626                     if (postprocessor.call(this, clsName, cls, clsData, process) !== false) {
3627                         process.apply(this, arguments);
3628                     }
3629                 };
3630
3631                 process.call(manager, className, this, data);
3632             });
3633         },
3634
3635         
3636         instantiateByAlias: function() {
3637             var alias = arguments[0],
3638                 args = slice.call(arguments),
3639                 className = this.getNameByAlias(alias);
3640
3641             if (!className) {
3642                 className = this.maps.aliasToName[alias];
3643
3644                 if (!className) {
3645                     Ext.Error.raise({
3646                         sourceClass: "Ext",
3647                         sourceMethod: "createByAlias",
3648                         msg: "Cannot create an instance of unrecognized alias: " + alias
3649                     });
3650                 }
3651
3652                 if (Ext.global.console) {
3653                     Ext.global.console.warn("[Ext.Loader] Synchronously loading '" + className + "'; consider adding " +
3654                          "Ext.require('" + alias + "') above Ext.onReady");
3655                 }
3656
3657                 Ext.syncRequire(className);
3658             }
3659
3660             args[0] = className;
3661
3662             return this.instantiate.apply(this, args);
3663         },
3664
3665         
3666         instantiate: function() {
3667             var name = arguments[0],
3668                 args = slice.call(arguments, 1),
3669                 alias = name,
3670                 possibleName, cls;
3671
3672             if (typeof name !== 'function') {
3673                 if ((typeof name !== 'string' || name.length < 1)) {
3674                     Ext.Error.raise({
3675                         sourceClass: "Ext",
3676                         sourceMethod: "create",
3677                         msg: "Invalid class name or alias '" + name + "' specified, must be a non-empty string"
3678                     });
3679                 }
3680
3681                 cls = this.get(name);
3682             }
3683             else {
3684                 cls = name;
3685             }
3686
3687             
3688             if (!cls) {
3689                 possibleName = this.getNameByAlias(name);
3690
3691                 if (possibleName) {
3692                     name = possibleName;
3693
3694                     cls = this.get(name);
3695                 }
3696             }
3697
3698             
3699             if (!cls) {
3700                 possibleName = this.getNameByAlternate(name);
3701
3702                 if (possibleName) {
3703                     name = possibleName;
3704
3705                     cls = this.get(name);
3706                 }
3707             }
3708
3709             
3710             if (!cls) {
3711                 if (Ext.global.console) {
3712                     Ext.global.console.warn("[Ext.Loader] Synchronously loading '" + name + "'; consider adding " +
3713                          "Ext.require('" + ((possibleName) ? alias : name) + "') above Ext.onReady");
3714                 }
3715
3716                 Ext.syncRequire(name);
3717
3718                 cls = this.get(name);
3719             }
3720
3721             if (!cls) {
3722                 Ext.Error.raise({
3723                     sourceClass: "Ext",
3724                     sourceMethod: "create",
3725                     msg: "Cannot create an instance of unrecognized class name / alias: " + alias
3726                 });
3727             }
3728
3729             if (typeof cls !== 'function') {
3730                 Ext.Error.raise({
3731                     sourceClass: "Ext",
3732                     sourceMethod: "create",
3733                     msg: "'" + name + "' is a singleton and cannot be instantiated"
3734                 });
3735             }
3736
3737             if (!this.instantiationCounts[name]) {
3738                 this.instantiationCounts[name] = 0;
3739             }
3740
3741             this.instantiationCounts[name]++;
3742
3743             return this.getInstantiator(args.length)(cls, args);
3744         },
3745
3746         
3747         dynInstantiate: function(name, args) {
3748             args = Ext.Array.from(args, true);
3749             args.unshift(name);
3750
3751             return this.instantiate.apply(this, args);
3752         },
3753
3754         
3755         getInstantiator: function(length) {
3756             if (!this.instantiators[length]) {
3757                 var i = length,
3758                     args = [];
3759
3760                 for (i = 0; i < length; i++) {
3761                     args.push('a['+i+']');
3762                 }
3763
3764                 this.instantiators[length] = new Function('c', 'a', 'return new c('+args.join(',')+')');
3765             }
3766
3767             return this.instantiators[length];
3768         },
3769
3770         
3771         postprocessors: {},
3772
3773         
3774         defaultPostprocessors: [],
3775
3776         
3777         registerPostprocessor: function(name, fn, always) {
3778             this.postprocessors[name] = {
3779                 name: name,
3780                 always: always ||  false,
3781                 fn: fn
3782             };
3783
3784             return this;
3785         },
3786
3787         
3788         setDefaultPostprocessors: function(postprocessors) {
3789             this.defaultPostprocessors = Ext.Array.from(postprocessors);
3790
3791             return this;
3792         },
3793
3794         
3795         setDefaultPostprocessorPosition: function(name, offset, relativeName) {
3796             var defaultPostprocessors = this.defaultPostprocessors,
3797                 index;
3798
3799             if (typeof offset === 'string') {
3800                 if (offset === 'first') {
3801                     defaultPostprocessors.unshift(name);
3802
3803                     return this;
3804                 }
3805                 else if (offset === 'last') {
3806                     defaultPostprocessors.push(name);
3807
3808                     return this;
3809                 }
3810
3811                 offset = (offset === 'after') ? 1 : -1;
3812             }
3813
3814             index = Ext.Array.indexOf(defaultPostprocessors, relativeName);
3815
3816             if (index !== -1) {
3817                 defaultPostprocessors.splice(Math.max(0, index + offset), 0, name);
3818             }
3819
3820             return this;
3821         },
3822
3823         
3824         getNamesByExpression: function(expression) {
3825             var nameToAliasesMap = this.maps.nameToAliases,
3826                 names = [],
3827                 name, alias, aliases, possibleName, regex, i, ln;
3828
3829             if (typeof expression !== 'string' || expression.length < 1) {
3830                 Ext.Error.raise({
3831                     sourceClass: "Ext.ClassManager",
3832                     sourceMethod: "getNamesByExpression",
3833                     msg: "Expression " + expression + " is invalid, must be a non-empty string"
3834                 });
3835             }
3836
3837             if (expression.indexOf('*') !== -1) {
3838                 expression = expression.replace(/\*/g, '(.*?)');
3839                 regex = new RegExp('^' + expression + '$');
3840
3841                 for (name in nameToAliasesMap) {
3842                     if (nameToAliasesMap.hasOwnProperty(name)) {
3843                         aliases = nameToAliasesMap[name];
3844
3845                         if (name.search(regex) !== -1) {
3846                             names.push(name);
3847                         }
3848                         else {
3849                             for (i = 0, ln = aliases.length; i < ln; i++) {
3850                                 alias = aliases[i];
3851
3852                                 if (alias.search(regex) !== -1) {
3853                                     names.push(name);
3854                                     break;
3855                                 }
3856                             }
3857                         }
3858                     }
3859                 }
3860
3861             } else {
3862                 possibleName = this.getNameByAlias(expression);
3863
3864                 if (possibleName) {
3865                     names.push(possibleName);
3866                 } else {
3867                     possibleName = this.getNameByAlternate(expression);
3868
3869                     if (possibleName) {
3870                         names.push(possibleName);
3871                     } else {
3872                         names.push(expression);
3873                     }
3874                 }
3875             }
3876
3877             return names;
3878         }
3879     };
3880
3881     Manager.registerPostprocessor('alias', function(name, cls, data) {
3882         var aliases = data.alias,
3883             widgetPrefix = 'widget.',
3884             i, ln, alias;
3885
3886         if (!(aliases instanceof Array)) {
3887             aliases = [aliases];
3888         }
3889
3890         for (i = 0, ln = aliases.length; i < ln; i++) {
3891             alias = aliases[i];
3892
3893             if (typeof alias !== 'string') {
3894                 Ext.Error.raise({
3895                     sourceClass: "Ext",
3896                     sourceMethod: "define",
3897                     msg: "Invalid alias of: '" + alias + "' for class: '" + name + "'; must be a valid string"
3898                 });
3899             }
3900
3901             this.setAlias(cls, alias);
3902         }
3903
3904         
3905         for (i = 0, ln = aliases.length; i < ln; i++) {
3906             alias = aliases[i];
3907
3908             if (alias.substring(0, widgetPrefix.length) === widgetPrefix) {
3909                 
3910                 cls.xtype = cls.$xtype = alias.substring(widgetPrefix.length);
3911                 break;
3912             }
3913         }
3914     });
3915
3916     Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {
3917         fn.call(this, name, new cls(), data);
3918         return false;
3919     });
3920
3921     Manager.registerPostprocessor('alternateClassName', function(name, cls, data) {
3922         var alternates = data.alternateClassName,
3923             i, ln, alternate;
3924
3925         if (!(alternates instanceof Array)) {
3926             alternates = [alternates];
3927         }
3928
3929         for (i = 0, ln = alternates.length; i < ln; i++) {
3930             alternate = alternates[i];
3931
3932             if (typeof alternate !== 'string') {
3933                 Ext.Error.raise({
3934                     sourceClass: "Ext",
3935                     sourceMethod: "define",
3936                     msg: "Invalid alternate of: '" + alternate + "' for class: '" + name + "'; must be a valid string"
3937                 });
3938             }
3939
3940             this.set(alternate, cls);
3941         }
3942     });
3943
3944     Manager.setDefaultPostprocessors(['alias', 'singleton', 'alternateClassName']);
3945
3946     Ext.apply(Ext, {
3947         
3948         create: alias(Manager, 'instantiate'),
3949
3950         
3951         factory: function(item, namespace) {
3952             if (item instanceof Array) {
3953                 var i, ln;
3954
3955                 for (i = 0, ln = item.length; i < ln; i++) {
3956                     item[i] = Ext.factory(item[i], namespace);
3957                 }
3958
3959                 return item;
3960             }
3961
3962             var isString = (typeof item === 'string');
3963
3964             if (isString || (item instanceof Object && item.constructor === Object)) {
3965                 var name, config = {};
3966
3967                 if (isString) {
3968                     name = item;
3969                 }
3970                 else {
3971                     name = item.className;
3972                     config = item;
3973                     delete config.className;
3974                 }
3975
3976                 if (namespace !== undefined && name.indexOf(namespace) === -1) {
3977                     name = namespace + '.' + Ext.String.capitalize(name);
3978                 }
3979
3980                 return Ext.create(name, config);
3981             }
3982
3983             if (typeof item === 'function') {
3984                 return Ext.create(item);
3985             }
3986
3987             return item;
3988         },
3989
3990         
3991         widget: function(name) {
3992             var args = slice.call(arguments);
3993             args[0] = 'widget.' + name;
3994
3995             return Manager.instantiateByAlias.apply(Manager, args);
3996         },
3997
3998         
3999         createByAlias: alias(Manager, 'instantiateByAlias'),
4000
4001         
4002         define: alias(Manager, 'create'),
4003
4004         
4005         getClassName: alias(Manager, 'getName'),
4006
4007         
4008         getDisplayName: function(object) {
4009             if (object.displayName) {
4010                 return object.displayName;
4011             }
4012
4013             if (object.$name && object.$class) {
4014                 return Ext.getClassName(object.$class) + '#' + object.$name;
4015             }
4016
4017             if (object.$className) {
4018                 return object.$className;
4019             }
4020
4021             return 'Anonymous';
4022         },
4023
4024         
4025         getClass: alias(Manager, 'getClass'),
4026
4027         
4028         namespace: alias(Manager, 'createNamespaces')
4029     });
4030
4031     Ext.createWidget = Ext.widget;
4032
4033     
4034     Ext.ns = Ext.namespace;
4035
4036     Class.registerPreprocessor('className', function(cls, data) {
4037         if (data.$className) {
4038             cls.$className = data.$className;
4039             cls.displayName = cls.$className;
4040         }
4041     }, true);
4042
4043     Class.setDefaultPreprocessorPosition('className', 'first');
4044
4045 })(Ext.Class, Ext.Function.alias);
4046
4047
4048
4049 (function(Manager, Class, flexSetter, alias) {
4050
4051     var
4052         dependencyProperties = ['extend', 'mixins', 'requires'],
4053         Loader;
4054
4055     Loader = Ext.Loader = {
4056         
4057         documentHead: typeof document !== 'undefined' && (document.head || document.getElementsByTagName('head')[0]),
4058
4059         
4060         isLoading: false,
4061
4062         
4063         queue: [],
4064
4065         
4066         isFileLoaded: {},
4067
4068         
4069         readyListeners: [],
4070
4071         
4072         optionalRequires: [],
4073
4074         
4075         requiresMap: {},
4076
4077         
4078         numPendingFiles: 0,
4079
4080         
4081         numLoadedFiles: 0,
4082
4083         
4084         hasFileLoadError: false,
4085
4086         
4087         classNameToFilePathMap: {},
4088
4089         
4090         history: [],
4091
4092         
4093         config: {
4094             
4095             enabled: false,
4096
4097             
4098             disableCaching: true,
4099
4100             
4101             disableCachingParam: '_dc',
4102
4103             
4104             paths: {
4105                 'Ext': '.'
4106             }
4107         },
4108
4109         
4110         setConfig: function(name, value) {
4111             if (Ext.isObject(name) && arguments.length === 1) {
4112                 Ext.Object.merge(this.config, name);
4113             }
4114             else {
4115                 this.config[name] = (Ext.isObject(value)) ? Ext.Object.merge(this.config[name], value) : value;
4116             }
4117
4118             return this;
4119         },
4120
4121         
4122         getConfig: function(name) {
4123             if (name) {
4124                 return this.config[name];
4125             }
4126
4127             return this.config;
4128         },
4129
4130         
4131         setPath: flexSetter(function(name, path) {
4132             this.config.paths[name] = path;
4133
4134             return this;
4135         }),
4136
4137         
4138         getPath: function(className) {
4139             var path = '',
4140                 paths = this.config.paths,
4141                 prefix = this.getPrefix(className);
4142
4143             if (prefix.length > 0) {
4144                 if (prefix === className) {
4145                     return paths[prefix];
4146                 }
4147
4148                 path = paths[prefix];
4149                 className = className.substring(prefix.length + 1);
4150             }
4151
4152             if (path.length > 0) {
4153                 path += '/';
4154             }
4155
4156             return path.replace(/\/\.\//g, '/') + className.replace(/\./g, "/") + '.js';
4157         },
4158
4159         
4160         getPrefix: function(className) {
4161             var paths = this.config.paths,
4162                 prefix, deepestPrefix = '';
4163
4164             if (paths.hasOwnProperty(className)) {
4165                 return className;
4166             }
4167
4168             for (prefix in paths) {
4169                 if (paths.hasOwnProperty(prefix) && prefix + '.' === className.substring(0, prefix.length + 1)) {
4170                     if (prefix.length > deepestPrefix.length) {
4171                         deepestPrefix = prefix;
4172                     }
4173                 }
4174             }
4175
4176             return deepestPrefix;
4177         },
4178
4179         
4180         refreshQueue: function() {
4181             var ln = this.queue.length,
4182                 i, item, j, requires;
4183
4184             if (ln === 0) {
4185                 this.triggerReady();
4186                 return;
4187             }
4188
4189             for (i = 0; i < ln; i++) {
4190                 item = this.queue[i];
4191
4192                 if (item) {
4193                     requires = item.requires;
4194
4195                     
4196                     
4197                     if (requires.length > this.numLoadedFiles) {
4198                         continue;
4199                     }
4200
4201                     j = 0;
4202
4203                     do {
4204                         if (Manager.isCreated(requires[j])) {
4205                             
4206                             requires.splice(j, 1);
4207                         }
4208                         else {
4209                             j++;
4210                         }
4211                     } while (j < requires.length);
4212
4213                     if (item.requires.length === 0) {
4214                         this.queue.splice(i, 1);
4215                         item.callback.call(item.scope);
4216                         this.refreshQueue();
4217                         break;
4218                     }
4219                 }
4220             }
4221
4222             return this;
4223         },
4224
4225         
4226         injectScriptElement: function(url, onLoad, onError, scope) {
4227             var script = document.createElement('script'),
4228                 me = this,
4229                 onLoadFn = function() {
4230                     me.cleanupScriptElement(script);
4231                     onLoad.call(scope);
4232                 },
4233                 onErrorFn = function() {
4234                     me.cleanupScriptElement(script);
4235                     onError.call(scope);
4236                 };
4237
4238             script.type = 'text/javascript';
4239             script.src = url;
4240             script.onload = onLoadFn;
4241             script.onerror = onErrorFn;
4242             script.onreadystatechange = function() {
4243                 if (this.readyState === 'loaded' || this.readyState === 'complete') {
4244                     onLoadFn();
4245                 }
4246             };
4247
4248             this.documentHead.appendChild(script);
4249
4250             return script;
4251         },
4252
4253         
4254         cleanupScriptElement: function(script) {
4255             script.onload = null;
4256             script.onreadystatechange = null;
4257             script.onerror = null;
4258
4259             return this;
4260         },
4261
4262         
4263         loadScriptFile: function(url, onLoad, onError, scope, synchronous) {
4264             var me = this,
4265                 noCacheUrl = url + (this.getConfig('disableCaching') ? ('?' + this.getConfig('disableCachingParam') + '=' + Ext.Date.now()) : ''),
4266                 fileName = url.split('/').pop(),
4267                 isCrossOriginRestricted = false,
4268                 xhr, status, onScriptError;
4269
4270             scope = scope || this;
4271
4272             this.isLoading = true;
4273
4274             if (!synchronous) {
4275                 onScriptError = function() {
4276                     onError.call(scope, "Failed loading '" + url + "', please verify that the file exists", synchronous);
4277                 };
4278
4279                 if (!Ext.isReady && Ext.onDocumentReady) {
4280                     Ext.onDocumentReady(function() {
4281                         me.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
4282                     });
4283                 }
4284                 else {
4285                     this.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
4286                 }
4287             }
4288             else {
4289                 if (typeof XMLHttpRequest !== 'undefined') {
4290                     xhr = new XMLHttpRequest();
4291                 } else {
4292                     xhr = new ActiveXObject('Microsoft.XMLHTTP');
4293                 }
4294
4295                 try {
4296                     xhr.open('GET', noCacheUrl, false);
4297                     xhr.send(null);
4298                 } catch (e) {
4299                     isCrossOriginRestricted = true;
4300                 }
4301
4302                 status = (xhr.status === 1223) ? 204 : xhr.status;
4303
4304                 if (!isCrossOriginRestricted) {
4305                     isCrossOriginRestricted = (status === 0);
4306                 }
4307
4308                 if (isCrossOriginRestricted
4309                 ) {
4310                     onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; It's likely that the file is either " +
4311                                        "being loaded from a different domain or from the local file system whereby cross origin " +
4312                                        "requests are not allowed due to security reasons. Use asynchronous loading with " +
4313                                        "Ext.require instead.", synchronous);
4314                 }
4315                 else if (status >= 200 && status < 300
4316                 ) {
4317                     
4318                     new Function(xhr.responseText + "\n//@ sourceURL=" + fileName)();
4319
4320                     onLoad.call(scope);
4321                 }
4322                 else {
4323                     onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; please " +
4324                                        "verify that the file exists. " +
4325                                        "XHR status code: " + status, synchronous);
4326                 }
4327
4328                 
4329                 xhr = null;
4330             }
4331         },
4332
4333         
4334         exclude: function(excludes) {
4335             var me = this;
4336
4337             return {
4338                 require: function(expressions, fn, scope) {
4339                     return me.require(expressions, fn, scope, excludes);
4340                 },
4341
4342                 syncRequire: function(expressions, fn, scope) {
4343                     return me.syncRequire(expressions, fn, scope, excludes);
4344                 }
4345             };
4346         },
4347
4348         
4349         syncRequire: function() {
4350             this.syncModeEnabled = true;
4351             this.require.apply(this, arguments);
4352             this.refreshQueue();
4353             this.syncModeEnabled = false;
4354         },
4355
4356         
4357         require: function(expressions, fn, scope, excludes) {
4358             var filePath, expression, exclude, className, excluded = {},
4359                 excludedClassNames = [],
4360                 possibleClassNames = [],
4361                 possibleClassName, classNames = [],
4362                 i, j, ln, subLn;
4363
4364             expressions = Ext.Array.from(expressions);
4365             excludes = Ext.Array.from(excludes);
4366
4367             fn = fn || Ext.emptyFn;
4368
4369             scope = scope || Ext.global;
4370
4371             for (i = 0, ln = excludes.length; i < ln; i++) {
4372                 exclude = excludes[i];
4373
4374                 if (typeof exclude === 'string' && exclude.length > 0) {
4375                     excludedClassNames = Manager.getNamesByExpression(exclude);
4376
4377                     for (j = 0, subLn = excludedClassNames.length; j < subLn; j++) {
4378                         excluded[excludedClassNames[j]] = true;
4379                     }
4380                 }
4381             }
4382
4383             for (i = 0, ln = expressions.length; i < ln; i++) {
4384                 expression = expressions[i];
4385
4386                 if (typeof expression === 'string' && expression.length > 0) {
4387                     possibleClassNames = Manager.getNamesByExpression(expression);
4388
4389                     for (j = 0, subLn = possibleClassNames.length; j < subLn; j++) {
4390                         possibleClassName = possibleClassNames[j];
4391
4392                         if (!excluded.hasOwnProperty(possibleClassName) && !Manager.isCreated(possibleClassName)) {
4393                             Ext.Array.include(classNames, possibleClassName);
4394                         }
4395                     }
4396                 }
4397             }
4398
4399             
4400             
4401             if (!this.config.enabled) {
4402                 if (classNames.length > 0) {
4403                     Ext.Error.raise({
4404                         sourceClass: "Ext.Loader",
4405                         sourceMethod: "require",
4406                         msg: "Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " +
4407                              "Missing required class" + ((classNames.length > 1) ? "es" : "") + ": " + classNames.join(', ')
4408                     });
4409                 }
4410             }
4411
4412             if (classNames.length === 0) {
4413                 fn.call(scope);
4414                 return this;
4415             }
4416
4417             this.queue.push({
4418                 requires: classNames,
4419                 callback: fn,
4420                 scope: scope
4421             });
4422
4423             classNames = classNames.slice();
4424
4425             for (i = 0, ln = classNames.length; i < ln; i++) {
4426                 className = classNames[i];
4427
4428                 if (!this.isFileLoaded.hasOwnProperty(className)) {
4429                     this.isFileLoaded[className] = false;
4430
4431                     filePath = this.getPath(className);
4432
4433                     this.classNameToFilePathMap[className] = filePath;
4434
4435                     this.numPendingFiles++;
4436
4437                     this.loadScriptFile(
4438                         filePath,
4439                         Ext.Function.pass(this.onFileLoaded, [className, filePath], this),
4440                         Ext.Function.pass(this.onFileLoadError, [className, filePath]),
4441                         this,
4442                         this.syncModeEnabled
4443                     );
4444                 }
4445             }
4446
4447             return this;
4448         },
4449
4450         
4451         onFileLoaded: function(className, filePath) {
4452             this.numLoadedFiles++;
4453
4454             this.isFileLoaded[className] = true;
4455
4456             this.numPendingFiles--;
4457
4458             if (this.numPendingFiles === 0) {
4459                 this.refreshQueue();
4460             }
4461
4462             if (this.numPendingFiles <= 1) {
4463                 window.status = "Finished loading all dependencies, onReady fired!";
4464             }
4465             else {
4466                 window.status = "Loading dependencies, " + this.numPendingFiles + " files left...";
4467             }
4468
4469             if (!this.syncModeEnabled && this.numPendingFiles === 0 && this.isLoading && !this.hasFileLoadError) {
4470                 var queue = this.queue,
4471                     requires,
4472                     i, ln, j, subLn, missingClasses = [], missingPaths = [];
4473
4474                 for (i = 0, ln = queue.length; i < ln; i++) {
4475                     requires = queue[i].requires;
4476
4477                     for (j = 0, subLn = requires.length; j < ln; j++) {
4478                         if (this.isFileLoaded[requires[j]]) {
4479                             missingClasses.push(requires[j]);
4480                         }
4481                     }
4482                 }
4483
4484                 if (missingClasses.length < 1) {
4485                     return;
4486                 }
4487
4488                 missingClasses = Ext.Array.filter(missingClasses, function(item) {
4489                     return !this.requiresMap.hasOwnProperty(item);
4490                 }, this);
4491
4492                 for (i = 0,ln = missingClasses.length; i < ln; i++) {
4493                     missingPaths.push(this.classNameToFilePathMap[missingClasses[i]]);
4494                 }
4495
4496                 Ext.Error.raise({
4497                     sourceClass: "Ext.Loader",
4498                     sourceMethod: "onFileLoaded",
4499                     msg: "The following classes are not declared even if their files have been " +
4500                             "loaded: '" + missingClasses.join("', '") + "'. Please check the source code of their " +
4501                             "corresponding files for possible typos: '" + missingPaths.join("', '") + "'"
4502                 });
4503             }
4504         },
4505
4506         
4507         onFileLoadError: function(className, filePath, errorMessage, isSynchronous) {
4508             this.numPendingFiles--;
4509             this.hasFileLoadError = true;
4510
4511             Ext.Error.raise({
4512                 sourceClass: "Ext.Loader",
4513                 classToLoad: className,
4514                 loadPath: filePath,
4515                 loadingType: isSynchronous ? 'synchronous' : 'async',
4516                 msg: errorMessage
4517             });
4518         },
4519
4520         
4521         addOptionalRequires: function(requires) {
4522             var optionalRequires = this.optionalRequires,
4523                 i, ln, require;
4524
4525             requires = Ext.Array.from(requires);
4526
4527             for (i = 0, ln = requires.length; i < ln; i++) {
4528                 require = requires[i];
4529
4530                 Ext.Array.include(optionalRequires, require);
4531             }
4532
4533             return this;
4534         },
4535
4536         
4537         triggerReady: function(force) {
4538             var readyListeners = this.readyListeners,
4539                 optionalRequires, listener;
4540
4541             if (this.isLoading || force) {
4542                 this.isLoading = false;
4543
4544                 if (this.optionalRequires.length) {
4545                     
4546                     optionalRequires = Ext.Array.clone(this.optionalRequires);
4547
4548                     
4549                     this.optionalRequires.length = 0;
4550
4551                     this.require(optionalRequires, Ext.Function.pass(this.triggerReady, [true], this), this);
4552                     return this;
4553                 }
4554
4555                 while (readyListeners.length) {
4556                     listener = readyListeners.shift();
4557                     listener.fn.call(listener.scope);
4558
4559                     if (this.isLoading) {
4560                         return this;
4561                     }
4562                 }
4563             }
4564
4565             return this;
4566         },
4567
4568         
4569         onReady: function(fn, scope, withDomReady, options) {
4570             var oldFn;
4571
4572             if (withDomReady !== false && Ext.onDocumentReady) {
4573                 oldFn = fn;
4574
4575                 fn = function() {
4576                     Ext.onDocumentReady(oldFn, scope, options);
4577                 };
4578             }
4579
4580             if (!this.isLoading) {
4581                 fn.call(scope);
4582             }
4583             else {
4584                 this.readyListeners.push({
4585                     fn: fn,
4586                     scope: scope
4587                 });
4588             }
4589         },
4590
4591         
4592         historyPush: function(className) {
4593             if (className && this.isFileLoaded.hasOwnProperty(className)) {
4594                 Ext.Array.include(this.history, className);
4595             }
4596
4597             return this;
4598         }
4599     };
4600
4601     
4602     Ext.require = alias(Loader, 'require');
4603
4604     
4605     Ext.syncRequire = alias(Loader, 'syncRequire');
4606
4607     
4608     Ext.exclude = alias(Loader, 'exclude');
4609
4610     
4611     Ext.onReady = function(fn, scope, options) {
4612         Loader.onReady(fn, scope, true, options);
4613     };
4614
4615     Class.registerPreprocessor('loader', function(cls, data, continueFn) {
4616         var me = this,
4617             dependencies = [],
4618             className = Manager.getName(cls),
4619             i, j, ln, subLn, value, propertyName, propertyValue;
4620
4621         
4622
4623         for (i = 0, ln = dependencyProperties.length; i < ln; i++) {
4624             propertyName = dependencyProperties[i];
4625
4626             if (data.hasOwnProperty(propertyName)) {
4627                 propertyValue = data[propertyName];
4628
4629                 if (typeof propertyValue === 'string') {
4630                     dependencies.push(propertyValue);
4631                 }
4632                 else if (propertyValue instanceof Array) {
4633                     for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
4634                         value = propertyValue[j];
4635
4636                         if (typeof value === 'string') {
4637                             dependencies.push(value);
4638                         }
4639                     }
4640                 }
4641                 else {
4642                     for (j in propertyValue) {
4643                         if (propertyValue.hasOwnProperty(j)) {
4644                             value = propertyValue[j];
4645
4646                             if (typeof value === 'string') {
4647                                 dependencies.push(value);
4648                             }
4649                         }
4650                     }
4651                 }
4652             }
4653         }
4654
4655         if (dependencies.length === 0) {
4656
4657             return;
4658         }
4659
4660         var deadlockPath = [],
4661             requiresMap = Loader.requiresMap,
4662             detectDeadlock;
4663
4664         
4665
4666         if (className) {
4667             requiresMap[className] = dependencies;
4668
4669             detectDeadlock = function(cls) {
4670                 deadlockPath.push(cls);
4671
4672                 if (requiresMap[cls]) {
4673                     if (Ext.Array.contains(requiresMap[cls], className)) {
4674                         Ext.Error.raise({
4675                             sourceClass: "Ext.Loader",
4676                             msg: "Deadlock detected while loading dependencies! '" + className + "' and '" +
4677                                 deadlockPath[1] + "' " + "mutually require each other. Path: " +
4678                                 deadlockPath.join(' -> ') + " -> " + deadlockPath[0]
4679                         });
4680                     }
4681
4682                     for (i = 0, ln = requiresMap[cls].length; i < ln; i++) {
4683                         detectDeadlock(requiresMap[cls][i]);
4684                     }
4685                 }
4686             };
4687
4688             detectDeadlock(className);
4689         }
4690
4691
4692         Loader.require(dependencies, function() {
4693             for (i = 0, ln = dependencyProperties.length; i < ln; i++) {
4694                 propertyName = dependencyProperties[i];
4695
4696                 if (data.hasOwnProperty(propertyName)) {
4697                     propertyValue = data[propertyName];
4698
4699                     if (typeof propertyValue === 'string') {
4700                         data[propertyName] = Manager.get(propertyValue);
4701                     }
4702                     else if (propertyValue instanceof Array) {
4703                         for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
4704                             value = propertyValue[j];
4705
4706                             if (typeof value === 'string') {
4707                                 data[propertyName][j] = Manager.get(value);
4708                             }
4709                         }
4710                     }
4711                     else {
4712                         for (var k in propertyValue) {
4713                             if (propertyValue.hasOwnProperty(k)) {
4714                                 value = propertyValue[k];
4715
4716                                 if (typeof value === 'string') {
4717                                     data[propertyName][k] = Manager.get(value);
4718                                 }
4719                             }
4720                         }
4721                     }
4722                 }
4723             }
4724
4725             continueFn.call(me, cls, data);
4726         });
4727
4728         return false;
4729     }, true);
4730
4731     Class.setDefaultPreprocessorPosition('loader', 'after', 'className');
4732
4733     Manager.registerPostprocessor('uses', function(name, cls, data) {
4734         var uses = Ext.Array.from(data.uses),
4735             items = [],
4736             i, ln, item;
4737
4738         for (i = 0, ln = uses.length; i < ln; i++) {
4739             item = uses[i];
4740
4741             if (typeof item === 'string') {
4742                 items.push(item);
4743             }
4744         }
4745
4746         Loader.addOptionalRequires(items);
4747     });
4748
4749     Manager.setDefaultPostprocessorPosition('uses', 'last');
4750
4751 })(Ext.ClassManager, Ext.Class, Ext.Function.flexSetter, Ext.Function.alias);
4752
4753
4754 Ext.Error = Ext.extend(Error, {
4755     statics: {
4756         
4757         ignore: false,
4758
4759         
4760         raise: function(err){
4761             err = err || {};
4762             if (Ext.isString(err)) {
4763                 err = { msg: err };
4764             }
4765
4766             var method = this.raise.caller;
4767
4768             if (method) {
4769                 if (method.$name) {
4770                     err.sourceMethod = method.$name;
4771                 }
4772                 if (method.$owner) {
4773                     err.sourceClass = method.$owner.$className;
4774                 }
4775             }
4776
4777             if (Ext.Error.handle(err) !== true) {
4778                 var global = Ext.global,
4779                     con = global.console,
4780                     msg = Ext.Error.prototype.toString.call(err),
4781                     noConsoleMsg = 'An uncaught error was raised: "' + msg + 
4782                         '". Use Firebug or Webkit console for additional details.';
4783
4784                 if (con) {
4785                     if (con.dir) {
4786                         con.warn('An uncaught error was raised with the following data:');
4787                         con.dir(err);
4788                     }
4789                     else {
4790                         con.warn(noConsoleMsg);
4791                     }
4792                     if (con.error) {
4793                         con.error(msg);
4794                     }
4795                 }
4796                 else if (global.alert){
4797                     global.alert(noConsoleMsg);
4798                 }
4799                 
4800                 throw new Ext.Error(err);
4801             }
4802         },
4803
4804         
4805         handle: function(){
4806             return Ext.Error.ignore;
4807         }
4808     },
4809
4810     
4811     constructor: function(config){
4812         if (Ext.isString(config)) {
4813             config = { msg: config };
4814         }
4815         Ext.apply(this, config);
4816     },
4817
4818     
4819     toString: function(){
4820         var me = this,
4821             className = me.className ? me.className  : '',
4822             methodName = me.methodName ? '.' + me.methodName + '(): ' : '',
4823             msg = me.msg || '(No description provided)';
4824
4825         return className + methodName + msg;
4826     }
4827 });
4828
4829
4830
4831
4832 Ext.JSON = new(function() {
4833     var useHasOwn = !! {}.hasOwnProperty,
4834     isNative = function() {
4835         var useNative = null;
4836
4837         return function() {
4838             if (useNative === null) {
4839                 useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
4840             }
4841
4842             return useNative;
4843         };
4844     }(),
4845     pad = function(n) {
4846         return n < 10 ? "0" + n : n;
4847     },
4848     doDecode = function(json) {
4849         return eval("(" + json + ')');
4850     },
4851     doEncode = function(o) {
4852         if (!Ext.isDefined(o) || o === null) {
4853             return "null";
4854         } else if (Ext.isArray(o)) {
4855             return encodeArray(o);
4856         } else if (Ext.isDate(o)) {
4857             return Ext.JSON.encodeDate(o);
4858         } else if (Ext.isString(o)) {
4859             return encodeString(o);
4860         } else if (typeof o == "number") {
4861             
4862             return isFinite(o) ? String(o) : "null";
4863         } else if (Ext.isBoolean(o)) {
4864             return String(o);
4865         } else if (Ext.isObject(o)) {
4866             return encodeObject(o);
4867         } else if (typeof o === "function") {
4868             return "null";
4869         }
4870         return 'undefined';
4871     },
4872     m = {
4873         "\b": '\\b',
4874         "\t": '\\t',
4875         "\n": '\\n',
4876         "\f": '\\f',
4877         "\r": '\\r',
4878         '"': '\\"',
4879         "\\": '\\\\',
4880         '\x0b': '\\u000b' 
4881     },
4882     charToReplace = /[\\\"\x00-\x1f\x7f-\uffff]/g,
4883     encodeString = function(s) {
4884         return '"' + s.replace(charToReplace, function(a) {
4885             var c = m[a];
4886             return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
4887         }) + '"';
4888     },
4889     encodeArray = function(o) {
4890         var a = ["[", ""],
4891         
4892         len = o.length,
4893         i;
4894         for (i = 0; i < len; i += 1) {
4895             a.push(doEncode(o[i]), ',');
4896         }
4897         
4898         a[a.length - 1] = ']';
4899         return a.join("");
4900     },
4901     encodeObject = function(o) {
4902         var a = ["{", ""],
4903         
4904         i;
4905         for (i in o) {
4906             if (!useHasOwn || o.hasOwnProperty(i)) {
4907                 a.push(doEncode(i), ":", doEncode(o[i]), ',');
4908             }
4909         }
4910         
4911         a[a.length - 1] = '}';
4912         return a.join("");
4913     };
4914
4915     
4916     this.encodeDate = function(o) {
4917         return '"' + o.getFullYear() + "-" 
4918         + pad(o.getMonth() + 1) + "-"
4919         + pad(o.getDate()) + "T"
4920         + pad(o.getHours()) + ":"
4921         + pad(o.getMinutes()) + ":"
4922         + pad(o.getSeconds()) + '"';
4923     };
4924
4925     
4926     this.encode = function() {
4927         var ec;
4928         return function(o) {
4929             if (!ec) {
4930                 
4931                 ec = isNative() ? JSON.stringify : doEncode;
4932             }
4933             return ec(o);
4934         };
4935     }();
4936
4937
4938     
4939     this.decode = function() {
4940         var dc;
4941         return function(json, safe) {
4942             if (!dc) {
4943                 
4944                 dc = isNative() ? JSON.parse : doDecode;
4945             }
4946             try {
4947                 return dc(json);
4948             } catch (e) {
4949                 if (safe === true) {
4950                     return null;
4951                 }
4952                 Ext.Error.raise({
4953                     sourceClass: "Ext.JSON",
4954                     sourceMethod: "decode",
4955                     msg: "You're trying to decode and invalid JSON String: " + json
4956                 });
4957             }
4958         };
4959     }();
4960
4961 })();
4962
4963 Ext.encode = Ext.JSON.encode;
4964
4965 Ext.decode = Ext.JSON.decode;
4966
4967
4968
4969 Ext.apply(Ext, {
4970     userAgent: navigator.userAgent.toLowerCase(),
4971     cache: {},
4972     idSeed: 1000,
4973     BLANK_IMAGE_URL : 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
4974     isStrict: document.compatMode == "CSS1Compat",
4975     windowId: 'ext-window',
4976     documentId: 'ext-document',
4977
4978     
4979     isReady: false,
4980
4981     
4982     enableGarbageCollector: true,
4983
4984     
4985     enableListenerCollection: true,
4986
4987     
4988     id: function(el, prefix) {
4989         el = Ext.getDom(el, true) || {};
4990         if (el === document) {
4991             el.id = this.documentId;
4992         }
4993         else if (el === window) {
4994             el.id = this.windowId;
4995         }
4996         if (!el.id) {
4997             el.id = (prefix || "ext-gen") + (++Ext.idSeed);
4998         }
4999         return el.id;
5000     },
5001
5002     
5003     getBody: function() {
5004         return Ext.get(document.body || false);
5005     },
5006
5007     
5008     getHead: function() {
5009         var head;
5010
5011         return function() {
5012             if (head == undefined) {
5013                 head = Ext.get(document.getElementsByTagName("head")[0]);
5014             }
5015
5016             return head;
5017         };
5018     }(),
5019
5020     
5021     getDoc: function() {
5022         return Ext.get(document);
5023     },
5024
5025     
5026     getCmp: function(id) {
5027         return Ext.ComponentManager.get(id);
5028     },
5029
5030     
5031     getOrientation: function() {
5032         return window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
5033     },
5034
5035     
5036     destroy: function() {
5037         var ln = arguments.length,
5038         i, arg;
5039
5040         for (i = 0; i < ln; i++) {
5041             arg = arguments[i];
5042             if (arg) {
5043                 if (Ext.isArray(arg)) {
5044                     this.destroy.apply(this, arg);
5045                 }
5046                 else if (Ext.isFunction(arg.destroy)) {
5047                     arg.destroy();
5048                 }
5049                 else if (arg.dom) {
5050                     arg.remove();
5051                 }
5052             }
5053         }
5054     },
5055
5056     
5057     callback: function(callback, scope, args, delay){
5058         if(Ext.isFunction(callback)){
5059             args = args || [];
5060             scope = scope || window;
5061             if (delay) {
5062                 Ext.defer(callback, delay, scope, args);
5063             } else {
5064                 callback.apply(scope, args);
5065             }
5066         }
5067     },
5068
5069     
5070     htmlEncode : function(value) {
5071         return Ext.String.htmlEncode(value);
5072     },
5073
5074     
5075     htmlDecode : function(value) {
5076          return Ext.String.htmlDecode(value);
5077     },
5078
5079     
5080     urlAppend : function(url, s) {
5081         if (!Ext.isEmpty(s)) {
5082             return url + (url.indexOf('?') === -1 ? '?' : '&') + s;
5083         }
5084         return url;
5085     }
5086 });
5087
5088
5089 Ext.ns = Ext.namespace;
5090
5091
5092 window.undefined = window.undefined;
5093
5094 (function(){
5095     var check = function(regex){
5096             return regex.test(Ext.userAgent);
5097         },
5098         docMode = document.documentMode,
5099         isOpera = check(/opera/),
5100         isOpera10_5 = isOpera && check(/version\/10\.5/),
5101         isChrome = check(/\bchrome\b/),
5102         isWebKit = check(/webkit/),
5103         isSafari = !isChrome && check(/safari/),
5104         isSafari2 = isSafari && check(/applewebkit\/4/), 
5105         isSafari3 = isSafari && check(/version\/3/),
5106         isSafari4 = isSafari && check(/version\/4/),
5107         isIE = !isOpera && check(/msie/),
5108         isIE7 = isIE && (check(/msie 7/) || docMode == 7),
5109         isIE8 = isIE && (check(/msie 8/) && docMode != 7 && docMode != 9 || docMode == 8),
5110         isIE9 = isIE && (check(/msie 9/) && docMode != 7 && docMode != 8 || docMode == 9),
5111         isIE6 = isIE && check(/msie 6/),
5112         isGecko = !isWebKit && check(/gecko/),
5113         isGecko3 = isGecko && check(/rv:1\.9/),
5114         isGecko4 = isGecko && check(/rv:2\.0/),
5115         isFF3_0 = isGecko3 && check(/rv:1\.9\.0/),
5116         isFF3_5 = isGecko3 && check(/rv:1\.9\.1/),
5117         isFF3_6 = isGecko3 && check(/rv:1\.9\.2/),
5118         isWindows = check(/windows|win32/),
5119         isMac = check(/macintosh|mac os x/),
5120         isLinux = check(/linux/),
5121         scrollWidth = null;
5122
5123     
5124     try {
5125         document.execCommand("BackgroundImageCache", false, true);
5126     } catch(e) {}
5127
5128     Ext.setVersion('extjs', '4.0.0');
5129     Ext.apply(Ext, {
5130         
5131         SSL_SECURE_URL : Ext.isSecure && isIE ? 'javascript:""' : 'about:blank',
5132
5133         
5134
5135         
5136         scopeResetCSS : Ext.buildSettings.scopeResetCSS,
5137
5138         
5139         enableNestedListenerRemoval : false,
5140
5141         
5142         USE_NATIVE_JSON : false,
5143
5144         
5145         getDom : function(el, strict) {
5146             if (!el || !document) {
5147                 return null;
5148             }
5149             if (el.dom) {
5150                 return el.dom;
5151             } else {
5152                 if (typeof el == 'string') {
5153                     var e = document.getElementById(el);
5154                     
5155                     
5156                     if (e && isIE && strict) {
5157                         if (el == e.getAttribute('id')) {
5158                             return e;
5159                         } else {
5160                             return null;
5161                         }
5162                     }
5163                     return e;
5164                 } else {
5165                     return el;
5166                 }
5167             }
5168         },
5169
5170         
5171         removeNode : isIE6 || isIE7 ? function() {
5172             var d;
5173             return function(n){
5174                 if(n && n.tagName != 'BODY'){
5175                     (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
5176                     d = d || document.createElement('div');
5177                     d.appendChild(n);
5178                     d.innerHTML = '';
5179                     delete Ext.cache[n.id];
5180                 }
5181             };
5182         }() : function(n) {
5183             if (n && n.parentNode && n.tagName != 'BODY') {
5184                 (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
5185                 n.parentNode.removeChild(n);
5186                 delete Ext.cache[n.id];
5187             }
5188         },
5189
5190         
5191         isOpera : isOpera,
5192
5193         
5194         isOpera10_5 : isOpera10_5,
5195
5196         
5197         isWebKit : isWebKit,
5198
5199         
5200         isChrome : isChrome,
5201
5202         
5203         isSafari : isSafari,
5204
5205         
5206         isSafari3 : isSafari3,
5207
5208         
5209         isSafari4 : isSafari4,
5210
5211         
5212         isSafari2 : isSafari2,
5213
5214         
5215         isIE : isIE,
5216
5217         
5218         isIE6 : isIE6,
5219
5220         
5221         isIE7 : isIE7,
5222
5223         
5224         isIE8 : isIE8,
5225
5226         
5227         isIE9 : isIE9,
5228
5229         
5230         isGecko : isGecko,
5231
5232         
5233         isGecko3 : isGecko3,
5234
5235         
5236         isGecko4 : isGecko4,
5237
5238         
5239
5240         isFF3_0 : isFF3_0,
5241         
5242
5243         isFF3_5 : isFF3_5,
5244         
5245         isFF3_6 : isFF3_6,
5246
5247         
5248         isLinux : isLinux,
5249
5250         
5251         isWindows : isWindows,
5252
5253         
5254         isMac : isMac,
5255
5256         
5257         BLANK_IMAGE_URL : (isIE6 || isIE7) ? 'http:/' + '/www.sencha.com/s.gif' : 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
5258
5259         
5260         value : function(v, defaultValue, allowBlank){
5261             return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
5262         },
5263
5264         
5265         escapeRe : function(s) {
5266             return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
5267         },
5268
5269         
5270         addBehaviors : function(o){
5271             if(!Ext.isReady){
5272                 Ext.onReady(function(){
5273                     Ext.addBehaviors(o);
5274                 });
5275             } else {
5276                 var cache = {}, 
5277                     parts,
5278                     b,
5279                     s;
5280                 for (b in o) {
5281                     if ((parts = b.split('@'))[1]) { 
5282                         s = parts[0];
5283                         if(!cache[s]){
5284                             cache[s] = Ext.select(s);
5285                         }
5286                         cache[s].on(parts[1], o[b]);
5287                     }
5288                 }
5289                 cache = null;
5290             }
5291         },
5292
5293         
5294         getScrollBarWidth: function(force){
5295             if(!Ext.isReady){
5296                 return 0;
5297             }
5298
5299             if(force === true || scrollWidth === null){
5300                 
5301                 
5302                 
5303                 var cssClass = Ext.isIE9 ? '' : Ext.baseCSSPrefix + 'hide-offsets';
5304                     
5305                 var div = Ext.getBody().createChild('<div class="' + cssClass + '" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
5306                     child = div.child('div', true);
5307                 var w1 = child.offsetWidth;
5308                 div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
5309                 var w2 = child.offsetWidth;
5310                 div.remove();
5311                 
5312                 scrollWidth = w1 - w2 + 2;
5313             }
5314             return scrollWidth;
5315         },
5316
5317         
5318         copyTo : function(dest, source, names, usePrototypeKeys){
5319             if(typeof names == 'string'){
5320                 names = names.split(/[,;\s]/);
5321             }
5322             Ext.each(names, function(name){
5323                 if(usePrototypeKeys || source.hasOwnProperty(name)){
5324                     dest[name] = source[name];
5325                 }
5326             }, this);
5327             return dest;
5328         },
5329
5330         
5331         destroyMembers : function(o, arg1, arg2, etc){
5332             for (var i = 1, a = arguments, len = a.length; i < len; i++) {
5333                 Ext.destroy(o[a[i]]);
5334                 delete o[a[i]];
5335             }
5336         },
5337
5338         
5339         partition : function(arr, truth){
5340             var ret = [[],[]];
5341             Ext.each(arr, function(v, i, a) {
5342                 ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
5343             });
5344             return ret;
5345         },
5346
5347         
5348         invoke : function(arr, methodName){
5349             var ret = [],
5350                 args = Array.prototype.slice.call(arguments, 2);
5351             Ext.each(arr, function(v,i) {
5352                 if (v && typeof v[methodName] == 'function') {
5353                     ret.push(v[methodName].apply(v, args));
5354                 } else {
5355                     ret.push(undefined);
5356                 }
5357             });
5358             return ret;
5359         },
5360
5361         
5362         zip : function(){
5363             var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
5364                 arrs = parts[0],
5365                 fn = parts[1][0],
5366                 len = Ext.max(Ext.pluck(arrs, "length")),
5367                 ret = [];
5368
5369             for (var i = 0; i < len; i++) {
5370                 ret[i] = [];
5371                 if(fn){
5372                     ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
5373                 }else{
5374                     for (var j = 0, aLen = arrs.length; j < aLen; j++){
5375                         ret[i].push( arrs[j][i] );
5376                     }
5377                 }
5378             }
5379             return ret;
5380         },
5381
5382         
5383         toSentence: function(items, connector) {
5384             var length = items.length;
5385
5386             if (length <= 1) {
5387                 return items[0];
5388             } else {
5389                 var head = items.slice(0, length - 1),
5390                     tail = items[length - 1];
5391
5392                 return Ext.util.Format.format("{0} {1} {2}", head.join(", "), connector || 'and', tail);
5393             }
5394         },
5395
5396         
5397         useShims: isIE6
5398     });
5399 })();
5400
5401
5402 Ext.application = function(config) {
5403     Ext.require('Ext.app.Application');
5404
5405     Ext.onReady(function() {
5406         Ext.create('Ext.app.Application', config);
5407     });
5408 };
5409
5410
5411 (function() {
5412     Ext.ns('Ext.util');
5413
5414     Ext.util.Format = {};
5415     var UtilFormat     = Ext.util.Format,
5416         stripTagsRE    = /<\/?[^>]+>/gi,
5417         stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
5418         nl2brRe        = /\r?\n/g,
5419
5420         
5421         formatCleanRe  = /[^\d\.]/g,
5422
5423         
5424         
5425         I18NFormatCleanRe;
5426
5427     Ext.apply(UtilFormat, {
5428         
5429         thousandSeparator: ',',
5430
5431         
5432         decimalSeparator: '.',
5433
5434         
5435         currencyPrecision: 2,
5436
5437         
5438         currencySign: '$',
5439
5440         
5441         currencyAtEnd: false,
5442
5443         
5444         undef : function(value) {
5445             return value !== undefined ? value : "";
5446         },
5447
5448         
5449         defaultValue : function(value, defaultValue) {
5450             return value !== undefined && value !== '' ? value : defaultValue;
5451         },
5452
5453         
5454         substr : function(value, start, length) {
5455             return String(value).substr(start, length);
5456         },
5457
5458         
5459         lowercase : function(value) {
5460             return String(value).toLowerCase();
5461         },
5462
5463         
5464         uppercase : function(value) {
5465             return String(value).toUpperCase();
5466         },
5467
5468         
5469         usMoney : function(v) {
5470             return UtilFormat.currency(v, '$', 2);
5471         },
5472
5473         
5474         currency: function(v, currencySign, decimals, end) {
5475             var negativeSign = '',
5476                 format = ",0",
5477                 i = 0;
5478             v = v - 0;
5479             if (v < 0) {
5480                 v = -v;
5481                 negativeSign = '-';
5482             }
5483             decimals = decimals || UtilFormat.currencyPrecision;
5484             format += format + (decimals > 0 ? '.' : '');
5485             for (; i < decimals; i++) {
5486                 format += '0';
5487             }
5488             v = UtilFormat.number(v, format); 
5489             if ((end || UtilFormat.currencyAtEnd) === true) {
5490                 return Ext.String.format("{0}{1}{2}", negativeSign, v, currencySign || UtilFormat.currencySign);
5491             } else {
5492                 return Ext.String.format("{0}{1}{2}", negativeSign, currencySign || UtilFormat.currencySign, v);
5493             }
5494         },
5495
5496         
5497         date: function(v, format) {
5498             if (!v) {
5499                 return "";
5500             }
5501             if (!Ext.isDate(v)) {
5502                 v = new Date(Date.parse(v));
5503             }
5504             return Ext.Date.dateFormat(v, format || Ext.Date.defaultFormat);
5505         },
5506
5507         
5508         dateRenderer : function(format) {
5509             return function(v) {
5510                 return UtilFormat.date(v, format);
5511             };
5512         },
5513
5514         
5515         stripTags : function(v) {
5516             return !v ? v : String(v).replace(stripTagsRE, "");
5517         },
5518
5519         
5520         stripScripts : function(v) {
5521             return !v ? v : String(v).replace(stripScriptsRe, "");
5522         },
5523
5524         
5525         fileSize : function(size) {
5526             if (size < 1024) {
5527                 return size + " bytes";
5528             } else if (size < 1048576) {
5529                 return (Math.round(((size*10) / 1024))/10) + " KB";
5530             } else {
5531                 return (Math.round(((size*10) / 1048576))/10) + " MB";
5532             }
5533         },
5534
5535         
5536         math : function(){
5537             var fns = {};
5538
5539             return function(v, a){
5540                 if (!fns[a]) {
5541                     fns[a] = Ext.functionFactory('v', 'return v ' + a + ';');
5542                 }
5543                 return fns[a](v);
5544             };
5545         }(),
5546
5547         
5548         round : function(value, precision) {
5549             var result = Number(value);
5550             if (typeof precision == 'number') {
5551                 precision = Math.pow(10, precision);
5552                 result = Math.round(value * precision) / precision;
5553             }
5554             return result;
5555         },
5556
5557         
5558         number:
5559             function(v, formatString) {
5560             if (!formatString) {
5561                 return v;
5562             }
5563             v = Ext.Number.from(v, NaN);
5564             if (isNaN(v)) {
5565                 return '';
5566             }
5567             var comma = UtilFormat.thousandSeparator,
5568                 dec   = UtilFormat.decimalSeparator,
5569                 i18n  = false,
5570                 neg   = v < 0,
5571                 hasComma,
5572                 psplit;
5573
5574             v = Math.abs(v);
5575
5576             
5577             
5578             
5579             
5580             if (formatString.substr(formatString.length - 2) == '/i') {
5581                 if (!I18NFormatCleanRe) {
5582                     I18NFormatCleanRe = new RegExp('[^\\d\\' + UtilFormat.decimalSeparator + ']','g');
5583                 }
5584                 formatString = formatString.substr(0, formatString.length - 2);
5585                 i18n   = true;
5586                 hasComma = formatString.indexOf(comma) != -1;
5587                 psplit = formatString.replace(I18NFormatCleanRe, '').split(dec);
5588             } else {
5589                 hasComma = formatString.indexOf(',') != -1;
5590                 psplit = formatString.replace(formatCleanRe, '').split('.');
5591             }
5592
5593             if (1 < psplit.length) {
5594                 v = v.toFixed(psplit[1].length);
5595             } else if(2 < psplit.length) {
5596                 Ext.Error.raise({
5597                     sourceClass: "Ext.util.Format",
5598                     sourceMethod: "number",
5599                     value: v,
5600                     formatString: formatString,
5601                     msg: "Invalid number format, should have no more than 1 decimal"
5602                 });
5603             } else {
5604                 v = v.toFixed(0);
5605             }
5606
5607             var fnum = v.toString();
5608
5609             psplit = fnum.split('.');
5610
5611             if (hasComma) {
5612                 var cnum = psplit[0],
5613                     parr = [],
5614                     j    = cnum.length,
5615                     m    = Math.floor(j / 3),
5616                     n    = cnum.length % 3 || 3,
5617                     i;
5618
5619                 for (i = 0; i < j; i += n) {
5620                     if (i !== 0) {
5621                         n = 3;
5622                     }
5623
5624                     parr[parr.length] = cnum.substr(i, n);
5625                     m -= 1;
5626                 }
5627                 fnum = parr.join(comma);
5628                 if (psplit[1]) {
5629                     fnum += dec + psplit[1];
5630                 }
5631             } else {
5632                 if (psplit[1]) {
5633                     fnum = psplit[0] + dec + psplit[1];
5634                 }
5635             }
5636
5637             return (neg ? '-' : '') + formatString.replace(/[\d,?\.?]+/, fnum);
5638         },
5639
5640         
5641         numberRenderer : function(format) {
5642             return function(v) {
5643                 return UtilFormat.number(v, format);
5644             };
5645         },
5646
5647         
5648         plural : function(v, s, p) {
5649             return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
5650         },
5651
5652         
5653         nl2br : function(v) {
5654             return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
5655         },
5656
5657         
5658         capitalize: Ext.String.capitalize,
5659
5660         
5661         ellipsis: Ext.String.ellipsis,
5662
5663         
5664         format: Ext.String.format,
5665
5666         
5667         htmlDecode: Ext.String.htmlDecode,
5668
5669         
5670         htmlEncode: Ext.String.htmlEncode,
5671
5672         
5673         leftPad: Ext.String.leftPad,
5674
5675         
5676         trim : Ext.String.trim,
5677
5678         
5679         parseBox : function(box) {
5680             if (Ext.isNumber(box)) {
5681                 box = box.toString();
5682             }
5683             var parts  = box.split(' '),
5684                 ln = parts.length;
5685
5686             if (ln == 1) {
5687                 parts[1] = parts[2] = parts[3] = parts[0];
5688             }
5689             else if (ln == 2) {
5690                 parts[2] = parts[0];
5691                 parts[3] = parts[1];
5692             }
5693             else if (ln == 3) {
5694                 parts[3] = parts[1];
5695             }
5696
5697             return {
5698                 top   :parseInt(parts[0], 10) || 0,
5699                 right :parseInt(parts[1], 10) || 0,
5700                 bottom:parseInt(parts[2], 10) || 0,
5701                 left  :parseInt(parts[3], 10) || 0
5702             };
5703         },
5704
5705         
5706         escapeRegex : function(s) {
5707             return s.replace(/([\-.*+?\^${}()|\[\]\/\\])/g, "\\$1");
5708         }
5709     });
5710 })();
5711
5712
5713 Ext.ns('Ext.util');
5714
5715 Ext.util.TaskRunner = function(interval) {
5716     interval = interval || 10;
5717     var tasks = [],
5718     removeQueue = [],
5719     id = 0,
5720     running = false,
5721
5722     
5723     stopThread = function() {
5724         running = false;
5725         clearInterval(id);
5726         id = 0;
5727     },
5728
5729     
5730     startThread = function() {
5731         if (!running) {
5732             running = true;
5733             id = setInterval(runTasks, interval);
5734         }
5735     },
5736
5737     
5738     removeTask = function(t) {
5739         removeQueue.push(t);
5740         if (t.onStop) {
5741             t.onStop.apply(t.scope || t);
5742         }
5743     },
5744
5745     
5746     runTasks = function() {
5747         var rqLen = removeQueue.length,
5748             now = new Date().getTime(),
5749             i;
5750
5751         if (rqLen > 0) {
5752             for (i = 0; i < rqLen; i++) {
5753                 Ext.Array.remove(tasks, removeQueue[i]);
5754             }
5755             removeQueue = [];
5756             if (tasks.length < 1) {
5757                 stopThread();
5758                 return;
5759             }
5760         }
5761         i = 0;
5762         var t,
5763             itime,
5764             rt,
5765             len = tasks.length;
5766         for (; i < len; ++i) {
5767             t = tasks[i];
5768             itime = now - t.taskRunTime;
5769             if (t.interval <= itime) {
5770                 rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
5771                 t.taskRunTime = now;
5772                 if (rt === false || t.taskRunCount === t.repeat) {
5773                     removeTask(t);
5774                     return;
5775                 }
5776             }
5777             if (t.duration && t.duration <= (now - t.taskStartTime)) {
5778                 removeTask(t);
5779             }
5780         }
5781     };
5782
5783     
5784     this.start = function(task) {
5785         tasks.push(task);
5786         task.taskStartTime = new Date().getTime();
5787         task.taskRunTime = 0;
5788         task.taskRunCount = 0;
5789         startThread();
5790         return task;
5791     };
5792
5793     
5794     this.stop = function(task) {
5795         removeTask(task);
5796         return task;
5797     };
5798
5799     
5800     this.stopAll = function() {
5801         stopThread();
5802         for (var i = 0, len = tasks.length; i < len; i++) {
5803             if (tasks[i].onStop) {
5804                 tasks[i].onStop();
5805             }
5806         }
5807         tasks = [];
5808         removeQueue = [];
5809     };
5810 };
5811
5812
5813 Ext.TaskManager = Ext.create('Ext.util.TaskRunner');
5814
5815 Ext.is = {
5816     init : function(navigator) {
5817         var platforms = this.platforms,
5818             ln = platforms.length,
5819             i, platform;
5820
5821         navigator = navigator || window.navigator;
5822
5823         for (i = 0; i < ln; i++) {
5824             platform = platforms[i];
5825             this[platform.identity] = platform.regex.test(navigator[platform.property]);
5826         }
5827
5828         
5829         this.Desktop = this.Mac || this.Windows || (this.Linux && !this.Android);
5830         
5831         this.Tablet = this.iPad;
5832         
5833         this.Phone = !this.Desktop && !this.Tablet;
5834         
5835         this.iOS = this.iPhone || this.iPad || this.iPod;
5836         
5837         
5838         this.Standalone = !!window.navigator.standalone;
5839     },
5840     
5841     
5842     platforms: [{
5843         property: 'platform',
5844         regex: /iPhone/i,
5845         identity: 'iPhone'
5846     },
5847     
5848     
5849     {
5850         property: 'platform',
5851         regex: /iPod/i,
5852         identity: 'iPod'
5853     },
5854     
5855     
5856     {
5857         property: 'userAgent',
5858         regex: /iPad/i,
5859         identity: 'iPad'
5860     },
5861     
5862     
5863     {
5864         property: 'userAgent',
5865         regex: /Blackberry/i,
5866         identity: 'Blackberry'
5867     },
5868     
5869     
5870     {
5871         property: 'userAgent',
5872         regex: /Android/i,
5873         identity: 'Android'
5874     },
5875     
5876     
5877     {
5878         property: 'platform',
5879         regex: /Mac/i,
5880         identity: 'Mac'
5881     },
5882     
5883     
5884     {
5885         property: 'platform',
5886         regex: /Win/i,
5887         identity: 'Windows'
5888     },
5889     
5890     
5891     {
5892         property: 'platform',
5893         regex: /Linux/i,
5894         identity: 'Linux'
5895     }]
5896 };
5897
5898 Ext.is.init();
5899
5900
5901 Ext.supports = {
5902     init : function() {
5903         var doc = document,
5904             div = doc.createElement('div'),
5905             tests = this.tests,
5906             ln = tests.length,
5907             i, test;
5908
5909         div.innerHTML = [
5910             '<div style="height:30px;width:50px;">',
5911                 '<div style="height:20px;width:20px;"></div>',
5912             '</div>',
5913             '<div style="width: 200px; height: 200px; position: relative; padding: 5px;">',
5914                 '<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></div>',
5915             '</div>',
5916             '<div style="float:left; background-color:transparent;"></div>'
5917         ].join('');
5918
5919         doc.body.appendChild(div);
5920
5921         for (i = 0; i < ln; i++) {
5922             test = tests[i];
5923             this[test.identity] = test.fn.call(this, doc, div);
5924         }
5925
5926         doc.body.removeChild(div);
5927     },
5928
5929     
5930     CSS3BoxShadow: Ext.isDefined(document.documentElement.style.boxShadow),
5931
5932     
5933     ClassList: !!document.documentElement.classList,
5934
5935     
5936     OrientationChange: ((typeof window.orientation != 'undefined') && ('onorientationchange' in window)),
5937     
5938     
5939     DeviceMotion: ('ondevicemotion' in window),
5940     
5941     
5942     
5943     
5944     Touch: ('ontouchstart' in window) && (!Ext.is.Desktop),
5945
5946     tests: [
5947         
5948         {
5949             identity: 'Transitions',
5950             fn: function(doc, div) {
5951                 var prefix = [
5952                         'webkit',
5953                         'Moz',
5954                         'o',
5955                         'ms',
5956                         'khtml'
5957                     ],
5958                     TE = 'TransitionEnd',
5959                     transitionEndName = [
5960                         prefix[0] + TE,
5961                         'transitionend', 
5962                         prefix[2] + TE,
5963                         prefix[3] + TE,
5964                         prefix[4] + TE
5965                     ],
5966                     ln = prefix.length,
5967                     i = 0,
5968                     out = false;
5969                 div = Ext.get(div);
5970                 for (; i < ln; i++) {
5971                     if (div.getStyle(prefix[i] + "TransitionProperty")) {
5972                         Ext.supports.CSS3Prefix = prefix[i];
5973                         Ext.supports.CSS3TransitionEnd = transitionEndName[i];
5974                         out = true;
5975                         break;
5976                     }
5977                 }
5978                 return out;
5979             }
5980         },
5981         
5982         
5983         {
5984             identity: 'RightMargin',
5985             fn: function(doc, div, view) {
5986                 view = doc.defaultView;
5987                 return !(view && view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px');
5988             }
5989         },
5990         
5991         
5992         {
5993             identity: 'TransparentColor',
5994             fn: function(doc, div, view) {
5995                 view = doc.defaultView;
5996                 return !(view && view.getComputedStyle(div.lastChild, null).backgroundColor != 'transparent');
5997             }
5998         },
5999
6000         
6001         {
6002             identity: 'ComputedStyle',
6003             fn: function(doc, div, view) {
6004                 view = doc.defaultView;
6005                 return view && view.getComputedStyle;
6006             }
6007         },
6008         
6009         
6010         {
6011             identity: 'Svg',
6012             fn: function(doc) {
6013                 return !!doc.createElementNS && !!doc.createElementNS( "http:/" + "/www.w3.org/2000/svg", "svg").createSVGRect;
6014             }
6015         },
6016     
6017         
6018         {
6019             identity: 'Canvas',
6020             fn: function(doc) {
6021                 return !!doc.createElement('canvas').getContext;
6022             }
6023         },
6024         
6025         
6026         {
6027             identity: 'Vml',
6028             fn: function(doc) {
6029                 var d = doc.createElement("div");
6030                 d.innerHTML = "<!--[if vml]><br><br><![endif]-->";
6031                 return (d.childNodes.length == 2);
6032             }
6033         },
6034         
6035         
6036         {
6037             identity: 'Float',
6038             fn: function(doc, div) {
6039                 return !!div.lastChild.style.cssFloat;
6040             }
6041         },
6042         
6043         
6044         {
6045             identity: 'AudioTag',
6046             fn: function(doc) {
6047                 return !!doc.createElement('audio').canPlayType;
6048             }
6049         },
6050         
6051         
6052         {
6053             identity: 'History',
6054             fn: function() {
6055                 return !!(window.history && history.pushState);
6056             }
6057         },
6058         
6059         
6060         {
6061             identity: 'CSS3DTransform',
6062             fn: function() {
6063                 return (typeof WebKitCSSMatrix != 'undefined' && new WebKitCSSMatrix().hasOwnProperty('m41'));
6064             }
6065         },
6066
6067                 
6068         {
6069             identity: 'CSS3LinearGradient',
6070             fn: function(doc, div) {
6071                 var property = 'background-image:',
6072                     webkit   = '-webkit-gradient(linear, left top, right bottom, from(black), to(white))',
6073                     w3c      = 'linear-gradient(left top, black, white)',
6074                     moz      = '-moz-' + w3c,
6075                     options  = [property + webkit, property + w3c, property + moz];
6076                 
6077                 div.style.cssText = options.join(';');
6078                 
6079                 return ("" + div.style.backgroundImage).indexOf('gradient') !== -1;
6080             }
6081         },
6082         
6083         
6084         {
6085             identity: 'CSS3BorderRadius',
6086             fn: function(doc, div) {
6087                 var domPrefixes = ['borderRadius', 'BorderRadius', 'MozBorderRadius', 'WebkitBorderRadius', 'OBorderRadius', 'KhtmlBorderRadius'],
6088                     pass = false,
6089                     i;
6090                 for (i = 0; i < domPrefixes.length; i++) {
6091                     if (document.body.style[domPrefixes[i]] !== undefined) {
6092                         return true;
6093                     }
6094                 }
6095                 return pass;
6096             }
6097         },
6098         
6099         
6100         {
6101             identity: 'GeoLocation',
6102             fn: function() {
6103                 return (typeof navigator != 'undefined' && typeof navigator.geolocation != 'undefined') || (typeof google != 'undefined' && typeof google.gears != 'undefined');
6104             }
6105         },
6106         
6107         {
6108             identity: 'MouseEnterLeave',
6109             fn: function(doc, div){
6110                 return ('onmouseenter' in div && 'onmouseleave' in div);
6111             }
6112         },
6113         
6114         {
6115             identity: 'MouseWheel',
6116             fn: function(doc, div) {
6117                 return ('onmousewheel' in div);
6118             }
6119         },
6120         
6121         {
6122             identity: 'Opacity',
6123             fn: function(doc, div){
6124                 
6125                 if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
6126                     return false;
6127                 }
6128                 div.firstChild.style.cssText = 'opacity:0.73';
6129                 return div.firstChild.style.opacity == '0.73';
6130             }
6131         },
6132         
6133         {
6134             identity: 'Placeholder',
6135             fn: function(doc) {
6136                 return 'placeholder' in doc.createElement('input');
6137             }
6138         },
6139         
6140         
6141         {
6142             identity: 'Direct2DBug',
6143             fn: function() {
6144                 return Ext.isString(document.body.style.msTransformOrigin);
6145             }
6146         },
6147         
6148         {
6149             identity: 'BoundingClientRect',
6150             fn: function(doc, div) {
6151                 return Ext.isFunction(div.getBoundingClientRect);
6152             }
6153         },
6154         {
6155             identity: 'IncludePaddingInWidthCalculation',
6156             fn: function(doc, div){
6157                 var el = Ext.get(div.childNodes[1].firstChild);
6158                 return el.getWidth() == 210;
6159             }
6160         },
6161         {
6162             identity: 'IncludePaddingInHeightCalculation',
6163             fn: function(doc, div){
6164                 var el = Ext.get(div.childNodes[1].firstChild);
6165                 return el.getHeight() == 210;
6166             }
6167         },
6168         
6169         
6170         {
6171             identity: 'ArraySort',
6172             fn: function() {
6173                 var a = [1,2,3,4,5].sort(function(){ return 0; });
6174                 return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
6175             }
6176         },
6177         
6178         {
6179             identity: 'Range',
6180             fn: function() {
6181                 return !!document.createRange;
6182             }
6183         },
6184         
6185         {
6186             identity: 'CreateContextualFragment',
6187             fn: function() {
6188                 var range = Ext.supports.Range ? document.createRange() : false;
6189                 
6190                 return range && !!range.createContextualFragment;
6191             }
6192         }
6193         
6194     ]
6195 };
6196
6197
6198
6199
6200
6201 Ext.ns('Ext.core');
6202 Ext.core.DomHelper = function(){
6203     var tempTableEl = null,
6204         emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
6205         tableRe = /^table|tbody|tr|td$/i,
6206         confRe = /tag|children|cn|html$/i,
6207         tableElRe = /td|tr|tbody/i,
6208         endRe = /end/i,
6209         pub,
6210         
6211         afterbegin = 'afterbegin',
6212         afterend = 'afterend',
6213         beforebegin = 'beforebegin',
6214         beforeend = 'beforeend',
6215         ts = '<table>',
6216         te = '</table>',
6217         tbs = ts+'<tbody>',
6218         tbe = '</tbody>'+te,
6219         trs = tbs + '<tr>',
6220         tre = '</tr>'+tbe;
6221
6222     
6223     function doInsert(el, o, returnElement, pos, sibling, append){
6224         el = Ext.getDom(el);
6225         var newNode;
6226         if (pub.useDom) {
6227             newNode = createDom(o, null);
6228             if (append) {
6229                 el.appendChild(newNode);
6230             } else {
6231                 (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
6232             }
6233         } else {
6234             newNode = Ext.core.DomHelper.insertHtml(pos, el, Ext.core.DomHelper.createHtml(o));
6235         }
6236         return returnElement ? Ext.get(newNode, true) : newNode;
6237     }
6238     
6239     function createDom(o, parentNode){
6240         var el,
6241             doc = document,
6242             useSet,
6243             attr,
6244             val,
6245             cn;
6246
6247         if (Ext.isArray(o)) {                       
6248             el = doc.createDocumentFragment(); 
6249             for (var i = 0, l = o.length; i < l; i++) {
6250                 createDom(o[i], el);
6251             }
6252         } else if (typeof o == 'string') {         
6253             el = doc.createTextNode(o);
6254         } else {
6255             el = doc.createElement( o.tag || 'div' );
6256             useSet = !!el.setAttribute; 
6257             for (attr in o) {
6258                 if(!confRe.test(attr)){
6259                     val = o[attr];
6260                     if(attr == 'cls'){
6261                         el.className = val;
6262                     }else{
6263                         if(useSet){
6264                             el.setAttribute(attr, val);
6265                         }else{
6266                             el[attr] = val;
6267                         }
6268                     }
6269                 }
6270             }
6271             Ext.core.DomHelper.applyStyles(el, o.style);
6272
6273             if ((cn = o.children || o.cn)) {
6274                 createDom(cn, el);
6275             } else if (o.html) {
6276                 el.innerHTML = o.html;
6277             }
6278         }
6279         if(parentNode){
6280            parentNode.appendChild(el);
6281         }
6282         return el;
6283     }
6284
6285     
6286     function createHtml(o){
6287         var b = '',
6288             attr,
6289             val,
6290             key,
6291             cn,
6292             i;
6293
6294         if(typeof o == "string"){
6295             b = o;
6296         } else if (Ext.isArray(o)) {
6297             for (i=0; i < o.length; i++) {
6298                 if(o[i]) {
6299                     b += createHtml(o[i]);
6300                 }
6301             }
6302         } else {
6303             b += '<' + (o.tag = o.tag || 'div');
6304             for (attr in o) {
6305                 val = o[attr];
6306                 if(!confRe.test(attr)){
6307                     if (typeof val == "object") {
6308                         b += ' ' + attr + '="';
6309                         for (key in val) {
6310                             b += key + ':' + val[key] + ';';
6311                         }
6312                         b += '"';
6313                     }else{
6314                         b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
6315                     }
6316                 }
6317             }
6318             
6319             if (emptyTags.test(o.tag)) {
6320                 b += '/>';
6321             } else {
6322                 b += '>';
6323                 if ((cn = o.children || o.cn)) {
6324                     b += createHtml(cn);
6325                 } else if(o.html){
6326                     b += o.html;
6327                 }
6328                 b += '</' + o.tag + '>';
6329             }
6330         }
6331         return b;
6332     }
6333
6334     function ieTable(depth, s, h, e){
6335         tempTableEl.innerHTML = [s, h, e].join('');
6336         var i = -1,
6337             el = tempTableEl,
6338             ns;
6339         while(++i < depth){
6340             el = el.firstChild;
6341         }
6342
6343         ns = el.nextSibling;
6344         if (ns){
6345             var df = document.createDocumentFragment();
6346             while(el){
6347                 ns = el.nextSibling;
6348                 df.appendChild(el);
6349                 el = ns;
6350             }
6351             el = df;
6352         }
6353         return el;
6354     }
6355
6356     
6357     function insertIntoTable(tag, where, el, html) {
6358         var node,
6359             before;
6360
6361         tempTableEl = tempTableEl || document.createElement('div');
6362
6363         if(tag == 'td' && (where == afterbegin || where == beforeend) ||
6364            !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
6365             return null;
6366         }
6367         before = where == beforebegin ? el :
6368                  where == afterend ? el.nextSibling :
6369                  where == afterbegin ? el.firstChild : null;
6370
6371         if (where == beforebegin || where == afterend) {
6372             el = el.parentNode;
6373         }
6374
6375         if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
6376             node = ieTable(4, trs, html, tre);
6377         } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
6378                    (tag == 'tr' && (where == beforebegin || where == afterend))) {
6379             node = ieTable(3, tbs, html, tbe);
6380         } else {
6381             node = ieTable(2, ts, html, te);
6382         }
6383         el.insertBefore(node, before);
6384         return node;
6385     }
6386     
6387        
6388     function createContextualFragment(html){
6389         var div = document.createElement("div"),
6390             fragment = document.createDocumentFragment(),
6391             i = 0,
6392             length, childNodes;
6393         
6394         div.innerHTML = html;
6395         childNodes = div.childNodes;
6396         length = childNodes.length;
6397
6398         for (; i < length; i++) {
6399             fragment.appendChild(childNodes[i].cloneNode(true));
6400         }
6401
6402         return fragment;
6403     }
6404     
6405     pub = {
6406         
6407         markup : function(o){
6408             return createHtml(o);
6409         },
6410
6411         
6412         applyStyles : function(el, styles){
6413             if (styles) {
6414                 el = Ext.fly(el);
6415                 if (typeof styles == "function") {
6416                     styles = styles.call();
6417                 }
6418                 if (typeof styles == "string") {
6419                     styles = Ext.core.Element.parseStyles(styles);
6420                 }
6421                 if (typeof styles == "object") {
6422                     el.setStyle(styles);
6423                 }
6424             }
6425         },
6426
6427         
6428         insertHtml : function(where, el, html){
6429             var hash = {},
6430                 hashVal,
6431                 range,
6432                 rangeEl,
6433                 setStart,
6434                 frag,
6435                 rs;
6436
6437             where = where.toLowerCase();
6438             
6439             hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
6440             hash[afterend] = ['AfterEnd', 'nextSibling'];
6441             
6442             
6443             if (el.insertAdjacentHTML) {
6444                 if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
6445                     return rs;
6446                 }
6447                 
6448                 
6449                 hash[afterbegin] = ['AfterBegin', 'firstChild'];
6450                 hash[beforeend] = ['BeforeEnd', 'lastChild'];
6451                 if ((hashVal = hash[where])) {
6452                     el.insertAdjacentHTML(hashVal[0], html);
6453                     return el[hashVal[1]];
6454                 }
6455             
6456             } else {
6457                 
6458                 if (Ext.isTextNode(el)) {
6459                     where = where === 'afterbegin' ? 'beforebegin' : where; 
6460                     where = where === 'beforeend' ? 'afterend' : where;
6461                 }
6462                 range = Ext.supports.CreateContextualFragment ? el.ownerDocument.createRange() : undefined;
6463                 setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
6464                 if (hash[where]) {
6465                     if (range) {
6466                         range[setStart](el);
6467                         frag = range.createContextualFragment(html);
6468                     } else {
6469                         frag = createContextualFragment(html);
6470                     }
6471                     el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
6472                     return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
6473                 } else {
6474                     rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
6475                     if (el.firstChild) {
6476                         if (range) {
6477                             range[setStart](el[rangeEl]);
6478                             frag = range.createContextualFragment(html);
6479                         } else {
6480                             frag = createContextualFragment(html);
6481                         }
6482                         
6483                         if(where == afterbegin){
6484                             el.insertBefore(frag, el.firstChild);
6485                         }else{
6486                             el.appendChild(frag);
6487                         }
6488                     } else {
6489                         el.innerHTML = html;
6490                     }
6491                     return el[rangeEl];
6492                 }
6493             }
6494             Ext.Error.raise({
6495                 sourceClass: 'Ext.core.DomHelper',
6496                 sourceMethod: 'insertHtml',
6497                 htmlToInsert: html,
6498                 targetElement: el,
6499                 msg: 'Illegal insertion point reached: "' + where + '"'
6500             });
6501         },
6502
6503         
6504         insertBefore : function(el, o, returnElement){
6505             return doInsert(el, o, returnElement, beforebegin);
6506         },
6507
6508         
6509         insertAfter : function(el, o, returnElement){
6510             return doInsert(el, o, returnElement, afterend, 'nextSibling');
6511         },
6512
6513         
6514         insertFirst : function(el, o, returnElement){
6515             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
6516         },
6517
6518         
6519         append : function(el, o, returnElement){
6520             return doInsert(el, o, returnElement, beforeend, '', true);
6521         },
6522
6523         
6524         overwrite : function(el, o, returnElement){
6525             el = Ext.getDom(el);
6526             el.innerHTML = createHtml(o);
6527             return returnElement ? Ext.get(el.firstChild) : el.firstChild;
6528         },
6529
6530         createHtml : createHtml,
6531         
6532         
6533         createDom: createDom,
6534         
6535         
6536         useDom : false,
6537         
6538         
6539         createTemplate : function(o){
6540             var html = Ext.core.DomHelper.createHtml(o);
6541             return Ext.create('Ext.Template', html);
6542         }
6543     };
6544     return pub;
6545 }();
6546
6547
6548
6549 Ext.ns('Ext.core');
6550
6551 Ext.core.DomQuery = Ext.DomQuery = function(){
6552     var cache = {},
6553         simpleCache = {},
6554         valueCache = {},
6555         nonSpace = /\S/,
6556         trimRe = /^\s+|\s+$/g,
6557         tplRe = /\{(\d+)\}/g,
6558         modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
6559         tagTokenRe = /^(#)?([\w-\*]+)/,
6560         nthRe = /(\d*)n\+?(\d*)/,
6561         nthRe2 = /\D/,
6562         
6563     
6564     
6565     isIE = window.ActiveXObject ? true : false,
6566     key = 30803;
6567
6568     
6569     
6570     eval("var batch = 30803;");
6571
6572     
6573     
6574     function child(parent, index){
6575         var i = 0,
6576             n = parent.firstChild;
6577         while(n){
6578             if(n.nodeType == 1){
6579                if(++i == index){
6580                    return n;
6581                }
6582             }
6583             n = n.nextSibling;
6584         }
6585         return null;
6586     }
6587
6588     
6589     function next(n){
6590         while((n = n.nextSibling) && n.nodeType != 1);
6591         return n;
6592     }
6593
6594     
6595     function prev(n){
6596         while((n = n.previousSibling) && n.nodeType != 1);
6597         return n;
6598     }
6599
6600     
6601     
6602     function children(parent){
6603         var n = parent.firstChild,
6604         nodeIndex = -1,
6605         nextNode;
6606         while(n){
6607             nextNode = n.nextSibling;
6608             
6609             if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
6610             parent.removeChild(n);
6611             }else{
6612             
6613             n.nodeIndex = ++nodeIndex;
6614             }
6615             n = nextNode;
6616         }
6617         return this;
6618     }
6619
6620
6621     
6622     
6623     function byClassName(nodeSet, cls){
6624         if(!cls){
6625             return nodeSet;
6626         }
6627         var result = [], ri = -1;
6628         for(var i = 0, ci; ci = nodeSet[i]; i++){
6629             if((' '+ci.className+' ').indexOf(cls) != -1){
6630                 result[++ri] = ci;
6631             }
6632         }
6633         return result;
6634     };
6635
6636     function attrValue(n, attr){
6637         
6638         if(!n.tagName && typeof n.length != "undefined"){
6639             n = n[0];
6640         }
6641         if(!n){
6642             return null;
6643         }
6644
6645         if(attr == "for"){
6646             return n.htmlFor;
6647         }
6648         if(attr == "class" || attr == "className"){
6649             return n.className;
6650         }
6651         return n.getAttribute(attr) || n[attr];
6652
6653     };
6654
6655
6656     
6657     
6658     
6659     function getNodes(ns, mode, tagName){
6660         var result = [], ri = -1, cs;
6661         if(!ns){
6662             return result;
6663         }
6664         tagName = tagName || "*";
6665         
6666         if(typeof ns.getElementsByTagName != "undefined"){
6667             ns = [ns];
6668         }
6669
6670         
6671         
6672         if(!mode){
6673             for(var i = 0, ni; ni = ns[i]; i++){
6674                 cs = ni.getElementsByTagName(tagName);
6675                 for(var j = 0, ci; ci = cs[j]; j++){
6676                     result[++ri] = ci;
6677                 }
6678             }
6679         
6680         
6681         } else if(mode == "/" || mode == ">"){
6682             var utag = tagName.toUpperCase();
6683             for(var i = 0, ni, cn; ni = ns[i]; i++){
6684                 cn = ni.childNodes;
6685                 for(var j = 0, cj; cj = cn[j]; j++){
6686                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
6687                         result[++ri] = cj;
6688                     }
6689                 }
6690             }
6691         
6692         
6693         }else if(mode == "+"){
6694             var utag = tagName.toUpperCase();
6695             for(var i = 0, n; n = ns[i]; i++){
6696                 while((n = n.nextSibling) && n.nodeType != 1);
6697                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
6698                     result[++ri] = n;
6699                 }
6700             }
6701         
6702         
6703         }else if(mode == "~"){
6704             var utag = tagName.toUpperCase();
6705             for(var i = 0, n; n = ns[i]; i++){
6706                 while((n = n.nextSibling)){
6707                     if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
6708                         result[++ri] = n;
6709                     }
6710                 }
6711             }
6712         }
6713         return result;
6714     }
6715
6716     function concat(a, b){
6717         if(b.slice){
6718             return a.concat(b);
6719         }
6720         for(var i = 0, l = b.length; i < l; i++){
6721             a[a.length] = b[i];
6722         }
6723         return a;
6724     }
6725
6726     function byTag(cs, tagName){
6727         if(cs.tagName || cs == document){
6728             cs = [cs];
6729         }
6730         if(!tagName){
6731             return cs;
6732         }
6733         var result = [], ri = -1;
6734         tagName = tagName.toLowerCase();
6735         for(var i = 0, ci; ci = cs[i]; i++){
6736             if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
6737                 result[++ri] = ci;
6738             }
6739         }
6740         return result;
6741     }
6742
6743     function byId(cs, id){
6744         if(cs.tagName || cs == document){
6745             cs = [cs];
6746         }
6747         if(!id){
6748             return cs;
6749         }
6750         var result = [], ri = -1;
6751         for(var i = 0, ci; ci = cs[i]; i++){
6752             if(ci && ci.id == id){
6753                 result[++ri] = ci;
6754                 return result;
6755             }
6756         }
6757         return result;
6758     }
6759
6760     
6761     
6762     function byAttribute(cs, attr, value, op, custom){
6763         var result = [],
6764             ri = -1,
6765             useGetStyle = custom == "{",
6766             fn = Ext.DomQuery.operators[op],
6767             a,
6768             xml,
6769             hasXml;
6770
6771         for(var i = 0, ci; ci = cs[i]; i++){
6772             
6773             if(ci.nodeType != 1){
6774                 continue;
6775             }
6776             
6777             if(!hasXml){
6778                 xml = Ext.DomQuery.isXml(ci);
6779                 hasXml = true;
6780             }
6781
6782             
6783             if(!xml){
6784                 if(useGetStyle){
6785                     a = Ext.DomQuery.getStyle(ci, attr);
6786                 } else if (attr == "class" || attr == "className"){
6787                     a = ci.className;
6788                 } else if (attr == "for"){
6789                     a = ci.htmlFor;
6790                 } else if (attr == "href"){
6791                     
6792                     
6793                     a = ci.getAttribute("href", 2);
6794                 } else{
6795                     a = ci.getAttribute(attr);
6796                 }
6797             }else{
6798                 a = ci.getAttribute(attr);
6799             }
6800             if((fn && fn(a, value)) || (!fn && a)){
6801                 result[++ri] = ci;
6802             }
6803         }
6804         return result;
6805     }
6806
6807     function byPseudo(cs, name, value){
6808         return Ext.DomQuery.pseudos[name](cs, value);
6809     }
6810
6811     function nodupIEXml(cs){
6812         var d = ++key,
6813             r;
6814         cs[0].setAttribute("_nodup", d);
6815         r = [cs[0]];
6816         for(var i = 1, len = cs.length; i < len; i++){
6817             var c = cs[i];
6818             if(!c.getAttribute("_nodup") != d){
6819                 c.setAttribute("_nodup", d);
6820                 r[r.length] = c;
6821             }
6822         }
6823         for(var i = 0, len = cs.length; i < len; i++){
6824             cs[i].removeAttribute("_nodup");
6825         }
6826         return r;
6827     }
6828
6829     function nodup(cs){
6830         if(!cs){
6831             return [];
6832         }
6833         var len = cs.length, c, i, r = cs, cj, ri = -1;
6834         if(!len || typeof cs.nodeType != "undefined" || len == 1){
6835             return cs;
6836         }
6837         if(isIE && typeof cs[0].selectSingleNode != "undefined"){
6838             return nodupIEXml(cs);
6839         }
6840         var d = ++key;
6841         cs[0]._nodup = d;
6842         for(i = 1; c = cs[i]; i++){
6843             if(c._nodup != d){
6844                 c._nodup = d;
6845             }else{
6846                 r = [];
6847                 for(var j = 0; j < i; j++){
6848                     r[++ri] = cs[j];
6849                 }
6850                 for(j = i+1; cj = cs[j]; j++){
6851                     if(cj._nodup != d){
6852                         cj._nodup = d;
6853                         r[++ri] = cj;
6854                     }
6855                 }
6856                 return r;
6857             }
6858         }
6859         return r;
6860     }
6861
6862     function quickDiffIEXml(c1, c2){
6863         var d = ++key,
6864             r = [];
6865         for(var i = 0, len = c1.length; i < len; i++){
6866             c1[i].setAttribute("_qdiff", d);
6867         }
6868         for(var i = 0, len = c2.length; i < len; i++){
6869             if(c2[i].getAttribute("_qdiff") != d){
6870                 r[r.length] = c2[i];
6871             }
6872         }
6873         for(var i = 0, len = c1.length; i < len; i++){
6874            c1[i].removeAttribute("_qdiff");
6875         }
6876         return r;
6877     }
6878
6879     function quickDiff(c1, c2){
6880         var len1 = c1.length,
6881             d = ++key,
6882             r = [];
6883         if(!len1){
6884             return c2;
6885         }
6886         if(isIE && typeof c1[0].selectSingleNode != "undefined"){
6887             return quickDiffIEXml(c1, c2);
6888         }
6889         for(var i = 0; i < len1; i++){
6890             c1[i]._qdiff = d;
6891         }
6892         for(var i = 0, len = c2.length; i < len; i++){
6893             if(c2[i]._qdiff != d){
6894                 r[r.length] = c2[i];
6895             }
6896         }
6897         return r;
6898     }
6899
6900     function quickId(ns, mode, root, id){
6901         if(ns == root){
6902            var d = root.ownerDocument || root;
6903            return d.getElementById(id);
6904         }
6905         ns = getNodes(ns, mode, "*");
6906         return byId(ns, id);
6907     }
6908
6909     return {
6910         getStyle : function(el, name){
6911             return Ext.fly(el).getStyle(name);
6912         },
6913         
6914         compile : function(path, type){
6915             type = type || "select";
6916
6917             
6918             var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
6919                 mode,
6920                 lastPath,
6921                 matchers = Ext.DomQuery.matchers,
6922                 matchersLn = matchers.length,
6923                 modeMatch,
6924                 
6925                 lmode = path.match(modeRe);
6926
6927             if(lmode && lmode[1]){
6928                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
6929                 path = path.replace(lmode[1], "");
6930             }
6931
6932             
6933             while(path.substr(0, 1)=="/"){
6934                 path = path.substr(1);
6935             }
6936
6937             while(path && lastPath != path){
6938                 lastPath = path;
6939                 var tokenMatch = path.match(tagTokenRe);
6940                 if(type == "select"){
6941                     if(tokenMatch){
6942                         
6943                         if(tokenMatch[1] == "#"){
6944                             fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';
6945                         }else{
6946                             fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';
6947                         }
6948                         path = path.replace(tokenMatch[0], "");
6949                     }else if(path.substr(0, 1) != '@'){
6950                         fn[fn.length] = 'n = getNodes(n, mode, "*");';
6951                     }
6952                 
6953                 }else{
6954                     if(tokenMatch){
6955                         if(tokenMatch[1] == "#"){
6956                             fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';
6957                         }else{
6958                             fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';
6959                         }
6960                         path = path.replace(tokenMatch[0], "");
6961                     }
6962                 }
6963                 while(!(modeMatch = path.match(modeRe))){
6964                     var matched = false;
6965                     for(var j = 0; j < matchersLn; j++){
6966                         var t = matchers[j];
6967                         var m = path.match(t.re);
6968                         if(m){
6969                             fn[fn.length] = t.select.replace(tplRe, function(x, i){
6970                                 return m[i];
6971                             });
6972                             path = path.replace(m[0], "");
6973                             matched = true;
6974                             break;
6975                         }
6976                     }
6977                     
6978                     if(!matched){
6979                         Ext.Error.raise({
6980                             sourceClass: 'Ext.DomQuery',
6981                             sourceMethod: 'compile',
6982                             msg: 'Error parsing selector. Parsing failed at "' + path + '"'
6983                         });
6984                     }
6985                 }
6986                 if(modeMatch[1]){
6987                     fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';
6988                     path = path.replace(modeMatch[1], "");
6989                 }
6990             }
6991             
6992             fn[fn.length] = "return nodup(n);\n}";
6993
6994             
6995             eval(fn.join(""));
6996             return f;
6997         },
6998
6999         
7000         jsSelect: function(path, root, type){
7001             
7002             root = root || document;
7003
7004             if(typeof root == "string"){
7005                 root = document.getElementById(root);
7006             }
7007             var paths = path.split(","),
7008                 results = [];
7009
7010             
7011             for(var i = 0, len = paths.length; i < len; i++){
7012                 var subPath = paths[i].replace(trimRe, "");
7013                 
7014                 if(!cache[subPath]){
7015                     cache[subPath] = Ext.DomQuery.compile(subPath);
7016                     if(!cache[subPath]){
7017                         Ext.Error.raise({
7018                             sourceClass: 'Ext.DomQuery',
7019                             sourceMethod: 'jsSelect',
7020                             msg: subPath + ' is not a valid selector'
7021                         });
7022                     }
7023                 }
7024                 var result = cache[subPath](root);
7025                 if(result && result != document){
7026                     results = results.concat(result);
7027                 }
7028             }
7029
7030             
7031             
7032             if(paths.length > 1){
7033                 return nodup(results);
7034             }
7035             return results;
7036         },
7037
7038         isXml: function(el) {
7039             var docEl = (el ? el.ownerDocument || el : 0).documentElement;
7040             return docEl ? docEl.nodeName !== "HTML" : false;
7041         },
7042         
7043         select : document.querySelectorAll ? function(path, root, type) {
7044             root = root || document;
7045             if (!Ext.DomQuery.isXml(root)) {
7046             try {
7047                 var cs = root.querySelectorAll(path);
7048                 return Ext.Array.toArray(cs);
7049             }
7050             catch (ex) {}
7051             }
7052             return Ext.DomQuery.jsSelect.call(this, path, root, type);
7053         } : function(path, root, type) {
7054             return Ext.DomQuery.jsSelect.call(this, path, root, type);
7055         },
7056
7057         
7058         selectNode : function(path, root){
7059             return Ext.DomQuery.select(path, root)[0];
7060         },
7061
7062         
7063         selectValue : function(path, root, defaultValue){
7064             path = path.replace(trimRe, "");
7065             if(!valueCache[path]){
7066                 valueCache[path] = Ext.DomQuery.compile(path, "select");
7067             }
7068             var n = valueCache[path](root), v;
7069             n = n[0] ? n[0] : n;
7070
7071             
7072             
7073             
7074             
7075             if (typeof n.normalize == 'function') n.normalize();
7076
7077             v = (n && n.firstChild ? n.firstChild.nodeValue : null);
7078             return ((v === null||v === undefined||v==='') ? defaultValue : v);
7079         },
7080
7081         
7082         selectNumber : function(path, root, defaultValue){
7083             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
7084             return parseFloat(v);
7085         },
7086
7087         
7088         is : function(el, ss){
7089             if(typeof el == "string"){
7090                 el = document.getElementById(el);
7091             }
7092             var isArray = Ext.isArray(el),
7093                 result = Ext.DomQuery.filter(isArray ? el : [el], ss);
7094             return isArray ? (result.length == el.length) : (result.length > 0);
7095         },
7096
7097         
7098         filter : function(els, ss, nonMatches){
7099             ss = ss.replace(trimRe, "");
7100             if(!simpleCache[ss]){
7101                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
7102             }
7103             var result = simpleCache[ss](els);
7104             return nonMatches ? quickDiff(result, els) : result;
7105         },
7106
7107         
7108         matchers : [{
7109                 re: /^\.([\w-]+)/,
7110                 select: 'n = byClassName(n, " {1} ");'
7111             }, {
7112                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
7113                 select: 'n = byPseudo(n, "{1}", "{2}");'
7114             },{
7115                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
7116                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
7117             }, {
7118                 re: /^#([\w-]+)/,
7119                 select: 'n = byId(n, "{1}");'
7120             },{
7121                 re: /^@([\w-]+)/,
7122                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
7123             }
7124         ],
7125
7126         
7127         operators : {
7128             "=" : function(a, v){
7129                 return a == v;
7130             },
7131             "!=" : function(a, v){
7132                 return a != v;
7133             },
7134             "^=" : function(a, v){
7135                 return a && a.substr(0, v.length) == v;
7136             },
7137             "$=" : function(a, v){
7138                 return a && a.substr(a.length-v.length) == v;
7139             },
7140             "*=" : function(a, v){
7141                 return a && a.indexOf(v) !== -1;
7142             },
7143             "%=" : function(a, v){
7144                 return (a % v) == 0;
7145             },
7146             "|=" : function(a, v){
7147                 return a && (a == v || a.substr(0, v.length+1) == v+'-');
7148             },
7149             "~=" : function(a, v){
7150                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
7151             }
7152         },
7153
7154         
7155         pseudos : {
7156             "first-child" : function(c){
7157                 var r = [], ri = -1, n;
7158                 for(var i = 0, ci; ci = n = c[i]; i++){
7159                     while((n = n.previousSibling) && n.nodeType != 1);
7160                     if(!n){
7161                         r[++ri] = ci;
7162                     }
7163                 }
7164                 return r;
7165             },
7166
7167             "last-child" : function(c){
7168                 var r = [], ri = -1, n;
7169                 for(var i = 0, ci; ci = n = c[i]; i++){
7170                     while((n = n.nextSibling) && n.nodeType != 1);
7171                     if(!n){
7172                         r[++ri] = ci;
7173                     }
7174                 }
7175                 return r;
7176             },
7177
7178             "nth-child" : function(c, a) {
7179                 var r = [], ri = -1,
7180                     m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
7181                     f = (m[1] || 1) - 0, l = m[2] - 0;
7182                 for(var i = 0, n; n = c[i]; i++){
7183                     var pn = n.parentNode;
7184                     if (batch != pn._batch) {
7185                         var j = 0;
7186                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
7187                             if(cn.nodeType == 1){
7188                                cn.nodeIndex = ++j;
7189                             }
7190                         }
7191                         pn._batch = batch;
7192                     }
7193                     if (f == 1) {
7194                         if (l == 0 || n.nodeIndex == l){
7195                             r[++ri] = n;
7196                         }
7197                     } else if ((n.nodeIndex + l) % f == 0){
7198                         r[++ri] = n;
7199                     }
7200                 }
7201
7202                 return r;
7203             },
7204
7205             "only-child" : function(c){
7206                 var r = [], ri = -1;;
7207                 for(var i = 0, ci; ci = c[i]; i++){
7208                     if(!prev(ci) && !next(ci)){
7209                         r[++ri] = ci;
7210                     }
7211                 }
7212                 return r;
7213             },
7214
7215             "empty" : function(c){
7216                 var r = [], ri = -1;
7217                 for(var i = 0, ci; ci = c[i]; i++){
7218                     var cns = ci.childNodes, j = 0, cn, empty = true;
7219                     while(cn = cns[j]){
7220                         ++j;
7221                         if(cn.nodeType == 1 || cn.nodeType == 3){
7222                             empty = false;
7223                             break;
7224                         }
7225                     }
7226                     if(empty){
7227                         r[++ri] = ci;
7228                     }
7229                 }
7230                 return r;
7231             },
7232
7233             "contains" : function(c, v){
7234                 var r = [], ri = -1;
7235                 for(var i = 0, ci; ci = c[i]; i++){
7236                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
7237                         r[++ri] = ci;
7238                     }
7239                 }
7240                 return r;
7241             },
7242
7243             "nodeValue" : function(c, v){
7244                 var r = [], ri = -1;
7245                 for(var i = 0, ci; ci = c[i]; i++){
7246                     if(ci.firstChild && ci.firstChild.nodeValue == v){
7247                         r[++ri] = ci;
7248                     }
7249                 }
7250                 return r;
7251             },
7252
7253             "checked" : function(c){
7254                 var r = [], ri = -1;
7255                 for(var i = 0, ci; ci = c[i]; i++){
7256                     if(ci.checked == true){
7257                         r[++ri] = ci;
7258                     }
7259                 }
7260                 return r;
7261             },
7262
7263             "not" : function(c, ss){
7264                 return Ext.DomQuery.filter(c, ss, true);
7265             },
7266
7267             "any" : function(c, selectors){
7268                 var ss = selectors.split('|'),
7269                     r = [], ri = -1, s;
7270                 for(var i = 0, ci; ci = c[i]; i++){
7271                     for(var j = 0; s = ss[j]; j++){
7272                         if(Ext.DomQuery.is(ci, s)){
7273                             r[++ri] = ci;
7274                             break;
7275                         }
7276                     }
7277                 }
7278                 return r;
7279             },
7280
7281             "odd" : function(c){
7282                 return this["nth-child"](c, "odd");
7283             },
7284
7285             "even" : function(c){
7286                 return this["nth-child"](c, "even");
7287             },
7288
7289             "nth" : function(c, a){
7290                 return c[a-1] || [];
7291             },
7292
7293             "first" : function(c){
7294                 return c[0] || [];
7295             },
7296
7297             "last" : function(c){
7298                 return c[c.length-1] || [];
7299             },
7300
7301             "has" : function(c, ss){
7302                 var s = Ext.DomQuery.select,
7303                     r = [], ri = -1;
7304                 for(var i = 0, ci; ci = c[i]; i++){
7305                     if(s(ss, ci).length > 0){
7306                         r[++ri] = ci;
7307                     }
7308                 }
7309                 return r;
7310             },
7311
7312             "next" : function(c, ss){
7313                 var is = Ext.DomQuery.is,
7314                     r = [], ri = -1;
7315                 for(var i = 0, ci; ci = c[i]; i++){
7316                     var n = next(ci);
7317                     if(n && is(n, ss)){
7318                         r[++ri] = ci;
7319                     }
7320                 }
7321                 return r;
7322             },
7323
7324             "prev" : function(c, ss){
7325                 var is = Ext.DomQuery.is,
7326                     r = [], ri = -1;
7327                 for(var i = 0, ci; ci = c[i]; i++){
7328                     var n = prev(ci);
7329                     if(n && is(n, ss)){
7330                         r[++ri] = ci;
7331                     }
7332                 }
7333                 return r;
7334             }
7335         }
7336     };
7337 }();
7338
7339
7340 Ext.query = Ext.DomQuery.select;
7341
7342
7343  (function() {
7344     var DOC = document,
7345         EC = Ext.cache;
7346
7347     Ext.Element = Ext.core.Element = function(element, forceNew) {
7348         var dom = typeof element == "string" ? DOC.getElementById(element) : element,
7349         id;
7350
7351         if (!dom) {
7352             return null;
7353         }
7354
7355         id = dom.id;
7356
7357         if (!forceNew && id && EC[id]) {
7358             
7359             return EC[id].el;
7360         }
7361
7362         
7363         this.dom = dom;
7364
7365         
7366         this.id = id || Ext.id(dom);
7367     };
7368
7369     var DH = Ext.core.DomHelper,
7370     El = Ext.core.Element;
7371
7372
7373     El.prototype = {
7374         
7375         set: function(o, useSet) {
7376             var el = this.dom,
7377                 attr,
7378                 val;
7379             useSet = (useSet !== false) && !!el.setAttribute;
7380
7381             for (attr in o) {
7382                 if (o.hasOwnProperty(attr)) {
7383                     val = o[attr];
7384                     if (attr == 'style') {
7385                         DH.applyStyles(el, val);
7386                     } else if (attr == 'cls') {
7387                         el.className = val;
7388                     } else if (useSet) {
7389                         el.setAttribute(attr, val);
7390                     } else {
7391                         el[attr] = val;
7392                     }
7393                 }
7394             }
7395             return this;
7396         },
7397
7398         
7399         
7400         
7401         
7402         
7403         
7404         
7405         
7406         
7407         
7408         
7409
7410         
7411         
7412         
7413         
7414
7415
7416         
7417         
7418         
7419         
7420         
7421         
7422         
7423
7424         
7425         
7426         
7427         
7428         
7429         
7430         
7431
7432         
7433         
7434         
7435         
7436
7437         
7438         
7439         
7440         
7441         
7442         
7443         
7444         
7445
7446         
7447         defaultUnit: "px",
7448
7449         
7450         is: function(simpleSelector) {
7451             return Ext.DomQuery.is(this.dom, simpleSelector);
7452         },
7453
7454         
7455         focus: function(defer,
7456                         
7457                         dom) {
7458             var me = this;
7459             dom = dom || me.dom;
7460             try {
7461                 if (Number(defer)) {
7462                     Ext.defer(me.focus, defer, null, [null, dom]);
7463                 } else {
7464                     dom.focus();
7465                 }
7466             } catch(e) {}
7467             return me;
7468         },
7469
7470         
7471         blur: function() {
7472             try {
7473                 this.dom.blur();
7474             } catch(e) {}
7475             return this;
7476         },
7477
7478         
7479         getValue: function(asNumber) {
7480             var val = this.dom.value;
7481             return asNumber ? parseInt(val, 10) : val;
7482         },
7483
7484         
7485         addListener: function(eventName, fn, scope, options) {
7486             Ext.EventManager.on(this.dom, eventName, fn, scope || this, options);
7487             return this;
7488         },
7489
7490         
7491         removeListener: function(eventName, fn, scope) {
7492             Ext.EventManager.un(this.dom, eventName, fn, scope || this);
7493             return this;
7494         },
7495
7496         
7497         removeAllListeners: function() {
7498             Ext.EventManager.removeAll(this.dom);
7499             return this;
7500         },
7501
7502         
7503         purgeAllListeners: function() {
7504             Ext.EventManager.purgeElement(this);
7505             return this;
7506         },
7507
7508         
7509         addUnits: function(size, units) {
7510
7511             
7512             if (Ext.isNumber(size)) {
7513                 return size + (units || this.defaultUnit || 'px');
7514             }
7515
7516             
7517             if (size === "" || size == "auto" || size === undefined || size === null) {
7518                 return size || '';
7519             }
7520
7521             
7522             if (!unitPattern.test(size)) {
7523                 if (Ext.isDefined(Ext.global.console)) {
7524                     Ext.global.console.warn("Warning, size detected as NaN on Element.addUnits.");
7525                 }
7526                 return size || '';
7527             }
7528             return size;
7529         },
7530
7531         
7532         isBorderBox: function() {
7533             return Ext.isBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()];
7534         },
7535
7536         
7537         remove: function() {
7538             var me = this,
7539             dom = me.dom;
7540
7541             if (dom) {
7542                 delete me.dom;
7543                 Ext.removeNode(dom);
7544             }
7545         },
7546
7547         
7548         hover: function(overFn, outFn, scope, options) {
7549             var me = this;
7550             me.on('mouseenter', overFn, scope || me.dom, options);
7551             me.on('mouseleave', outFn, scope || me.dom, options);
7552             return me;
7553         },
7554
7555         
7556         contains: function(el) {
7557             return ! el ? false: Ext.core.Element.isAncestor(this.dom, el.dom ? el.dom: el);
7558         },
7559
7560         
7561         getAttributeNS: function(ns, name) {
7562             return this.getAttribute(name, ns);
7563         },
7564
7565         
7566         getAttribute: (Ext.isIE && !(Ext.isIE9 && document.documentMode === 9)) ?
7567         function(name, ns) {
7568             var d = this.dom,
7569             type;
7570             if(ns) {
7571                 type = typeof d[ns + ":" + name];
7572                 if (type != 'undefined' && type != 'unknown') {
7573                     return d[ns + ":" + name] || null;
7574                 }
7575                 return null;
7576             }
7577             if (name === "for") {
7578                 name = "htmlFor";
7579             }
7580             return d[name] || null;
7581         }: function(name, ns) {
7582             var d = this.dom;
7583             if (ns) {
7584                return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name);
7585             }
7586             return  d.getAttribute(name) || d[name] || null;
7587         },
7588
7589         
7590         update: function(html) {
7591             if (this.dom) {
7592                 this.dom.innerHTML = html;
7593             }
7594             return this;
7595         }
7596     };
7597
7598     var ep = El.prototype;
7599
7600     El.addMethods = function(o) {
7601         Ext.apply(ep, o);
7602     };
7603
7604     
7605     ep.on = ep.addListener;
7606
7607     
7608     ep.un = ep.removeListener;
7609
7610     
7611     ep.clearListeners = ep.removeAllListeners;
7612
7613     
7614     ep.destroy = ep.remove;
7615
7616     
7617     ep.autoBoxAdjust = true;
7618
7619     
7620     var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
7621     docEl;
7622
7623     
7624     El.get = function(el) {
7625         var ex,
7626         elm,
7627         id;
7628         if (!el) {
7629             return null;
7630         }
7631         if (typeof el == "string") {
7632             
7633             if (! (elm = DOC.getElementById(el))) {
7634                 return null;
7635             }
7636             if (EC[el] && EC[el].el) {
7637                 ex = EC[el].el;
7638                 ex.dom = elm;
7639             } else {
7640                 ex = El.addToCache(new El(elm));
7641             }
7642             return ex;
7643         } else if (el.tagName) {
7644             
7645             if (! (id = el.id)) {
7646                 id = Ext.id(el);
7647             }
7648             if (EC[id] && EC[id].el) {
7649                 ex = EC[id].el;
7650                 ex.dom = el;
7651             } else {
7652                 ex = El.addToCache(new El(el));
7653             }
7654             return ex;
7655         } else if (el instanceof El) {
7656             if (el != docEl) {
7657                 
7658                 
7659                 
7660                 if (Ext.isIE && (el.id == undefined || el.id == '')) {
7661                     el.dom = el.dom;
7662                 } else {
7663                     el.dom = DOC.getElementById(el.id) || el.dom;
7664                 }
7665             }
7666             return el;
7667         } else if (el.isComposite) {
7668             return el;
7669         } else if (Ext.isArray(el)) {
7670             return El.select(el);
7671         } else if (el == DOC) {
7672             
7673             if (!docEl) {
7674                 var f = function() {};
7675                 f.prototype = El.prototype;
7676                 docEl = new f();
7677                 docEl.dom = DOC;
7678             }
7679             return docEl;
7680         }
7681         return null;
7682     };
7683
7684     El.addToCache = function(el, id) {
7685         if (el) {
7686             id = id || el.id;
7687             EC[id] = {
7688                 el: el,
7689                 data: {},
7690                 events: {}
7691             };
7692         }
7693         return el;
7694     };
7695
7696     
7697     El.data = function(el, key, value) {
7698         el = El.get(el);
7699         if (!el) {
7700             return null;
7701         }
7702         var c = EC[el.id].data;
7703         if (arguments.length == 2) {
7704             return c[key];
7705         } else {
7706             return (c[key] = value);
7707         }
7708     };
7709
7710     
7711     
7712     
7713     function garbageCollect() {
7714         if (!Ext.enableGarbageCollector) {
7715             clearInterval(El.collectorThreadId);
7716         } else {
7717             var eid,
7718             el,
7719             d,
7720             o;
7721
7722             for (eid in EC) {
7723                 if (!EC.hasOwnProperty(eid)) {
7724                     continue;
7725                 }
7726                 o = EC[eid];
7727                 if (o.skipGarbageCollection) {
7728                     continue;
7729                 }
7730                 el = o.el;
7731                 d = el.dom;
7732                 
7733                 
7734                 
7735                 
7736                 
7737                 
7738                 
7739                 
7740                 
7741                 
7742                 
7743                 
7744                 
7745                 
7746                 
7747                 
7748                 
7749                 if (!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))) {
7750                     if (d && Ext.enableListenerCollection) {
7751                         Ext.EventManager.removeAll(d);
7752                     }
7753                     delete EC[eid];
7754                 }
7755             }
7756             
7757             if (Ext.isIE) {
7758                 var t = {};
7759                 for (eid in EC) {
7760                     if (!EC.hasOwnProperty(eid)) {
7761                         continue;
7762                     }
7763                     t[eid] = EC[eid];
7764                 }
7765                 EC = Ext.cache = t;
7766             }
7767         }
7768     }
7769     El.collectorThreadId = setInterval(garbageCollect, 30000);
7770
7771     var flyFn = function() {};
7772     flyFn.prototype = El.prototype;
7773
7774     
7775     El.Flyweight = function(dom) {
7776         this.dom = dom;
7777     };
7778
7779     El.Flyweight.prototype = new flyFn();
7780     El.Flyweight.prototype.isFlyweight = true;
7781     El._flyweights = {};
7782
7783     
7784     El.fly = function(el, named) {
7785         var ret = null;
7786         named = named || '_global';
7787         el = Ext.getDom(el);
7788         if (el) {
7789             (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
7790             ret = El._flyweights[named];
7791         }
7792         return ret;
7793     };
7794
7795     
7796     Ext.get = El.get;
7797
7798     
7799     Ext.fly = El.fly;
7800
7801     
7802     var noBoxAdjust = Ext.isStrict ? {
7803         select: 1
7804     }: {
7805         input: 1,
7806         select: 1,
7807         textarea: 1
7808     };
7809     if (Ext.isIE || Ext.isGecko) {
7810         noBoxAdjust['button'] = 1;
7811     }
7812 })();
7813
7814
7815 Ext.core.Element.addMethods({
7816     
7817     findParent : function(simpleSelector, maxDepth, returnEl) {
7818         var p = this.dom,
7819             b = document.body,
7820             depth = 0,
7821             stopEl;
7822
7823         maxDepth = maxDepth || 50;
7824         if (isNaN(maxDepth)) {
7825             stopEl = Ext.getDom(maxDepth);
7826             maxDepth = Number.MAX_VALUE;
7827         }
7828         while (p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl) {
7829             if (Ext.DomQuery.is(p, simpleSelector)) {
7830                 return returnEl ? Ext.get(p) : p;
7831             }
7832             depth++;
7833             p = p.parentNode;
7834         }
7835         return null;
7836     },
7837     
7838     
7839     findParentNode : function(simpleSelector, maxDepth, returnEl) {
7840         var p = Ext.fly(this.dom.parentNode, '_internal');
7841         return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7842     },
7843
7844     
7845     up : function(simpleSelector, maxDepth) {
7846         return this.findParentNode(simpleSelector, maxDepth, true);
7847     },
7848
7849     
7850     select : function(selector) {
7851         return Ext.core.Element.select(selector, false,  this.dom);
7852     },
7853
7854     
7855     query : function(selector) {
7856         return Ext.DomQuery.select(selector, this.dom);
7857     },
7858
7859     
7860     down : function(selector, returnDom) {
7861         var n = Ext.DomQuery.selectNode(selector, this.dom);
7862         return returnDom ? n : Ext.get(n);
7863     },
7864
7865     
7866     child : function(selector, returnDom) {
7867         var node,
7868             me = this,
7869             id;
7870         id = Ext.get(me).id;
7871         
7872         id = id.replace(/[\.:]/g, "\\$0");
7873         node = Ext.DomQuery.selectNode('#' + id + " > " + selector, me.dom);
7874         return returnDom ? node : Ext.get(node);
7875     },
7876
7877      
7878     parent : function(selector, returnDom) {
7879         return this.matchNode('parentNode', 'parentNode', selector, returnDom);
7880     },
7881
7882      
7883     next : function(selector, returnDom) {
7884         return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
7885     },
7886
7887     
7888     prev : function(selector, returnDom) {
7889         return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
7890     },
7891
7892
7893     
7894     first : function(selector, returnDom) {
7895         return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
7896     },
7897
7898     
7899     last : function(selector, returnDom) {
7900         return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
7901     },
7902
7903     matchNode : function(dir, start, selector, returnDom) {
7904         if (!this.dom) {
7905             return null;
7906         }
7907         
7908         var n = this.dom[start];
7909         while (n) {
7910             if (n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))) {
7911                 return !returnDom ? Ext.get(n) : n;
7912             }
7913             n = n[dir];
7914         }
7915         return null;
7916     }
7917 });
7918
7919
7920 Ext.core.Element.addMethods({
7921     
7922     appendChild : function(el) {
7923         return Ext.get(el).appendTo(this);
7924     },
7925
7926     
7927     appendTo : function(el) {
7928         Ext.getDom(el).appendChild(this.dom);
7929         return this;
7930     },
7931
7932     
7933     insertBefore : function(el) {
7934         el = Ext.getDom(el);
7935         el.parentNode.insertBefore(this.dom, el);
7936         return this;
7937     },
7938
7939     
7940     insertAfter : function(el) {
7941         el = Ext.getDom(el);
7942         el.parentNode.insertBefore(this.dom, el.nextSibling);
7943         return this;
7944     },
7945
7946     
7947     insertFirst : function(el, returnDom) {
7948         el = el || {};
7949         if (el.nodeType || el.dom || typeof el == 'string') { 
7950             el = Ext.getDom(el);
7951             this.dom.insertBefore(el, this.dom.firstChild);
7952             return !returnDom ? Ext.get(el) : el;
7953         }
7954         else { 
7955             return this.createChild(el, this.dom.firstChild, returnDom);
7956         }
7957     },
7958
7959     
7960     insertSibling: function(el, where, returnDom){
7961         var me = this, rt,
7962         isAfter = (where || 'before').toLowerCase() == 'after',
7963         insertEl;
7964
7965         if(Ext.isArray(el)){
7966             insertEl = me;
7967             Ext.each(el, function(e) {
7968                 rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
7969                 if(isAfter){
7970                     insertEl = rt;
7971                 }
7972             });
7973             return rt;
7974         }
7975
7976         el = el || {};
7977
7978         if(el.nodeType || el.dom){
7979             rt = me.dom.parentNode.insertBefore(Ext.getDom(el), isAfter ? me.dom.nextSibling : me.dom);
7980             if (!returnDom) {
7981                 rt = Ext.get(rt);
7982             }
7983         }else{
7984             if (isAfter && !me.dom.nextSibling) {
7985                 rt = Ext.core.DomHelper.append(me.dom.parentNode, el, !returnDom);
7986             } else {
7987                 rt = Ext.core.DomHelper[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
7988             }
7989         }
7990         return rt;
7991     },
7992
7993     
7994     replace : function(el) {
7995         el = Ext.get(el);
7996         this.insertBefore(el);
7997         el.remove();
7998         return this;
7999     },
8000     
8001     
8002     replaceWith: function(el){
8003         var me = this;
8004             
8005         if(el.nodeType || el.dom || typeof el == 'string'){
8006             el = Ext.get(el);
8007             me.dom.parentNode.insertBefore(el, me.dom);
8008         }else{
8009             el = Ext.core.DomHelper.insertBefore(me.dom, el);
8010         }
8011         
8012         delete Ext.cache[me.id];
8013         Ext.removeNode(me.dom);      
8014         me.id = Ext.id(me.dom = el);
8015         Ext.core.Element.addToCache(me.isFlyweight ? new Ext.core.Element(me.dom) : me);     
8016         return me;
8017     },
8018     
8019     
8020     createChild : function(config, insertBefore, returnDom) {
8021         config = config || {tag:'div'};
8022         if (insertBefore) {
8023             return Ext.core.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8024         }
8025         else {
8026             return Ext.core.DomHelper[!this.dom.firstChild ? 'insertFirst' : 'append'](this.dom, config,  returnDom !== true);
8027         }
8028     },
8029
8030     
8031     wrap : function(config, returnDom) {
8032         var newEl = Ext.core.DomHelper.insertBefore(this.dom, config || {tag: "div"}, !returnDom),
8033             d = newEl.dom || newEl;
8034
8035         d.appendChild(this.dom);
8036         return newEl;
8037     },
8038
8039     
8040     insertHtml : function(where, html, returnEl) {
8041         var el = Ext.core.DomHelper.insertHtml(where, this.dom, html);
8042         return returnEl ? Ext.get(el) : el;
8043     }
8044 });
8045
8046
8047 (function(){
8048     Ext.core.Element.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
8049     
8050     var supports = Ext.supports,
8051         view = document.defaultView,
8052         opacityRe = /alpha\(opacity=(.*)\)/i,
8053         trimRe = /^\s+|\s+$/g,
8054         spacesRe = /\s+/,
8055         wordsRe = /\w/g,
8056         adjustDirect2DTableRe = /table-row|table-.*-group/,
8057         INTERNAL = '_internal',
8058         PADDING = 'padding',
8059         MARGIN = 'margin',
8060         BORDER = 'border',
8061         LEFT = '-left',
8062         RIGHT = '-right',
8063         TOP = '-top',
8064         BOTTOM = '-bottom',
8065         WIDTH = '-width',
8066         MATH = Math,
8067         HIDDEN = 'hidden',
8068         ISCLIPPED = 'isClipped',
8069         OVERFLOW = 'overflow',
8070         OVERFLOWX = 'overflow-x',
8071         OVERFLOWY = 'overflow-y',
8072         ORIGINALCLIP = 'originalClip',
8073         
8074         borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
8075         paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
8076         margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
8077         data = Ext.core.Element.data;
8078
8079     Ext.override(Ext.core.Element, {
8080         
8081         
8082         
8083         adjustWidth : function(width) {
8084             var me = this,
8085                 isNum = (typeof width == 'number');
8086                 
8087             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
8088                width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
8089             }
8090             return (isNum && width < 0) ? 0 : width;
8091         },
8092
8093         
8094         adjustHeight : function(height) {
8095             var me = this,
8096                 isNum = (typeof height == "number");
8097                 
8098             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
8099                height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
8100             }
8101             return (isNum && height < 0) ? 0 : height;
8102         },
8103
8104
8105         
8106         addCls : function(className){
8107             var me = this,
8108                 cls = [],
8109                 space = ((me.dom.className.replace(trimRe, '') == '') ? "" : " "),
8110                 i, len, v;
8111             if (!Ext.isDefined(className)) {
8112                 return me;
8113             }
8114             
8115             if (!Ext.isArray(className)) {
8116                 if (typeof className === 'string') {
8117                     className = className.replace(trimRe, '').split(spacesRe);
8118                     if (className.length === 1) {
8119                         className = className[0];
8120                         if (!me.hasCls(className)) {
8121                             me.dom.className += space + className;
8122                         }
8123                     } else {
8124                         this.addCls(className);
8125                     }
8126                 }
8127             } else {
8128                 for (i = 0, len = className.length; i < len; i++) {
8129                     v = className[i];
8130                     if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
8131                         cls.push(v);
8132                     }
8133                 }
8134                 if (cls.length) {
8135                     me.dom.className += space + cls.join(" ");
8136                 }
8137             }
8138             return me;
8139         },
8140
8141         
8142         removeCls : function(className){
8143             var me = this,
8144                 i, idx, len, cls, elClasses;
8145             if (!Ext.isDefined(className)) {
8146                 return me;
8147             }
8148             if (!Ext.isArray(className)){
8149                 className = className.replace(trimRe, '').split(spacesRe);
8150             }
8151             if (me.dom && me.dom.className) {
8152                 elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
8153                 for (i = 0, len = className.length; i < len; i++) {
8154                     cls = className[i];
8155                     if (typeof cls == 'string') {
8156                         cls = cls.replace(trimRe, '');
8157                         idx = Ext.Array.indexOf(elClasses, cls);
8158                         if (idx != -1) {
8159                             elClasses.splice(idx, 1);
8160                         }
8161                     }
8162                 }
8163                 me.dom.className = elClasses.join(" ");
8164             }
8165             return me;
8166         },
8167
8168         
8169         radioCls : function(className){
8170             var cn = this.dom.parentNode.childNodes,
8171                 v, i, len;
8172             className = Ext.isArray(className) ? className : [className];
8173             for (i = 0, len = cn.length; i < len; i++) {
8174                 v = cn[i];
8175                 if (v && v.nodeType == 1) {
8176                     Ext.fly(v, '_internal').removeCls(className);
8177                 }
8178             }
8179             return this.addCls(className);
8180         },
8181
8182         
8183         toggleCls : Ext.supports.ClassList ?
8184             function(className) {
8185                 this.dom.classList.toggle(Ext.String.trim(className));
8186                 return this;
8187             } :
8188             function(className) {
8189                 return this.hasCls(className) ? this.removeCls(className) : this.addCls(className);
8190             },
8191
8192         
8193         hasCls : Ext.supports.ClassList ?
8194             function(className) {
8195                 if (!className) {
8196                     return false;
8197                 }
8198                 className = className.split(spacesRe);
8199                 var ln = className.length,
8200                     i = 0;
8201                 for (; i < ln; i++) {
8202                     if (className[i] && this.dom.classList.contains(className[i])) {
8203                         return true;
8204                     }
8205                 }
8206                 return false;
8207             } :
8208             function(className){
8209                 return className && (' ' + this.dom.className + ' ').indexOf(' ' + className + ' ') != -1;
8210             },
8211
8212         
8213         replaceCls : function(oldClassName, newClassName){
8214             return this.removeCls(oldClassName).addCls(newClassName);
8215         },
8216
8217         isStyle : function(style, val) {
8218             return this.getStyle(style) == val;
8219         },
8220
8221         
8222         getStyle : function(){
8223             return view && view.getComputedStyle ?
8224                 function(prop){
8225                     var el = this.dom,
8226                         v, cs, out, display;
8227
8228                     if(el == document){
8229                         return null;
8230                     }
8231                     prop = Ext.core.Element.normalize(prop);
8232                     out = (v = el.style[prop]) ? v :
8233                            (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
8234                            
8235                     
8236                     
8237                     if(prop == 'marginRight' && out != '0px' && !supports.RightMargin){
8238                         display = this.getStyle('display');
8239                         el.style.display = 'inline-block';
8240                         out = view.getComputedStyle(el, '').marginRight;
8241                         el.style.display = display;
8242                     }
8243                     
8244                     if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.TransparentColor){
8245                         out = 'transparent';
8246                     }
8247                     return out;
8248                 } :
8249                 function(prop){
8250                     var el = this.dom,
8251                         m, cs;
8252
8253                     if (el == document) {
8254                         return null;
8255                     }
8256                     
8257                     if (prop == 'opacity') {
8258                         if (el.style.filter.match) {
8259                             m = el.style.filter.match(opacityRe);
8260                             if(m){
8261                                 var fv = parseFloat(m[1]);
8262                                 if(!isNaN(fv)){
8263                                     return fv ? fv / 100 : 0;
8264                                 }
8265                             }
8266                         }
8267                         return 1;
8268                     }
8269                     prop = Ext.core.Element.normalize(prop);
8270                     return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
8271                 };
8272         }(),
8273
8274         
8275         getColor : function(attr, defaultValue, prefix){
8276             var v = this.getStyle(attr),
8277                 color = prefix || prefix === '' ? prefix : '#',
8278                 h;
8279
8280             if(!v || (/transparent|inherit/.test(v))) {
8281                 return defaultValue;
8282             }
8283             if(/^r/.test(v)){
8284                 Ext.each(v.slice(4, v.length -1).split(','), function(s){
8285                     h = parseInt(s, 10);
8286                     color += (h < 16 ? '0' : '') + h.toString(16);
8287                 });
8288             }else{
8289                 v = v.replace('#', '');
8290                 color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
8291             }
8292             return(color.length > 5 ? color.toLowerCase() : defaultValue);
8293         },
8294
8295         
8296         setStyle : function(prop, value){
8297             var me = this,
8298                 tmp, style;
8299
8300             if (!me.dom) {
8301                 return me;
8302             }
8303
8304             if (!Ext.isObject(prop)) {
8305                 tmp = {};
8306                 tmp[prop] = value;
8307                 prop = tmp;
8308             }
8309             for (style in prop) {
8310                 if (prop.hasOwnProperty(style)) {
8311                     value = Ext.value(prop[style], '');
8312                     if (style == 'opacity') {
8313                         me.setOpacity(value);
8314                     }
8315                     else {
8316                         me.dom.style[Ext.core.Element.normalize(style)] = value;
8317                     }
8318                 }
8319             }
8320             return me;
8321         },
8322
8323         
8324         setOpacity: function(opacity, animate) {
8325             var me = this,
8326                 dom = me.dom,
8327                 val,
8328                 style;
8329
8330             if (!me.dom) {
8331                 return me;
8332             }
8333
8334             style = me.dom.style;
8335
8336             if (!animate || !me.anim) {
8337                 if (!Ext.supports.Opacity) {
8338                     opacity = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')': '';
8339                     val = style.filter.replace(opacityRe, '').replace(trimRe, '');
8340
8341                     style.zoom = 1;
8342                     style.filter = val + (val.length > 0 ? ' ': '') + opacity;
8343                 }
8344                 else {
8345                     style.opacity = opacity;
8346                 }
8347             }
8348             else {
8349                 if (!Ext.isObject(animate)) {
8350                     animate = {
8351                         duration: 350,
8352                         easing: 'ease-in'
8353                     };
8354                 }
8355                 me.animate(Ext.applyIf({
8356                     to: {
8357                         opacity: opacity
8358                     }
8359                 },
8360                 animate));
8361             }
8362             return me;
8363         },
8364
8365
8366         
8367         clearOpacity : function(){
8368             var style = this.dom.style;
8369             if(!Ext.supports.Opacity){
8370                 if(!Ext.isEmpty(style.filter)){
8371                     style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
8372                 }
8373             }else{
8374                 style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
8375             }
8376             return this;
8377         },
8378         
8379         
8380         adjustDirect2DDimension: function(dimension) {
8381             var me = this,
8382                 dom = me.dom,
8383                 display = me.getStyle('display'),
8384                 inlineDisplay = dom.style['display'],
8385                 inlinePosition = dom.style['position'],
8386                 originIndex = dimension === 'width' ? 0 : 1,
8387                 floating;
8388                 
8389             if (display === 'inline') {
8390                 dom.style['display'] = 'inline-block';
8391             }
8392
8393             dom.style['position'] = display.match(adjustDirect2DTableRe) ? 'absolute' : 'static';
8394
8395             
8396             
8397             floating = (parseFloat(me.getStyle(dimension)) || parseFloat(dom.currentStyle.msTransformOrigin.split(' ')[originIndex]) * 2) % 1;
8398             
8399             dom.style['position'] = inlinePosition;
8400             
8401             if (display === 'inline') {
8402                 dom.style['display'] = inlineDisplay;
8403             }
8404
8405             return floating;
8406         },
8407         
8408         
8409         getHeight: function(contentHeight, preciseHeight) {
8410             var me = this,
8411                 dom = me.dom,
8412                 hidden = Ext.isIE && me.isStyle('display', 'none'),
8413                 height, overflow, style, floating;
8414
8415             
8416             
8417             if (Ext.isIEQuirks) {
8418                 style = dom.style;
8419                 overflow = style.overflow;
8420                 me.setStyle({ overflow: 'hidden'});
8421             }
8422
8423             height = dom.offsetHeight;
8424
8425             height = MATH.max(height, hidden ? 0 : dom.clientHeight) || 0;
8426
8427             
8428             if (!hidden && Ext.supports.Direct2DBug) {
8429                 floating = me.adjustDirect2DDimension('height');
8430                 if (preciseHeight) {
8431                     height += floating;
8432                 }
8433                 else if (floating > 0 && floating < 0.5) {
8434                     height++;
8435                 }
8436             }
8437
8438             if (contentHeight) {
8439                 height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
8440             }
8441
8442             if (Ext.isIEQuirks) {
8443                 me.setStyle({ overflow: overflow});
8444             }
8445
8446             if (height < 0) {
8447                 height = 0;
8448             }
8449             return height;
8450         },
8451                 
8452         
8453         getWidth: function(contentWidth, preciseWidth) {
8454             var me = this,
8455                 dom = me.dom,
8456                 hidden = Ext.isIE && me.isStyle('display', 'none'),
8457                 rect, width, overflow, style, floating, parentPosition;
8458
8459             
8460             
8461             if (Ext.isIEQuirks) {
8462                 style = dom.style;
8463                 overflow = style.overflow;
8464                 me.setStyle({overflow: 'hidden'});
8465             }
8466             
8467             
8468             if (Ext.isOpera10_5) {
8469                 if (dom.parentNode.currentStyle.position === 'relative') {
8470                     parentPosition = dom.parentNode.style.position;
8471                     dom.parentNode.style.position = 'static';
8472                     width = dom.offsetWidth;
8473                     dom.parentNode.style.position = parentPosition;
8474                 }
8475                 width = Math.max(width || 0, dom.offsetWidth);
8476             
8477             
8478             
8479             
8480             
8481             
8482             } else if (Ext.supports.BoundingClientRect) {
8483                 rect = dom.getBoundingClientRect();
8484                 width = rect.right - rect.left;
8485                 width = preciseWidth ? width : Math.ceil(width);
8486             } else {
8487                 width = dom.offsetWidth;
8488             }
8489
8490             width = MATH.max(width, hidden ? 0 : dom.clientWidth) || 0;
8491
8492             
8493             if (!hidden && Ext.supports.Direct2DBug) {
8494                 floating = me.adjustDirect2DDimension('width');
8495                 if (preciseWidth) {
8496                     width += floating;
8497                 }
8498                 else if (floating > 0 && floating < 0.5) {
8499                     width++;
8500                 }
8501             }
8502             
8503             if (contentWidth) {
8504                 width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
8505             }
8506             
8507             if (Ext.isIEQuirks) {
8508                 me.setStyle({ overflow: overflow});
8509             }
8510
8511             if (width < 0) {
8512                 width = 0;
8513             }
8514             return width;
8515         },
8516
8517         
8518         setWidth : function(width, animate){
8519             var me = this;
8520             width = me.adjustWidth(width);
8521             if (!animate || !me.anim) {
8522                 me.dom.style.width = me.addUnits(width);
8523             }
8524             else {
8525                 if (!Ext.isObject(animate)) {
8526                     animate = {};
8527                 }
8528                 me.animate(Ext.applyIf({
8529                     to: {
8530                         width: width
8531                     }
8532                 }, animate));
8533             }
8534             return me;
8535         },
8536
8537         
8538          setHeight : function(height, animate){
8539             var me = this;
8540             height = me.adjustHeight(height);
8541             if (!animate || !me.anim) {
8542                 me.dom.style.height = me.addUnits(height);
8543             }
8544             else {
8545                 if (!Ext.isObject(animate)) {
8546                     animate = {};
8547                 }
8548                 me.animate(Ext.applyIf({
8549                     to: {
8550                         height: height
8551                     }
8552                 }, animate));
8553             }
8554             return me;
8555         },
8556
8557         
8558         getBorderWidth : function(side){
8559             return this.addStyles(side, borders);
8560         },
8561
8562         
8563         getPadding : function(side){
8564             return this.addStyles(side, paddings);
8565         },
8566
8567         
8568         clip : function(){
8569             var me = this,
8570                 dom = me.dom;
8571
8572             if(!data(dom, ISCLIPPED)){
8573                 data(dom, ISCLIPPED, true);
8574                 data(dom, ORIGINALCLIP, {
8575                     o: me.getStyle(OVERFLOW),
8576                     x: me.getStyle(OVERFLOWX),
8577                     y: me.getStyle(OVERFLOWY)
8578                 });
8579                 me.setStyle(OVERFLOW, HIDDEN);
8580                 me.setStyle(OVERFLOWX, HIDDEN);
8581                 me.setStyle(OVERFLOWY, HIDDEN);
8582             }
8583             return me;
8584         },
8585
8586         
8587         unclip : function(){
8588             var me = this,
8589                 dom = me.dom,
8590                 clip;
8591
8592             if(data(dom, ISCLIPPED)){
8593                 data(dom, ISCLIPPED, false);
8594                 clip = data(dom, ORIGINALCLIP);
8595                 if(o.o){
8596                     me.setStyle(OVERFLOW, o.o);
8597                 }
8598                 if(o.x){
8599                     me.setStyle(OVERFLOWX, o.x);
8600                 }
8601                 if(o.y){
8602                     me.setStyle(OVERFLOWY, o.y);
8603                 }
8604             }
8605             return me;
8606         },
8607
8608         
8609         addStyles : function(sides, styles){
8610             var totalSize = 0,
8611                 sidesArr = sides.match(wordsRe),
8612                 i = 0,
8613                 len = sidesArr.length,
8614                 side, size;
8615             for (; i < len; i++) {
8616                 side = sidesArr[i];
8617                 size = side && parseInt(this.getStyle(styles[side]), 10);
8618                 if (size) {
8619                     totalSize += MATH.abs(size);
8620                 }
8621             }
8622             return totalSize;
8623         },
8624
8625         margins : margins,
8626         
8627         
8628         applyStyles : function(style){
8629             Ext.core.DomHelper.applyStyles(this.dom, style);
8630             return this;
8631         },
8632
8633         
8634         getStyles : function(){
8635             var styles = {},
8636                 len = arguments.length,
8637                 i = 0, style;
8638                 
8639             for(; i < len; ++i) {
8640                 style = arguments[i];
8641                 styles[style] = this.getStyle(style);
8642             }
8643             return styles;
8644         },
8645
8646        
8647         boxWrap : function(cls){
8648             cls = cls || Ext.baseCSSPrefix + 'box';
8649             var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + Ext.String.format(Ext.core.Element.boxMarkup, cls) + "</div>"));
8650             Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
8651             return el;
8652         },
8653
8654         
8655         setSize : function(width, height, animate){
8656             var me = this;
8657             if (Ext.isObject(width)){ 
8658                 height = width.height;
8659                 width = width.width;
8660             }
8661             width = me.adjustWidth(width);
8662             height = me.adjustHeight(height);
8663             if(!animate || !me.anim){
8664                 me.dom.style.width = me.addUnits(width);
8665                 me.dom.style.height = me.addUnits(height);
8666             }
8667             else {
8668                 if (!Ext.isObject(animate)) {
8669                     animate = {};
8670                 }
8671                 me.animate(Ext.applyIf({
8672                     to: {
8673                         width: width,
8674                         height: height
8675                     }
8676                 }, animate));
8677             }
8678             return me;
8679         },
8680
8681         
8682         getComputedHeight : function(){
8683             var me = this,
8684                 h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
8685             if(!h){
8686                 h = parseFloat(me.getStyle('height')) || 0;
8687                 if(!me.isBorderBox()){
8688                     h += me.getFrameWidth('tb');
8689                 }
8690             }
8691             return h;
8692         },
8693
8694         
8695         getComputedWidth : function(){
8696             var me = this,
8697                 w = Math.max(me.dom.offsetWidth, me.dom.clientWidth);
8698                 
8699             if(!w){
8700                 w = parseFloat(me.getStyle('width')) || 0;
8701                 if(!me.isBorderBox()){
8702                     w += me.getFrameWidth('lr');
8703                 }
8704             }
8705             return w;
8706         },
8707
8708         
8709         getFrameWidth : function(sides, onlyContentBox){
8710             return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8711         },
8712
8713         
8714         addClsOnOver : function(className){
8715             var dom = this.dom;
8716             this.hover(
8717                 function(){
8718                     Ext.fly(dom, INTERNAL).addCls(className);
8719                 },
8720                 function(){
8721                     Ext.fly(dom, INTERNAL).removeCls(className);
8722                 }
8723             );
8724             return this;
8725         },
8726
8727         
8728         addClsOnFocus : function(className){
8729             var me = this,
8730                 dom = me.dom;
8731             me.on("focus", function(){
8732                 Ext.fly(dom, INTERNAL).addCls(className);
8733             });
8734             me.on("blur", function(){
8735                 Ext.fly(dom, INTERNAL).removeCls(className);
8736             });
8737             return me;
8738         },
8739
8740         
8741         addClsOnClick : function(className){
8742             var dom = this.dom;
8743             this.on("mousedown", function(){
8744                 Ext.fly(dom, INTERNAL).addCls(className);
8745                 var d = Ext.getDoc(),
8746                     fn = function(){
8747                         Ext.fly(dom, INTERNAL).removeCls(className);
8748                         d.removeListener("mouseup", fn);
8749                     };
8750                 d.on("mouseup", fn);
8751             });
8752             return this;
8753         },
8754
8755         
8756
8757         getViewSize : function(){
8758             var me = this,
8759                 dom = me.dom,
8760                 isDoc = (dom == Ext.getDoc().dom || dom == Ext.getBody().dom),
8761                 style, overflow, ret;
8762
8763             
8764             if (isDoc) {
8765                 ret = {
8766                     width : Ext.core.Element.getViewWidth(),
8767                     height : Ext.core.Element.getViewHeight()
8768                 };
8769
8770             
8771             }
8772             else {
8773                 
8774                 
8775                 if (Ext.isIE6 || Ext.isIEQuirks) {
8776                     style = dom.style;
8777                     overflow = style.overflow;
8778                     me.setStyle({ overflow: 'hidden'});
8779                 }
8780                 ret = {
8781                     width : dom.clientWidth,
8782                     height : dom.clientHeight
8783                 };
8784                 if (Ext.isIE6 || Ext.isIEQuirks) {
8785                     me.setStyle({ overflow: overflow });
8786                 }
8787             }
8788             return ret;
8789         },
8790
8791         
8792
8793         getStyleSize : function(){
8794             var me = this,
8795                 doc = document,
8796                 d = this.dom,
8797                 isDoc = (d == doc || d == doc.body),
8798                 s = d.style,
8799                 w, h;
8800
8801             
8802             if (isDoc) {
8803                 return {
8804                     width : Ext.core.Element.getViewWidth(),
8805                     height : Ext.core.Element.getViewHeight()
8806                 };
8807             }
8808             
8809             if(s.width && s.width != 'auto'){
8810                 w = parseFloat(s.width);
8811                 if(me.isBorderBox()){
8812                    w -= me.getFrameWidth('lr');
8813                 }
8814             }
8815             
8816             if(s.height && s.height != 'auto'){
8817                 h = parseFloat(s.height);
8818                 if(me.isBorderBox()){
8819                    h -= me.getFrameWidth('tb');
8820                 }
8821             }
8822             
8823             return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
8824         },
8825
8826         
8827         getSize : function(contentSize){
8828             return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
8829         },
8830
8831         
8832         repaint : function(){
8833             var dom = this.dom;
8834             this.addCls(Ext.baseCSSPrefix + 'repaint');
8835             setTimeout(function(){
8836                 Ext.fly(dom).removeCls(Ext.baseCSSPrefix + 'repaint');
8837             }, 1);
8838             return this;
8839         },
8840
8841         
8842         unselectable : function(){
8843             var me = this;
8844             me.dom.unselectable = "on";
8845
8846             me.swallowEvent("selectstart", true);
8847             me.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8848             me.addCls(Ext.baseCSSPrefix + 'unselectable');
8849             
8850             return me;
8851         },
8852
8853         
8854         getMargin : function(side){
8855             var me = this,
8856                 hash = {t:"top", l:"left", r:"right", b: "bottom"},
8857                 o = {},
8858                 key;
8859
8860             if (!side) {
8861                 for (key in me.margins){
8862                     o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
8863                 }
8864                 return o;
8865             } else {
8866                 return me.addStyles.call(me, side, me.margins);
8867             }
8868         }
8869     });
8870 })();
8871
8872
8873 Ext.core.Element.VISIBILITY = 1;
8874
8875 Ext.core.Element.DISPLAY = 2;
8876
8877
8878 Ext.core.Element.OFFSETS = 3;
8879
8880
8881 Ext.core.Element.ASCLASS = 4;
8882
8883
8884 Ext.core.Element.visibilityCls = Ext.baseCSSPrefix + 'hide-nosize';
8885
8886 Ext.core.Element.addMethods(function(){
8887     var El = Ext.core.Element,
8888         OPACITY = "opacity",
8889         VISIBILITY = "visibility",
8890         DISPLAY = "display",
8891         HIDDEN = "hidden",
8892         OFFSETS = "offsets",
8893         ASCLASS = "asclass",
8894         NONE = "none",
8895         NOSIZE = 'nosize',
8896         ORIGINALDISPLAY = 'originalDisplay',
8897         VISMODE = 'visibilityMode',
8898         ISVISIBLE = 'isVisible',
8899         data = El.data,
8900         getDisplay = function(dom){
8901             var d = data(dom, ORIGINALDISPLAY);
8902             if(d === undefined){
8903                 data(dom, ORIGINALDISPLAY, d = '');
8904             }
8905             return d;
8906         },
8907         getVisMode = function(dom){
8908             var m = data(dom, VISMODE);
8909             if(m === undefined){
8910                 data(dom, VISMODE, m = 1);
8911             }
8912             return m;
8913         };
8914
8915     return {
8916         
8917         originalDisplay : "",
8918         visibilityMode : 1,
8919
8920         
8921         setVisibilityMode : function(visMode){
8922             data(this.dom, VISMODE, visMode);
8923             return this;
8924         },
8925
8926         
8927         isVisible : function() {
8928             var me = this,
8929                 dom = me.dom,
8930                 visible = data(dom, ISVISIBLE);
8931
8932             if(typeof visible == 'boolean'){ 
8933                 return visible;
8934             }
8935             
8936             visible = !me.isStyle(VISIBILITY, HIDDEN) &&
8937                       !me.isStyle(DISPLAY, NONE) &&
8938                       !((getVisMode(dom) == El.ASCLASS) && me.hasCls(me.visibilityCls || El.visibilityCls));
8939
8940             data(dom, ISVISIBLE, visible);
8941             return visible;
8942         },
8943
8944         
8945         setVisible : function(visible, animate){
8946             var me = this, isDisplay, isVisibility, isOffsets, isNosize,
8947                 dom = me.dom,
8948                 visMode = getVisMode(dom);
8949
8950
8951             
8952             if (typeof animate == 'string'){
8953                 switch (animate) {
8954                     case DISPLAY:
8955                         visMode = El.DISPLAY;
8956                         break;
8957                     case VISIBILITY:
8958                         visMode = El.VISIBILITY;
8959                         break;
8960                     case OFFSETS:
8961                         visMode = El.OFFSETS;
8962                         break;
8963                     case NOSIZE:
8964                     case ASCLASS:
8965                         visMode = El.ASCLASS;
8966                         break;
8967                 }
8968                 me.setVisibilityMode(visMode);
8969                 animate = false;
8970             }
8971
8972             if (!animate || !me.anim) {
8973                 if(visMode == El.ASCLASS ){
8974
8975                     me[visible?'removeCls':'addCls'](me.visibilityCls || El.visibilityCls);
8976
8977                 } else if (visMode == El.DISPLAY){
8978
8979                     return me.setDisplayed(visible);
8980
8981                 } else if (visMode == El.OFFSETS){
8982
8983                     if (!visible){
8984                         
8985                         if (!me.hideModeStyles) {
8986                             me.hideModeStyles = {
8987                                 position: me.getStyle('position'),
8988                                 top: me.getStyle('top'),
8989                                 left: me.getStyle('left')
8990                             };
8991                         }
8992                         me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
8993                     }
8994
8995                     
8996                     
8997                     else if (me.hideModeStyles) {
8998                         me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
8999                         delete me.hideModeStyles;
9000                     }
9001
9002                 }else{
9003                     me.fixDisplay();
9004                     
9005                     dom.style.visibility = visible ? '' : HIDDEN;
9006                 }
9007             }else{
9008                 
9009                 if(visible){
9010                     me.setOpacity(0.01);
9011                     me.setVisible(true);
9012                 }
9013                 if (!Ext.isObject(animate)) {
9014                     animate = {
9015                         duration: 350,
9016                         easing: 'ease-in'
9017                     };
9018                 }
9019                 me.animate(Ext.applyIf({
9020                     callback: function() {
9021                         visible || me.setVisible(false).setOpacity(1);
9022                     },
9023                     to: {
9024                         opacity: (visible) ? 1 : 0
9025                     }
9026                 }, animate));
9027             }
9028             data(dom, ISVISIBLE, visible);  
9029             return me;
9030         },
9031
9032
9033         
9034         hasMetrics  : function(){
9035             var dom = this.dom;
9036             return this.isVisible() || (getVisMode(dom) == El.OFFSETS) || (getVisMode(dom) == El.VISIBILITY);
9037         },
9038
9039         
9040         toggle : function(animate){
9041             var me = this;
9042             me.setVisible(!me.isVisible(), me.anim(animate));
9043             return me;
9044         },
9045
9046         
9047         setDisplayed : function(value) {
9048             if(typeof value == "boolean"){
9049                value = value ? getDisplay(this.dom) : NONE;
9050             }
9051             this.setStyle(DISPLAY, value);
9052             return this;
9053         },
9054
9055         
9056         fixDisplay : function(){
9057             var me = this;
9058             if (me.isStyle(DISPLAY, NONE)) {
9059                 me.setStyle(VISIBILITY, HIDDEN);
9060                 me.setStyle(DISPLAY, getDisplay(this.dom)); 
9061                 if (me.isStyle(DISPLAY, NONE)) { 
9062                     me.setStyle(DISPLAY, "block");
9063                 }
9064             }
9065         },
9066
9067         
9068         hide : function(animate){
9069             
9070             if (typeof animate == 'string'){
9071                 this.setVisible(false, animate);
9072                 return this;
9073             }
9074             this.setVisible(false, this.anim(animate));
9075             return this;
9076         },
9077
9078         
9079         show : function(animate){
9080             
9081             if (typeof animate == 'string'){
9082                 this.setVisible(true, animate);
9083                 return this;
9084             }
9085             this.setVisible(true, this.anim(animate));
9086             return this;
9087         }
9088     };
9089 }());
9090
9091 Ext.applyIf(Ext.core.Element.prototype, {
9092     
9093     animate: function(config) {
9094         var me = this;
9095         if (!me.id) {
9096             me = Ext.get(me.dom);
9097         }
9098         if (Ext.fx.Manager.hasFxBlock(me.id)) {
9099             return me;
9100         }
9101         Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(config)));
9102         return this;
9103     },
9104
9105     
9106     anim: function(config) {
9107         if (!Ext.isObject(config)) {
9108             return (config) ? {} : false;
9109         }
9110
9111         var me = this,
9112             duration = config.duration || Ext.fx.Anim.prototype.duration,
9113             easing = config.easing || 'ease',
9114             animConfig;
9115
9116         if (config.stopAnimation) {
9117             me.stopAnimation();
9118         }
9119
9120         Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
9121
9122         
9123         Ext.fx.Manager.setFxDefaults(me.id, {
9124             delay: 0
9125         });
9126
9127         animConfig = {
9128             target: me,
9129             remove: config.remove,
9130             alternate: config.alternate || false,
9131             duration: duration,
9132             easing: easing,
9133             callback: config.callback,
9134             listeners: config.listeners,
9135             iterations: config.iterations || 1,
9136             scope: config.scope,
9137             block: config.block,
9138             concurrent: config.concurrent,
9139             delay: config.delay || 0,
9140             paused: true,
9141             keyframes: config.keyframes,
9142             from: config.from || {},
9143             to: Ext.apply({}, config)
9144         };
9145         Ext.apply(animConfig.to, config.to);
9146
9147         
9148         delete animConfig.to.to;
9149         delete animConfig.to.from;
9150         delete animConfig.to.remove;
9151         delete animConfig.to.alternate;
9152         delete animConfig.to.keyframes;
9153         delete animConfig.to.iterations;
9154         delete animConfig.to.listeners;
9155         delete animConfig.to.target;
9156         delete animConfig.to.paused;
9157         delete animConfig.to.callback;
9158         delete animConfig.to.scope;
9159         delete animConfig.to.duration;
9160         delete animConfig.to.easing;
9161         delete animConfig.to.concurrent;
9162         delete animConfig.to.block;
9163         delete animConfig.to.stopAnimation;
9164         delete animConfig.to.delay;
9165         return animConfig;
9166     },
9167
9168     
9169     slideIn: function(anchor, obj, slideOut) { 
9170         var me = this,
9171             elStyle = me.dom.style,
9172             beforeAnim, wrapAnim;
9173
9174         anchor = anchor || "t";
9175         obj = obj || {};
9176
9177         beforeAnim = function() {
9178             var animScope = this,
9179                 listeners = obj.listeners,
9180                 box, position, restoreSize, wrap, anim;
9181
9182             if (!slideOut) {
9183                 me.fixDisplay();
9184             }
9185
9186             box = me.getBox();
9187             if ((anchor == 't' || anchor == 'b') && box.height == 0) {
9188                 box.height = me.dom.scrollHeight;
9189             }
9190             else if ((anchor == 'l' || anchor == 'r') && box.width == 0) {
9191                 box.width = me.dom.scrollWidth;
9192             }
9193             
9194             position = me.getPositioning();
9195             me.setSize(box.width, box.height);
9196
9197             wrap = me.wrap({
9198                 style: {
9199                     visibility: slideOut ? 'visible' : 'hidden'
9200                 }
9201             });
9202             wrap.setPositioning(position);
9203             if (wrap.isStyle('position', 'static')) {
9204                 wrap.position('relative');
9205             }
9206             me.clearPositioning('auto');
9207             wrap.clip();
9208
9209             
9210             
9211             
9212             me.setStyle({
9213                 visibility: '',
9214                 position: 'absolute'
9215             });
9216             if (slideOut) {
9217                 wrap.setSize(box.width, box.height);
9218             }
9219
9220             switch (anchor) {
9221                 case 't':
9222                     anim = {
9223                         from: {
9224                             width: box.width + 'px',
9225                             height: '0px'
9226                         },
9227                         to: {
9228                             width: box.width + 'px',
9229                             height: box.height + 'px'
9230                         }
9231                     };
9232                     elStyle.bottom = '0px';
9233                     break;
9234                 case 'l':
9235                     anim = {
9236                         from: {
9237                             width: '0px',
9238                             height: box.height + 'px'
9239                         },
9240                         to: {
9241                             width: box.width + 'px',
9242                             height: box.height + 'px'
9243                         }
9244                     };
9245                     elStyle.right = '0px';
9246                     break;
9247                 case 'r':
9248                     anim = {
9249                         from: {
9250                             x: box.x + box.width,
9251                             width: '0px',
9252                             height: box.height + 'px'
9253                         },
9254                         to: {
9255                             x: box.x,
9256                             width: box.width + 'px',
9257                             height: box.height + 'px'
9258                         }
9259                     };
9260                     break;
9261                 case 'b':
9262                     anim = {
9263                         from: {
9264                             y: box.y + box.height,
9265                             width: box.width + 'px',
9266                             height: '0px'
9267                         },
9268                         to: {
9269                             y: box.y,
9270                             width: box.width + 'px',
9271                             height: box.height + 'px'
9272                         }
9273                     };
9274                     break;
9275                 case 'tl':
9276                     anim = {
9277                         from: {
9278                             x: box.x,
9279                             y: box.y,
9280                             width: '0px',
9281                             height: '0px'
9282                         },
9283                         to: {
9284                             width: box.width + 'px',
9285                             height: box.height + 'px'
9286                         }
9287                     };
9288                     elStyle.bottom = '0px';
9289                     elStyle.right = '0px';
9290                     break;
9291                 case 'bl':
9292                     anim = {
9293                         from: {
9294                             x: box.x + box.width,
9295                             width: '0px',
9296                             height: '0px'
9297                         },
9298                         to: {
9299                             x: box.x,
9300                             width: box.width + 'px',
9301                             height: box.height + 'px'
9302                         }
9303                     };
9304                     elStyle.right = '0px';
9305                     break;
9306                 case 'br':
9307                     anim = {
9308                         from: {
9309                             x: box.x + box.width,
9310                             y: box.y + box.height,
9311                             width: '0px',
9312                             height: '0px'
9313                         },
9314                         to: {
9315                             x: box.x,
9316                             y: box.y,
9317                             width: box.width + 'px',
9318                             height: box.height + 'px'
9319                         }
9320                     };
9321                     break;
9322                 case 'tr':
9323                     anim = {
9324                         from: {
9325                             y: box.y + box.height,
9326                             width: '0px',
9327                             height: '0px'
9328                         },
9329                         to: {
9330                             y: box.y,
9331                             width: box.width + 'px',
9332                             height: box.height + 'px'
9333                         }
9334                     };
9335                     elStyle.bottom = '0px';
9336                     break;
9337             }
9338
9339             wrap.show();
9340             wrapAnim = Ext.apply({}, obj);
9341             delete wrapAnim.listeners;
9342             wrapAnim = Ext.create('Ext.fx.Anim', Ext.applyIf(wrapAnim, {
9343                 target: wrap,
9344                 duration: 500,
9345                 easing: 'ease-out',
9346                 from: slideOut ? anim.to : anim.from,
9347                 to: slideOut ? anim.from : anim.to
9348             }));
9349
9350             
9351             wrapAnim.on('afteranimate', function() {
9352                 if (slideOut) {
9353                     me.setPositioning(position);
9354                     if (obj.useDisplay) {
9355                         me.setDisplayed(false);
9356                     } else {
9357                         me.hide();   
9358                     }
9359                 }
9360                 else {
9361                     me.clearPositioning();
9362                     me.setPositioning(position);
9363                 }
9364                 if (wrap.dom) {
9365                     wrap.dom.parentNode.insertBefore(me.dom, wrap.dom); 
9366                     wrap.remove();
9367                 }
9368                 me.setSize(box.width, box.height);
9369                 animScope.end();
9370             });
9371             
9372             if (listeners) {
9373                 wrapAnim.on(listeners);
9374             }
9375         };
9376
9377         me.animate({
9378             duration: obj.duration ? obj.duration * 2 : 1000,
9379             listeners: {
9380                 beforeanimate: {
9381                     fn: beforeAnim
9382                 },
9383                 afteranimate: {
9384                     fn: function() {
9385                         if (wrapAnim && wrapAnim.running) {
9386                             wrapAnim.end();
9387                         }
9388                     }
9389                 }
9390             }
9391         });
9392         return me;
9393     },
9394
9395     
9396     
9397     slideOut: function(anchor, o) {
9398         return this.slideIn(anchor, o, true);
9399     },
9400
9401     
9402
9403     puff: function(obj) {
9404         var me = this,
9405             beforeAnim;
9406         obj = Ext.applyIf(obj || {}, {
9407             easing: 'ease-out',
9408             duration: 500,
9409             useDisplay: false
9410         });
9411
9412         beforeAnim = function() {
9413             me.clearOpacity();
9414             me.show();
9415
9416             var box = me.getBox(),
9417                 fontSize = me.getStyle('fontSize'),
9418                 position = me.getPositioning();
9419             this.to = {
9420                 width: box.width * 2,
9421                 height: box.height * 2,
9422                 x: box.x - (box.width / 2),
9423                 y: box.y - (box.height /2),
9424                 opacity: 0,
9425                 fontSize: '200%'
9426             };
9427             this.on('afteranimate',function() {
9428                 if (me.dom) {
9429                     if (obj.useDisplay) {
9430                         me.setDisplayed(false);
9431                     } else {
9432                         me.hide();
9433                     }
9434                     me.clearOpacity();  
9435                     me.setPositioning(position);
9436                     me.setStyle({fontSize: fontSize});
9437                 }
9438             });
9439         };
9440
9441         me.animate({
9442             duration: obj.duration,
9443             easing: obj.easing,
9444             listeners: {
9445                 beforeanimate: {
9446                     fn: beforeAnim
9447                 }
9448             }
9449         });
9450         return me;
9451     },
9452
9453     
9454     switchOff: function(obj) {
9455         var me = this,
9456             beforeAnim;
9457         
9458         obj = Ext.applyIf(obj || {}, {
9459             easing: 'ease-in',
9460             duration: 500,
9461             remove: false,
9462             useDisplay: false
9463         });
9464
9465         beforeAnim = function() {
9466             var animScope = this,
9467                 size = me.getSize(),
9468                 xy = me.getXY(),
9469                 keyframe, position;
9470             me.clearOpacity();
9471             me.clip();
9472             position = me.getPositioning();
9473
9474             keyframe = Ext.create('Ext.fx.Animator', {
9475                 target: me,
9476                 duration: obj.duration,
9477                 easing: obj.easing,
9478                 keyframes: {
9479                     33: {
9480                         opacity: 0.3
9481                     },
9482                     66: {
9483                         height: 1,
9484                         y: xy[1] + size.height / 2
9485                     },
9486                     100: {
9487                         width: 1,
9488                         x: xy[0] + size.width / 2
9489                     }
9490                 }
9491             });
9492             keyframe.on('afteranimate', function() {
9493                 if (obj.useDisplay) {
9494                     me.setDisplayed(false);
9495                 } else {
9496                     me.hide();
9497                 }  
9498                 me.clearOpacity();
9499                 me.setPositioning(position);
9500                 me.setSize(size);
9501                 animScope.end();
9502             });
9503         };
9504         me.animate({
9505             duration: (obj.duration * 2),
9506             listeners: {
9507                 beforeanimate: {
9508                     fn: beforeAnim
9509                 }
9510             }
9511         });
9512         return me;
9513     },
9514
9515    
9516     frame : function(color, count, obj){
9517         var me = this,
9518             beforeAnim;
9519
9520         color = color || '#C3DAF9';
9521         count = count || 1;
9522         obj = obj || {};
9523
9524         beforeAnim = function() {
9525             me.show();
9526             var animScope = this,
9527                 box = me.getBox(),
9528                 proxy = Ext.getBody().createChild({
9529                     style: {
9530                         position : 'absolute',
9531                         'pointer-events': 'none',
9532                         'z-index': 35000,
9533                         border : '0px solid ' + color
9534                     }
9535                 }),
9536                 proxyAnim;
9537             proxyAnim = Ext.create('Ext.fx.Anim', {
9538                 target: proxy,
9539                 duration: obj.duration || 1000,
9540                 iterations: count,
9541                 from: {
9542                     top: box.y,
9543                     left: box.x,
9544                     borderWidth: 0,
9545                     opacity: 1,
9546                     height: box.height,
9547                     width: box.width
9548                 },
9549                 to: {
9550                     top: box.y - 20,
9551                     left: box.x - 20,
9552                     borderWidth: 10,
9553                     opacity: 0,
9554                     height: box.height + 40,
9555                     width: box.width + 40
9556                 }
9557             });
9558             proxyAnim.on('afteranimate', function() {
9559                 proxy.remove();
9560                 animScope.end();
9561             });
9562         };
9563
9564         me.animate({
9565             duration: (obj.duration * 2) || 2000,
9566             listeners: {
9567                 beforeanimate: {
9568                     fn: beforeAnim
9569                 }
9570             }
9571         });
9572         return me;
9573     },
9574
9575     
9576     ghost: function(anchor, obj) {
9577         var me = this,
9578             beforeAnim;
9579
9580         anchor = anchor || "b";
9581         beforeAnim = function() {
9582             var width = me.getWidth(),
9583                 height = me.getHeight(),
9584                 xy = me.getXY(),
9585                 position = me.getPositioning(),
9586                 to = {
9587                     opacity: 0
9588                 };
9589             switch (anchor) {
9590                 case 't':
9591                     to.y = xy[1] - height;
9592                     break;
9593                 case 'l':
9594                     to.x = xy[0] - width;
9595                     break;
9596                 case 'r':
9597                     to.x = xy[0] + width;
9598                     break;
9599                 case 'b':
9600                     to.y = xy[1] + height;
9601                     break;
9602                 case 'tl':
9603                     to.x = xy[0] - width;
9604                     to.y = xy[1] - height;
9605                     break;
9606                 case 'bl':
9607                     to.x = xy[0] - width;
9608                     to.y = xy[1] + height;
9609                     break;
9610                 case 'br':
9611                     to.x = xy[0] + width;
9612                     to.y = xy[1] + height;
9613                     break;
9614                 case 'tr':
9615                     to.x = xy[0] + width;
9616                     to.y = xy[1] - height;
9617                     break;
9618             }
9619             this.to = to;
9620             this.on('afteranimate', function () {
9621                 if (me.dom) {
9622                     me.hide();
9623                     me.clearOpacity();
9624                     me.setPositioning(position);
9625                 }
9626             });
9627         };
9628
9629         me.animate(Ext.applyIf(obj || {}, {
9630             duration: 500,
9631             easing: 'ease-out',
9632             listeners: {
9633                 beforeanimate: {
9634                     fn: beforeAnim
9635                 }
9636             }
9637         }));
9638         return me;
9639     },
9640
9641      
9642     highlight: function(color, o) {
9643         var me = this,
9644             dom = me.dom,
9645             from = {},
9646             restore, to, attr, lns, event, fn;
9647
9648         o = o || {};
9649         lns = o.listeners || {};
9650         attr = o.attr || 'backgroundColor';
9651         from[attr] = color || 'ffff9c';
9652         
9653         if (!o.to) {
9654             to = {};
9655             to[attr] = o.endColor || me.getColor(attr, 'ffffff', '');
9656         }
9657         else {
9658             to = o.to;
9659         }
9660         
9661         
9662         o.listeners = Ext.apply(Ext.apply({}, lns), {
9663             beforeanimate: function() {
9664                 restore = dom.style[attr];
9665                 me.clearOpacity();
9666                 me.show();
9667                 
9668                 event = lns.beforeanimate;
9669                 if (event) {
9670                     fn = event.fn || event;
9671                     return fn.apply(event.scope || lns.scope || window, arguments);
9672                 }
9673             },
9674             afteranimate: function() {
9675                 if (dom) {
9676                     dom.style[attr] = restore;
9677                 }
9678                 
9679                 event = lns.afteranimate;
9680                 if (event) {
9681                     fn = event.fn || event;
9682                     fn.apply(event.scope || lns.scope || window, arguments);
9683                 }
9684             }
9685         });
9686
9687         me.animate(Ext.apply({}, o, {
9688             duration: 1000,
9689             easing: 'ease-in',
9690             from: from,
9691             to: to
9692         }));
9693         return me;
9694     },
9695
9696    
9697     pause: function(ms) {
9698         var me = this;
9699         Ext.fx.Manager.setFxDefaults(me.id, {
9700             delay: ms
9701         });
9702         return me;
9703     },
9704
9705    
9706     fadeIn: function(o) {
9707         this.animate(Ext.apply({}, o, {
9708             opacity: 1
9709         }));
9710         return this;
9711     },
9712
9713    
9714     fadeOut: function(o) {
9715         this.animate(Ext.apply({}, o, {
9716             opacity: 0
9717         }));
9718         return this;
9719     },
9720
9721    
9722     scale: function(w, h, o) {
9723         this.animate(Ext.apply({}, o, {
9724             width: w,
9725             height: h
9726         }));
9727         return this;
9728     },
9729
9730    
9731     shift: function(config) {
9732         this.animate(config);
9733         return this;
9734     }
9735 });
9736
9737
9738 Ext.applyIf(Ext.core.Element, {
9739     unitRe: /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
9740     camelRe: /(-[a-z])/gi,
9741     opacityRe: /alpha\(opacity=(.*)\)/i,
9742     cssRe: /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
9743     propertyCache: {},
9744     defaultUnit : "px",
9745     borders: {l: 'border-left-width', r: 'border-right-width', t: 'border-top-width', b: 'border-bottom-width'},
9746     paddings: {l: 'padding-left', r: 'padding-right', t: 'padding-top', b: 'padding-bottom'},
9747     margins: {l: 'margin-left', r: 'margin-right', t: 'margin-top', b: 'margin-bottom'},
9748
9749     
9750     addUnits : Ext.core.Element.prototype.addUnits,
9751
9752     
9753     parseBox : function(box) {
9754         if (Ext.isObject(box)) {
9755             return {
9756                 top: box.top || 0,
9757                 right: box.right || 0,
9758                 bottom: box.bottom || 0,
9759                 left: box.left || 0
9760             };
9761         } else {
9762             if (typeof box != 'string') {
9763                 box = box.toString();
9764             }
9765             var parts  = box.split(' '),
9766                 ln = parts.length;
9767     
9768             if (ln == 1) {
9769                 parts[1] = parts[2] = parts[3] = parts[0];
9770             }
9771             else if (ln == 2) {
9772                 parts[2] = parts[0];
9773                 parts[3] = parts[1];
9774             }
9775             else if (ln == 3) {
9776                 parts[3] = parts[1];
9777             }
9778     
9779             return {
9780                 top   :parseFloat(parts[0]) || 0,
9781                 right :parseFloat(parts[1]) || 0,
9782                 bottom:parseFloat(parts[2]) || 0,
9783                 left  :parseFloat(parts[3]) || 0
9784             };
9785         }
9786         
9787     },
9788     
9789     
9790     unitizeBox : function(box, units) {
9791         var A = this.addUnits,
9792             B = this.parseBox(box);
9793             
9794         return A(B.top, units) + ' ' +
9795                A(B.right, units) + ' ' +
9796                A(B.bottom, units) + ' ' +
9797                A(B.left, units);
9798         
9799     },
9800
9801     
9802     camelReplaceFn : function(m, a) {
9803         return a.charAt(1).toUpperCase();
9804     },
9805
9806     
9807     normalize : function(prop) {
9808         if (prop == 'float') {
9809             prop = Ext.supports.Float ? 'cssFloat' : 'styleFloat';
9810         }
9811         return this.propertyCache[prop] || (this.propertyCache[prop] = prop.replace(this.camelRe, this.camelReplaceFn));
9812     },
9813
9814     
9815     getDocumentHeight: function() {
9816         return Math.max(!Ext.isStrict ? document.body.scrollHeight : document.documentElement.scrollHeight, this.getViewportHeight());
9817     },
9818
9819     
9820     getDocumentWidth: function() {
9821         return Math.max(!Ext.isStrict ? document.body.scrollWidth : document.documentElement.scrollWidth, this.getViewportWidth());
9822     },
9823
9824     
9825     getViewportHeight: function(){
9826         return window.innerHeight;
9827     },
9828
9829     
9830     getViewportWidth : function() {
9831         return window.innerWidth;
9832     },
9833
9834     
9835     getViewSize : function() {
9836         return {
9837             width: window.innerWidth,
9838             height: window.innerHeight
9839         };
9840     },
9841
9842     
9843     getOrientation : function() {
9844         if (Ext.supports.OrientationChange) {
9845             return (window.orientation == 0) ? 'portrait' : 'landscape';
9846         }
9847         
9848         return (window.innerHeight > window.innerWidth) ? 'portrait' : 'landscape';
9849     },
9850
9851     
9852     fromPoint: function(x, y) {
9853         return Ext.get(document.elementFromPoint(x, y));
9854     },
9855     
9856     
9857     parseStyles: function(styles){
9858         var out = {},
9859             cssRe = this.cssRe,
9860             matches;
9861             
9862         if (styles) {
9863             
9864             
9865             
9866             
9867             cssRe.lastIndex = 0;
9868             while ((matches = cssRe.exec(styles))) {
9869                 out[matches[1]] = matches[2];
9870             }
9871         }
9872         return out;
9873     }
9874 });
9875
9876
9877 Ext.CompositeElementLite = function(els, root){
9878     
9879     this.elements = [];
9880     this.add(els, root);
9881     this.el = new Ext.core.Element.Flyweight();
9882 };
9883
9884 Ext.CompositeElementLite.prototype = {
9885     isComposite: true,
9886
9887     
9888     getElement : function(el){
9889         
9890         var e = this.el;
9891         e.dom = el;
9892         e.id = el.id;
9893         return e;
9894     },
9895
9896     
9897     transformElement : function(el){
9898         return Ext.getDom(el);
9899     },
9900
9901     
9902     getCount : function(){
9903         return this.elements.length;
9904     },
9905     
9906     add : function(els, root){
9907         var me = this,
9908             elements = me.elements;
9909         if(!els){
9910             return this;
9911         }
9912         if(typeof els == "string"){
9913             els = Ext.core.Element.selectorFunction(els, root);
9914         }else if(els.isComposite){
9915             els = els.elements;
9916         }else if(!Ext.isIterable(els)){
9917             els = [els];
9918         }
9919
9920         for(var i = 0, len = els.length; i < len; ++i){
9921             elements.push(me.transformElement(els[i]));
9922         }
9923         return me;
9924     },
9925
9926     invoke : function(fn, args){
9927         var me = this,
9928             els = me.elements,
9929             len = els.length,
9930             e,
9931             i;
9932
9933         for(i = 0; i < len; i++) {
9934             e = els[i];
9935             if(e){
9936                 Ext.core.Element.prototype[fn].apply(me.getElement(e), args);
9937             }
9938         }
9939         return me;
9940     },
9941     
9942     item : function(index){
9943         var me = this,
9944             el = me.elements[index],
9945             out = null;
9946
9947         if(el){
9948             out = me.getElement(el);
9949         }
9950         return out;
9951     },
9952
9953     
9954     addListener : function(eventName, handler, scope, opt){
9955         var els = this.elements,
9956             len = els.length,
9957             i, e;
9958
9959         for(i = 0; i<len; i++) {
9960             e = els[i];
9961             if(e) {
9962                 Ext.EventManager.on(e, eventName, handler, scope || e, opt);
9963             }
9964         }
9965         return this;
9966     },
9967     
9968     each : function(fn, scope){
9969         var me = this,
9970             els = me.elements,
9971             len = els.length,
9972             i, e;
9973
9974         for(i = 0; i<len; i++) {
9975             e = els[i];
9976             if(e){
9977                 e = this.getElement(e);
9978                 if(fn.call(scope || e, e, me, i) === false){
9979                     break;
9980                 }
9981             }
9982         }
9983         return me;
9984     },
9985
9986     
9987     fill : function(els){
9988         var me = this;
9989         me.elements = [];
9990         me.add(els);
9991         return me;
9992     },
9993
9994     
9995     filter : function(selector){
9996         var els = [],
9997             me = this,
9998             fn = Ext.isFunction(selector) ? selector
9999                 : function(el){
10000                     return el.is(selector);
10001                 };
10002
10003         me.each(function(el, self, i) {
10004             if (fn(el, i) !== false) {
10005                 els[els.length] = me.transformElement(el);
10006             }
10007         });
10008         
10009         me.elements = els;
10010         return me;
10011     },
10012
10013     
10014     indexOf : function(el){
10015         return Ext.Array.indexOf(this.elements, this.transformElement(el));
10016     },
10017
10018     
10019     replaceElement : function(el, replacement, domReplace){
10020         var index = !isNaN(el) ? el : this.indexOf(el),
10021             d;
10022         if(index > -1){
10023             replacement = Ext.getDom(replacement);
10024             if(domReplace){
10025                 d = this.elements[index];
10026                 d.parentNode.insertBefore(replacement, d);
10027                 Ext.removeNode(d);
10028             }
10029             this.elements.splice(index, 1, replacement);
10030         }
10031         return this;
10032     },
10033
10034     
10035     clear : function(){
10036         this.elements = [];
10037     }
10038 };
10039
10040 Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
10041
10042
10043 Ext.CompositeElementLite.importElementMethods = function() {
10044     var fnName,
10045         ElProto = Ext.core.Element.prototype,
10046         CelProto = Ext.CompositeElementLite.prototype;
10047
10048     for (fnName in ElProto) {
10049         if (typeof ElProto[fnName] == 'function'){
10050             (function(fnName) {
10051                 CelProto[fnName] = CelProto[fnName] || function() {
10052                     return this.invoke(fnName, arguments);
10053                 };
10054             }).call(CelProto, fnName);
10055
10056         }
10057     }
10058 };
10059
10060 Ext.CompositeElementLite.importElementMethods();
10061
10062 if(Ext.DomQuery){
10063     Ext.core.Element.selectorFunction = Ext.DomQuery.select;
10064 }
10065
10066
10067 Ext.core.Element.select = function(selector, root){
10068     var els;
10069     if(typeof selector == "string"){
10070         els = Ext.core.Element.selectorFunction(selector, root);
10071     }else if(selector.length !== undefined){
10072         els = selector;
10073     }else{
10074         Ext.Error.raise({
10075             sourceClass: "Ext.core.Element",
10076             sourceMethod: "select",
10077             selector: selector,
10078             root: root,
10079             msg: "Invalid selector specified: " + selector
10080         });
10081     }
10082     return new Ext.CompositeElementLite(els);
10083 };
10084
10085 Ext.select = Ext.core.Element.select;
10086
10087
10088 Ext.util.DelayedTask = function(fn, scope, args) {
10089     var me = this,
10090         id,
10091         call = function() {
10092             clearInterval(id);
10093             id = null;
10094             fn.apply(scope, args || []);
10095         };
10096
10097     
10098     this.delay = function(delay, newFn, newScope, newArgs) {
10099         me.cancel();
10100         fn = newFn || fn;
10101         scope = newScope || scope;
10102         args = newArgs || args;
10103         id = setInterval(call, delay);
10104     };
10105
10106     
10107     this.cancel = function(){
10108         if (id) {
10109             clearInterval(id);
10110             id = null;
10111         }
10112     };
10113 };
10114 Ext.require('Ext.util.DelayedTask', function() {
10115
10116     Ext.util.Event = Ext.extend(Object, (function() {
10117         function createBuffered(handler, listener, o, scope) {
10118             listener.task = new Ext.util.DelayedTask();
10119             return function() {
10120                 listener.task.delay(o.buffer, handler, scope, Ext.Array.toArray(arguments));
10121             };
10122         }
10123
10124         function createDelayed(handler, listener, o, scope) {
10125             return function() {
10126                 var task = new Ext.util.DelayedTask();
10127                 if (!listener.tasks) {
10128                     listener.tasks = [];
10129                 }
10130                 listener.tasks.push(task);
10131                 task.delay(o.delay || 10, handler, scope, Ext.Array.toArray(arguments));
10132             };
10133         }
10134
10135         function createSingle(handler, listener, o, scope) {
10136             return function() {
10137                 listener.ev.removeListener(listener.fn, scope);
10138                 return handler.apply(scope, arguments);
10139             };
10140         }
10141
10142         return {
10143             isEvent: true,
10144
10145             constructor: function(observable, name) {
10146                 this.name = name;
10147                 this.observable = observable;
10148                 this.listeners = [];
10149             },
10150
10151             addListener: function(fn, scope, options) {
10152                 var me = this,
10153                     listener;
10154                     scope = scope || me.observable;
10155
10156                 if (!fn) {
10157                     Ext.Error.raise({
10158                         sourceClass: Ext.getClassName(this.observable),
10159                         sourceMethod: "addListener",
10160                         msg: "The specified callback function is undefined"
10161                     });
10162                 }
10163
10164                 if (!me.isListening(fn, scope)) {
10165                     listener = me.createListener(fn, scope, options);
10166                     if (me.firing) {
10167                         
10168                         me.listeners = me.listeners.slice(0);
10169                     }
10170                     me.listeners.push(listener);
10171                 }
10172             },
10173
10174             createListener: function(fn, scope, o) {
10175                 o = o || {};
10176                 scope = scope || this.observable;
10177
10178                 var listener = {
10179                         fn: fn,
10180                         scope: scope,
10181                         o: o,
10182                         ev: this
10183                     },
10184                     handler = fn;
10185
10186                 
10187                 
10188                 if (o.single) {
10189                     handler = createSingle(handler, listener, o, scope);
10190                 }
10191                 if (o.delay) {
10192                     handler = createDelayed(handler, listener, o, scope);
10193                 }
10194                 if (o.buffer) {
10195                     handler = createBuffered(handler, listener, o, scope);
10196                 }
10197
10198                 listener.fireFn = handler;
10199                 return listener;
10200             },
10201
10202             findListener: function(fn, scope) {
10203                 var listeners = this.listeners,
10204                 i = listeners.length,
10205                 listener,
10206                 s;
10207
10208                 while (i--) {
10209                     listener = listeners[i];
10210                     if (listener) {
10211                         s = listener.scope;
10212                         if (listener.fn == fn && (s == scope || s == this.observable)) {
10213                             return i;
10214                         }
10215                     }
10216                 }
10217
10218                 return - 1;
10219             },
10220
10221             isListening: function(fn, scope) {
10222                 return this.findListener(fn, scope) !== -1;
10223             },
10224
10225             removeListener: function(fn, scope) {
10226                 var me = this,
10227                     index,
10228                     listener,
10229                     k;
10230                 index = me.findListener(fn, scope);
10231                 if (index != -1) {
10232                     listener = me.listeners[index];
10233
10234                     if (me.firing) {
10235                         me.listeners = me.listeners.slice(0);
10236                     }
10237
10238                     
10239                     if (listener.task) {
10240                         listener.task.cancel();
10241                         delete listener.task;
10242                     }
10243
10244                     
10245                     k = listener.tasks && listener.tasks.length;
10246                     if (k) {
10247                         while (k--) {
10248                             listener.tasks[k].cancel();
10249                         }
10250                         delete listener.tasks;
10251                     }
10252
10253                     
10254                     me.listeners.splice(index, 1);
10255                     return true;
10256                 }
10257
10258                 return false;
10259             },
10260
10261             
10262             clearListeners: function() {
10263                 var listeners = this.listeners,
10264                     i = listeners.length;
10265
10266                 while (i--) {
10267                     this.removeListener(listeners[i].fn, listeners[i].scope);
10268                 }
10269             },
10270
10271             fire: function() {
10272                 var me = this,
10273                     listeners = me.listeners,
10274                     count = listeners.length,
10275                     i,
10276                     args,
10277                     listener;
10278
10279                 if (count > 0) {
10280                     me.firing = true;
10281                     for (i = 0; i < count; i++) {
10282                         listener = listeners[i];
10283                         args = arguments.length ? Array.prototype.slice.call(arguments, 0) : [];
10284                         if (listener.o) {
10285                             args.push(listener.o);
10286                         }
10287                         if (listener && listener.fireFn.apply(listener.scope || me.observable, args) === false) {
10288                             return (me.firing = false);
10289                         }
10290                     }
10291                 }
10292                 me.firing = false;
10293                 return true;
10294             }
10295         };
10296     })());
10297 });
10298
10299
10300 Ext.EventManager = {
10301
10302     
10303
10304     
10305     hasBoundOnReady: false,
10306
10307     
10308     hasFiredReady: false,
10309
10310     
10311     readyTimeout: null,
10312
10313     
10314     hasOnReadyStateChange: false,
10315
10316     
10317     readyEvent: new Ext.util.Event(),
10318
10319     
10320     checkReadyState: function(){
10321         var me = Ext.EventManager;
10322
10323         if(window.attachEvent){
10324             
10325             if (window != top) {
10326                 return false;
10327             }
10328             try{
10329                 document.documentElement.doScroll('left');
10330             }catch(e){
10331                 return false;
10332             }
10333             me.fireDocReady();
10334             return true;
10335         }
10336         if (document.readyState == 'complete') {
10337             me.fireDocReady();
10338             return true;
10339         }
10340         me.readyTimeout = setTimeout(arguments.callee, 2);
10341         return false;
10342     },
10343
10344     
10345     bindReadyEvent: function(){
10346         var me = Ext.EventManager;
10347         if (me.hasBoundOnReady) {
10348             return;
10349         }
10350
10351         if (document.addEventListener) {
10352             document.addEventListener('DOMContentLoaded', me.fireDocReady, false);
10353             
10354             window.addEventListener('load', me.fireDocReady, false);
10355         } else {
10356             
10357             if (!me.checkReadyState()) {
10358                 document.attachEvent('onreadystatechange', me.checkReadyState);
10359                 me.hasOnReadyStateChange = true;
10360             }
10361             
10362             window.attachEvent('onload', me.fireDocReady, false);
10363         }
10364         me.hasBoundOnReady = true;
10365     },
10366
10367     
10368     fireDocReady: function(){
10369         var me = Ext.EventManager;
10370
10371         
10372         if (!me.hasFiredReady) {
10373             me.hasFiredReady = true;
10374
10375             if (document.addEventListener) {
10376                 document.removeEventListener('DOMContentLoaded', me.fireDocReady, false);
10377                 window.removeEventListener('load', me.fireDocReady, false);
10378             } else {
10379                 if (me.readyTimeout !== null) {
10380                     clearTimeout(me.readyTimeout);
10381                 }
10382                 if (me.hasOnReadyStateChange) {
10383                     document.detachEvent('onreadystatechange', me.checkReadyState);
10384                 }
10385                 window.detachEvent('onload', me.fireDocReady);
10386             }
10387             Ext.supports.init();
10388         }
10389         if (!Ext.isReady) {
10390             Ext.isReady = true;
10391             me.onWindowUnload();
10392             me.readyEvent.fire();
10393         }
10394     },
10395
10396     
10397     onDocumentReady: function(fn, scope, options){
10398         options = options || {};
10399         var me = Ext.EventManager,
10400             readyEvent = me.readyEvent;
10401
10402         
10403         options.single = true;
10404
10405         
10406         if (Ext.isReady) {
10407             readyEvent.addListener(fn, scope, options);
10408             readyEvent.fire();
10409         } else {
10410             options.delay = options.delay || 1;
10411             readyEvent.addListener(fn, scope, options);
10412             me.bindReadyEvent();
10413         }
10414     },
10415
10416
10417     
10418
10419     
10420     stoppedMouseDownEvent: new Ext.util.Event(),
10421
10422     
10423     propRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|freezeEvent)$/,
10424
10425     
10426     getId : function(element) {
10427         var skipGarbageCollection = false,
10428             id;
10429     
10430         element = Ext.getDom(element);
10431     
10432         if (element === document || element === window) {
10433             id = element === document ? Ext.documentId : Ext.windowId;
10434         }
10435         else {
10436             id = Ext.id(element);
10437         }
10438         
10439         if (element && (element.getElementById || element.navigator)) {
10440             skipGarbageCollection = true;
10441         }
10442     
10443         if (!Ext.cache[id]){
10444             Ext.core.Element.addToCache(new Ext.core.Element(element), id);
10445             if (skipGarbageCollection) {
10446                 Ext.cache[id].skipGarbageCollection = true;
10447             }
10448         }
10449         return id;
10450     },
10451
10452     
10453     prepareListenerConfig: function(element, config, isRemove){
10454         var me = this,
10455             propRe = me.propRe,
10456             key, value, args;
10457
10458         
10459         for (key in config) {
10460             if (config.hasOwnProperty(key)) {
10461                 
10462                 if (!propRe.test(key)) {
10463                     value = config[key];
10464                     
10465                     
10466                     if (Ext.isFunction(value)) {
10467                         
10468                         args = [element, key, value, config.scope, config];
10469                     } else {
10470                         
10471                         args = [element, key, value.fn, value.scope, value];
10472                     }
10473
10474                     if (isRemove === true) {
10475                         me.removeListener.apply(this, args);
10476                     } else {
10477                         me.addListener.apply(me, args);
10478                     }
10479                 }
10480             }
10481         }
10482     },
10483
10484     
10485     normalizeEvent: function(eventName, fn){
10486         if (/mouseenter|mouseleave/.test(eventName) && !Ext.supports.MouseEnterLeave) {
10487             if (fn) {
10488                 fn = Ext.Function.createInterceptor(fn, this.contains, this);
10489             }
10490             eventName = eventName == 'mouseenter' ? 'mouseover' : 'mouseout';
10491         } else if (eventName == 'mousewheel' && !Ext.supports.MouseWheel && !Ext.isOpera){
10492             eventName = 'DOMMouseScroll';
10493         }
10494         return {
10495             eventName: eventName,
10496             fn: fn
10497         };
10498     },
10499
10500     
10501     contains: function(event){
10502         var parent = event.browserEvent.currentTarget,
10503             child = this.getRelatedTarget(event);
10504
10505         if (parent && parent.firstChild) {
10506             while (child) {
10507                 if (child === parent) {
10508                     return false;
10509                 }
10510                 child = child.parentNode;
10511                 if (child && (child.nodeType != 1)) {
10512                     child = null;
10513                 }
10514             }
10515         }
10516         return true;
10517     },
10518
10519     
10520     addListener: function(element, eventName, fn, scope, options){
10521         
10522         if (Ext.isObject(eventName)) {
10523             this.prepareListenerConfig(element, eventName);
10524             return;
10525         }
10526
10527         var dom = Ext.getDom(element),
10528             bind,
10529             wrap;
10530
10531         if (!dom){
10532             Ext.Error.raise({
10533                 sourceClass: 'Ext.EventManager',
10534                 sourceMethod: 'addListener',
10535                 targetElement: element,
10536                 eventName: eventName,
10537                 msg: 'Error adding "' + eventName + '\" listener for nonexistent element "' + element + '"'
10538             });
10539         }
10540         if (!fn) {
10541             Ext.Error.raise({
10542                 sourceClass: 'Ext.EventManager',
10543                 sourceMethod: 'addListener',
10544                 targetElement: element,
10545                 eventName: eventName,
10546                 msg: 'Error adding "' + eventName + '\" listener. The handler function is undefined.'
10547             });
10548         }
10549
10550         
10551         options = options || {};
10552
10553         bind = this.normalizeEvent(eventName, fn);
10554         wrap = this.createListenerWrap(dom, eventName, bind.fn, scope, options);
10555
10556
10557         if (dom.attachEvent) {
10558             dom.attachEvent('on' + bind.eventName, wrap);
10559         } else {
10560             dom.addEventListener(bind.eventName, wrap, options.capture || false);
10561         }
10562
10563         if (dom == document && eventName == 'mousedown') {
10564             this.stoppedMouseDownEvent.addListener(wrap);
10565         }
10566
10567         
10568         this.getEventListenerCache(dom, eventName).push({
10569             fn: fn,
10570             wrap: wrap,
10571             scope: scope
10572         });
10573     },
10574
10575     
10576     removeListener : function(element, eventName, fn, scope) {
10577         
10578         if (Ext.isObject(eventName)) {
10579             this.prepareListenerConfig(element, eventName, true);
10580             return;
10581         }
10582
10583         var dom = Ext.getDom(element),
10584             cache = this.getEventListenerCache(dom, eventName),
10585             bindName = this.normalizeEvent(eventName).eventName,
10586             i = cache.length, j,
10587             listener, wrap, tasks;
10588
10589
10590         while (i--) {
10591             listener = cache[i];
10592
10593             if (listener && (!fn || listener.fn == fn) && (!scope || listener.scope === scope)) {
10594                 wrap = listener.wrap;
10595
10596                 
10597                 if (wrap.task) {
10598                     clearTimeout(wrap.task);
10599                     delete wrap.task;
10600                 }
10601
10602                 
10603                 j = wrap.tasks && wrap.tasks.length;
10604                 if (j) {
10605                     while (j--) {
10606                         clearTimeout(wrap.tasks[j]);
10607                     }
10608                     delete wrap.tasks;
10609                 }
10610
10611                 if (dom.detachEvent) {
10612                     dom.detachEvent('on' + bindName, wrap);
10613                 } else {
10614                     dom.removeEventListener(bindName, wrap, false);
10615                 }
10616
10617                 if (wrap && dom == document && eventName == 'mousedown') {
10618                     this.stoppedMouseDownEvent.removeListener(wrap);
10619                 }
10620
10621                 
10622                 cache.splice(i, 1);
10623             }
10624         }
10625     },
10626
10627     
10628     removeAll : function(element){
10629         var dom = Ext.getDom(element),
10630             cache, ev;
10631         if (!dom) {
10632             return;
10633         }
10634         cache = this.getElementEventCache(dom);
10635
10636         for (ev in cache) {
10637             if (cache.hasOwnProperty(ev)) {
10638                 this.removeListener(dom, ev);
10639             }
10640         }
10641         Ext.cache[dom.id].events = {};
10642     },
10643
10644     
10645     purgeElement : function(element, eventName) {
10646         var dom = Ext.getDom(element),
10647             i = 0, len;
10648
10649         if(eventName) {
10650             this.removeListener(dom, eventName);
10651         }
10652         else {
10653             this.removeAll(dom);
10654         }
10655
10656         if(dom && dom.childNodes) {
10657             for(len = element.childNodes.length; i < len; i++) {
10658                 this.purgeElement(element.childNodes[i], eventName);
10659             }
10660         }
10661     },
10662
10663     
10664     createListenerWrap : function(dom, ename, fn, scope, options) {
10665         options = !Ext.isObject(options) ? {} : options;
10666
10667         var f = ['if(!Ext) {return;}'],
10668             gen;
10669
10670         if(options.buffer || options.delay || options.freezeEvent) {
10671             f.push('e = new Ext.EventObjectImpl(e, ' + (options.freezeEvent ? 'true' : 'false' ) + ');');
10672         } else {
10673             f.push('e = Ext.EventObject.setEvent(e);');
10674         }
10675
10676         if (options.delegate) {
10677             f.push('var t = e.getTarget("' + options.delegate + '", this);');
10678             f.push('if(!t) {return;}');
10679         } else {
10680             f.push('var t = e.target;');
10681         }
10682
10683         if (options.target) {
10684             f.push('if(e.target !== options.target) {return;}');
10685         }
10686
10687         if(options.stopEvent) {
10688             f.push('e.stopEvent();');
10689         } else {
10690             if(options.preventDefault) {
10691                 f.push('e.preventDefault();');
10692             }
10693             if(options.stopPropagation) {
10694                 f.push('e.stopPropagation();');
10695             }
10696         }
10697
10698         if(options.normalized === false) {
10699             f.push('e = e.browserEvent;');
10700         }
10701
10702         if(options.buffer) {
10703             f.push('(wrap.task && clearTimeout(wrap.task));');
10704             f.push('wrap.task = setTimeout(function(){');
10705         }
10706
10707         if(options.delay) {
10708             f.push('wrap.tasks = wrap.tasks || [];');
10709             f.push('wrap.tasks.push(setTimeout(function(){');
10710         }
10711
10712         
10713         f.push('fn.call(scope || dom, e, t, options);');
10714
10715         if(options.single) {
10716             f.push('Ext.EventManager.removeListener(dom, ename, fn, scope);');
10717         }
10718
10719         if(options.delay) {
10720             f.push('}, ' + options.delay + '));');
10721         }
10722
10723         if(options.buffer) {
10724             f.push('}, ' + options.buffer + ');');
10725         }
10726
10727         gen = Ext.functionFactory('e', 'options', 'fn', 'scope', 'ename', 'dom', 'wrap', 'args', f.join('\n'));
10728
10729         return function wrap(e, args) {
10730             gen.call(dom, e, options, fn, scope, ename, dom, wrap, args);
10731         };
10732     },
10733
10734     
10735     getEventListenerCache : function(element, eventName) {
10736         var eventCache = this.getElementEventCache(element);
10737         return eventCache[eventName] || (eventCache[eventName] = []);
10738     },
10739
10740     
10741     getElementEventCache : function(element) {
10742         var elementCache = Ext.cache[this.getId(element)];
10743         return elementCache.events || (elementCache.events = {});
10744     },
10745
10746     
10747     mouseLeaveRe: /(mouseout|mouseleave)/,
10748     mouseEnterRe: /(mouseover|mouseenter)/,
10749
10750     
10751     stopEvent: function(event) {
10752         this.stopPropagation(event);
10753         this.preventDefault(event);
10754     },
10755
10756     
10757     stopPropagation: function(event) {
10758         event = event.browserEvent || event;
10759         if (event.stopPropagation) {
10760             event.stopPropagation();
10761         } else {
10762             event.cancelBubble = true;
10763         }
10764     },
10765
10766     
10767     preventDefault: function(event) {
10768         event = event.browserEvent || event;
10769         if (event.preventDefault) {
10770             event.preventDefault();
10771         } else {
10772             event.returnValue = false;
10773             
10774             try {
10775               
10776               if (event.ctrlKey || event.keyCode > 111 && event.keyCode < 124) {
10777                   event.keyCode = -1;
10778               }
10779             } catch (e) {
10780                 
10781             }
10782         }
10783     },
10784
10785     
10786     getRelatedTarget: function(event) {
10787         event = event.browserEvent || event;
10788         var target = event.relatedTarget;
10789         if (!target) {
10790             if (this.mouseLeaveRe.test(event.type)) {
10791                 target = event.toElement;
10792             } else if (this.mouseEnterRe.test(event.type)) {
10793                 target = event.fromElement;
10794             }
10795         }
10796         return this.resolveTextNode(target);
10797     },
10798
10799     
10800     getPageX: function(event) {
10801         return this.getXY(event)[0];
10802     },
10803
10804     
10805     getPageY: function(event) {
10806         return this.getXY(event)[1];
10807     },
10808
10809     
10810     getPageXY: function(event) {
10811         event = event.browserEvent || event;
10812         var x = event.pageX,
10813             y = event.pageY,
10814             doc = document.documentElement,
10815             body = document.body;
10816
10817         
10818         if (!x && x !== 0) {
10819             x = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
10820             y = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
10821         }
10822         return [x, y];
10823     },
10824
10825     
10826     getTarget: function(event) {
10827         event = event.browserEvent || event;
10828         return this.resolveTextNode(event.target || event.srcElement);
10829     },
10830
10831     
10832     
10833     resolveTextNode: Ext.isGecko ?
10834         function(node) {
10835             if (!node) {
10836                 return;
10837             }
10838             
10839             var s = HTMLElement.prototype.toString.call(node);
10840             if (s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]') {
10841                 return;
10842             }
10843                 return node.nodeType == 3 ? node.parentNode: node;
10844             }: function(node) {
10845                 return node && node.nodeType == 3 ? node.parentNode: node;
10846             },
10847
10848     
10849
10850     
10851     curWidth: 0,
10852     curHeight: 0,
10853
10854     
10855     onWindowResize: function(fn, scope, options){
10856         var resize = this.resizeEvent;
10857         if(!resize){
10858             this.resizeEvent = resize = new Ext.util.Event();
10859             this.on(window, 'resize', this.fireResize, this, {buffer: 100});
10860         }
10861         resize.addListener(fn, scope, options);
10862     },
10863
10864     
10865     fireResize: function(){
10866         var me = this,
10867             w = Ext.core.Element.getViewWidth(),
10868             h = Ext.core.Element.getViewHeight();
10869
10870          
10871          if(me.curHeight != h || me.curWidth != w){
10872              me.curHeight = h;
10873              me.curWidth = w;
10874              me.resizeEvent.fire(w, h);
10875          }
10876     },
10877
10878     
10879     removeResizeListener: function(fn, scope){
10880         if (this.resizeEvent) {
10881             this.resizeEvent.removeListener(fn, scope);
10882         }
10883     },
10884
10885     onWindowUnload: function() {
10886         var unload = this.unloadEvent;
10887         if (!unload) {
10888             this.unloadEvent = unload = new Ext.util.Event();
10889             this.addListener(window, 'unload', this.fireUnload, this);
10890         }
10891     },
10892
10893     
10894     fireUnload: function() {
10895         
10896         try {
10897             this.removeUnloadListener();
10898             
10899             if (Ext.isGecko3) {
10900                 var gridviews = Ext.ComponentQuery.query('gridview'),
10901                     i = 0,
10902                     ln = gridviews.length;
10903                 for (; i < ln; i++) {
10904                     gridviews[i].scrollToTop();
10905                 }
10906             }
10907             
10908             var el,
10909                 cache = Ext.cache;
10910             for (el in cache) {
10911                 if (cache.hasOwnProperty(el)) {
10912                     Ext.EventManager.removeAll(el);
10913                 }
10914             }
10915         } catch(e) {
10916         }
10917     },
10918
10919     
10920     removeUnloadListener: function(){
10921         if (this.unloadEvent) {
10922             this.removeListener(window, 'unload', this.fireUnload);
10923         }
10924     },
10925
10926     
10927     useKeyDown: Ext.isWebKit ?
10928                    parseInt(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1], 10) >= 525 :
10929                    !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera),
10930
10931     
10932     getKeyEvent: function(){
10933         return this.useKeyDown ? 'keydown' : 'keypress';
10934     }
10935 };
10936
10937
10938 Ext.onReady = function(fn, scope, options) {
10939     Ext.Loader.onReady(fn, scope, true, options);
10940 };
10941
10942
10943 Ext.onDocumentReady = Ext.EventManager.onDocumentReady;
10944
10945
10946 Ext.EventManager.on = Ext.EventManager.addListener;
10947
10948
10949 Ext.EventManager.un = Ext.EventManager.removeListener;
10950
10951 (function(){
10952     var initExtCss = function() {
10953         
10954         var bd = document.body || document.getElementsByTagName('body')[0],
10955             baseCSSPrefix = Ext.baseCSSPrefix,
10956             cls = [],
10957             htmlCls = [],
10958             html;
10959
10960         if (!bd) {
10961             return false;
10962         }
10963
10964         html = bd.parentNode;
10965
10966         
10967         if (Ext.isIE) {
10968             cls.push(baseCSSPrefix + 'ie');
10969         }
10970         if (Ext.isIE6) {
10971             cls.push(baseCSSPrefix + 'ie6');
10972         }
10973         if (Ext.isIE7) {
10974             cls.push(baseCSSPrefix + 'ie7');
10975         }
10976         if (Ext.isIE8) {
10977             cls.push(baseCSSPrefix + 'ie8');
10978         }
10979         if (Ext.isIE9) {
10980             cls.push(baseCSSPrefix + 'ie9');
10981         }
10982         if (Ext.isGecko) {
10983             cls.push(baseCSSPrefix + 'gecko');
10984         }
10985         if (Ext.isGecko3) {
10986             cls.push(baseCSSPrefix + 'gecko3');
10987         }
10988         if (Ext.isGecko4) {
10989             cls.push(baseCSSPrefix + 'gecko4');
10990         }
10991         if (Ext.isOpera) {
10992             cls.push(baseCSSPrefix + 'opera');
10993         }
10994         if (Ext.isWebKit) {
10995             cls.push(baseCSSPrefix + 'webkit');
10996         }
10997         if (Ext.isSafari) {
10998             cls.push(baseCSSPrefix + 'safari');
10999         }
11000         if (Ext.isSafari2) {
11001             cls.push(baseCSSPrefix + 'safari2');
11002         }
11003         if (Ext.isSafari3) {
11004             cls.push(baseCSSPrefix + 'safari3');
11005         }
11006         if (Ext.isSafari4) {
11007             cls.push(baseCSSPrefix + 'safari4');
11008         }
11009         if (Ext.isChrome) {
11010             cls.push(baseCSSPrefix + 'chrome');
11011         }
11012         if (Ext.isMac) {
11013             cls.push(baseCSSPrefix + 'mac');
11014         }
11015         if (Ext.isLinux) {
11016             cls.push(baseCSSPrefix + 'linux');
11017         }
11018         if (!Ext.supports.CSS3BorderRadius) {
11019             cls.push(baseCSSPrefix + 'nbr');
11020         }
11021         if (!Ext.supports.CSS3LinearGradient) {
11022             cls.push(baseCSSPrefix + 'nlg');
11023         }
11024         if (!Ext.scopeResetCSS) {
11025             cls.push(baseCSSPrefix + 'reset');
11026         }
11027
11028         
11029         if (html) {
11030             if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
11031                 Ext.isBorderBox = false;
11032             }
11033             else {
11034                 Ext.isBorderBox = true;
11035             }
11036
11037             htmlCls.push(baseCSSPrefix + (Ext.isBorderBox ? 'border-box' : 'strict'));
11038             if (!Ext.isStrict) {
11039                 htmlCls.push(baseCSSPrefix + 'quirks');
11040                 if (Ext.isIE && !Ext.isStrict) {
11041                     Ext.isIEQuirks = true;
11042                 }
11043             }
11044             Ext.fly(html, '_internal').addCls(htmlCls);
11045         }
11046
11047         Ext.fly(bd, '_internal').addCls(cls);
11048         return true;
11049     };
11050
11051     Ext.onReady(initExtCss);
11052 })();
11053
11054
11055 Ext.define('Ext.EventObjectImpl', {
11056     uses: ['Ext.util.Point'],
11057
11058     
11059     BACKSPACE: 8,
11060     
11061     TAB: 9,
11062     
11063     NUM_CENTER: 12,
11064     
11065     ENTER: 13,
11066     
11067     RETURN: 13,
11068     
11069     SHIFT: 16,
11070     
11071     CTRL: 17,
11072     
11073     ALT: 18,
11074     
11075     PAUSE: 19,
11076     
11077     CAPS_LOCK: 20,
11078     
11079     ESC: 27,
11080     
11081     SPACE: 32,
11082     
11083     PAGE_UP: 33,
11084     
11085     PAGE_DOWN: 34,
11086     
11087     END: 35,
11088     
11089     HOME: 36,
11090     
11091     LEFT: 37,
11092     
11093     UP: 38,
11094     
11095     RIGHT: 39,
11096     
11097     DOWN: 40,
11098     
11099     PRINT_SCREEN: 44,
11100     
11101     INSERT: 45,
11102     
11103     DELETE: 46,
11104     
11105     ZERO: 48,
11106     
11107     ONE: 49,
11108     
11109     TWO: 50,
11110     
11111     THREE: 51,
11112     
11113     FOUR: 52,
11114     
11115     FIVE: 53,
11116     
11117     SIX: 54,
11118     
11119     SEVEN: 55,
11120     
11121     EIGHT: 56,
11122     
11123     NINE: 57,
11124     
11125     A: 65,
11126     
11127     B: 66,
11128     
11129     C: 67,
11130     
11131     D: 68,
11132     
11133     E: 69,
11134     
11135     F: 70,
11136     
11137     G: 71,
11138     
11139     H: 72,
11140     
11141     I: 73,
11142     
11143     J: 74,
11144     
11145     K: 75,
11146     
11147     L: 76,
11148     
11149     M: 77,
11150     
11151     N: 78,
11152     
11153     O: 79,
11154     
11155     P: 80,
11156     
11157     Q: 81,
11158     
11159     R: 82,
11160     
11161     S: 83,
11162     
11163     T: 84,
11164     
11165     U: 85,
11166     
11167     V: 86,
11168     
11169     W: 87,
11170     
11171     X: 88,
11172     
11173     Y: 89,
11174     
11175     Z: 90,
11176     
11177     CONTEXT_MENU: 93,
11178     
11179     NUM_ZERO: 96,
11180     
11181     NUM_ONE: 97,
11182     
11183     NUM_TWO: 98,
11184     
11185     NUM_THREE: 99,
11186     
11187     NUM_FOUR: 100,
11188     
11189     NUM_FIVE: 101,
11190     
11191     NUM_SIX: 102,
11192     
11193     NUM_SEVEN: 103,
11194     
11195     NUM_EIGHT: 104,
11196     
11197     NUM_NINE: 105,
11198     
11199     NUM_MULTIPLY: 106,
11200     
11201     NUM_PLUS: 107,
11202     
11203     NUM_MINUS: 109,
11204     
11205     NUM_PERIOD: 110,
11206     
11207     NUM_DIVISION: 111,
11208     
11209     F1: 112,
11210     
11211     F2: 113,
11212     
11213     F3: 114,
11214     
11215     F4: 115,
11216     
11217     F5: 116,
11218     
11219     F6: 117,
11220     
11221     F7: 118,
11222     
11223     F8: 119,
11224     
11225     F9: 120,
11226     
11227     F10: 121,
11228     
11229     F11: 122,
11230     
11231     F12: 123,
11232
11233     
11234     clickRe: /(dbl)?click/,
11235     
11236     safariKeys: {
11237         3: 13, 
11238         63234: 37, 
11239         63235: 39, 
11240         63232: 38, 
11241         63233: 40, 
11242         63276: 33, 
11243         63277: 34, 
11244         63272: 46, 
11245         63273: 36, 
11246         63275: 35 
11247     },
11248     
11249     btnMap: Ext.isIE ? {
11250         1: 0,
11251         4: 1,
11252         2: 2
11253     } : {
11254         0: 0,
11255         1: 1,
11256         2: 2
11257     },
11258
11259     constructor: function(event, freezeEvent){
11260         if (event) {
11261             this.setEvent(event.browserEvent || event, freezeEvent);
11262         }
11263     },
11264
11265     setEvent: function(event, freezeEvent){
11266         var me = this, button, options;
11267
11268         if (event == me || (event && event.browserEvent)) { 
11269             return event;
11270         }
11271         me.browserEvent = event;
11272         if (event) {
11273             
11274             button = event.button ? me.btnMap[event.button] : (event.which ? event.which - 1 : -1);
11275             if (me.clickRe.test(event.type) && button == -1) {
11276                 button = 0;
11277             }
11278             options = {
11279                 type: event.type,
11280                 button: button,
11281                 shiftKey: event.shiftKey,
11282                 
11283                 ctrlKey: event.ctrlKey || event.metaKey || false,
11284                 altKey: event.altKey,
11285                 
11286                 keyCode: event.keyCode,
11287                 charCode: event.charCode,
11288                 
11289                 target: Ext.EventManager.getTarget(event),
11290                 relatedTarget: Ext.EventManager.getRelatedTarget(event),
11291                 currentTarget: event.currentTarget,
11292                 xy: (freezeEvent ? me.getXY() : null)
11293             };
11294         } else {
11295             options = {
11296                 button: -1,
11297                 shiftKey: false,
11298                 ctrlKey: false,
11299                 altKey: false,
11300                 keyCode: 0,
11301                 charCode: 0,
11302                 target: null,
11303                 xy: [0, 0]
11304             };
11305         }
11306         Ext.apply(me, options);
11307         return me;
11308     },
11309
11310     
11311     stopEvent: function(){
11312         this.stopPropagation();
11313         this.preventDefault();
11314     },
11315
11316     
11317     preventDefault: function(){
11318         if (this.browserEvent) {
11319             Ext.EventManager.preventDefault(this.browserEvent);
11320         }
11321     },
11322
11323     
11324     stopPropagation: function(){
11325         var browserEvent = this.browserEvent;
11326
11327         if (browserEvent) {
11328             if (browserEvent.type == 'mousedown') {
11329                 Ext.EventManager.stoppedMouseDownEvent.fire(this);
11330             }
11331             Ext.EventManager.stopPropagation(browserEvent);
11332         }
11333     },
11334
11335     
11336     getCharCode: function(){
11337         return this.charCode || this.keyCode;
11338     },
11339
11340     
11341     getKey: function(){
11342         return this.normalizeKey(this.keyCode || this.charCode);
11343     },
11344
11345     
11346     normalizeKey: function(key){
11347         
11348         return Ext.isWebKit ? (this.safariKeys[key] || key) : key;
11349     },
11350
11351     
11352     getPageX: function(){
11353         return this.getX();
11354     },
11355
11356     
11357     getPageY: function(){
11358         return this.getY();
11359     },
11360     
11361     
11362     getX: function() {
11363         return this.getXY()[0];
11364     },    
11365     
11366     
11367     getY: function() {
11368         return this.getXY()[1];
11369     },
11370         
11371     
11372     getXY: function() {
11373         if (!this.xy) {
11374             
11375             this.xy = Ext.EventManager.getPageXY(this.browserEvent);
11376         }
11377         return this.xy;
11378     },
11379
11380     
11381     getTarget : function(selector, maxDepth, returnEl){
11382         if (selector) {
11383             return Ext.fly(this.target).findParent(selector, maxDepth, returnEl);
11384         }
11385         return returnEl ? Ext.get(this.target) : this.target;
11386     },
11387
11388     
11389     getRelatedTarget : function(selector, maxDepth, returnEl){
11390         if (selector) {
11391             return Ext.fly(this.relatedTarget).findParent(selector, maxDepth, returnEl);
11392         }
11393         return returnEl ? Ext.get(this.relatedTarget) : this.relatedTarget;
11394     },
11395
11396     
11397     getWheelDelta : function(){
11398         var event = this.browserEvent,
11399             delta = 0;
11400
11401         if (event.wheelDelta) { 
11402             delta = event.wheelDelta / 120;
11403         } else if (event.detail){ 
11404             delta = -event.detail / 3;
11405         }
11406         return delta;
11407     },
11408
11409     
11410     within : function(el, related, allowEl){
11411         if(el){
11412             var t = related ? this.getRelatedTarget() : this.getTarget(),
11413                 result;
11414
11415             if (t) {
11416                 result = Ext.fly(el).contains(t);
11417                 if (!result && allowEl) {
11418                     result = t == Ext.getDom(el);
11419                 }
11420                 return result;
11421             }
11422         }
11423         return false;
11424     },
11425
11426     
11427     isNavKeyPress : function(){
11428         var me = this,
11429             k = this.normalizeKey(me.keyCode);
11430
11431        return (k >= 33 && k <= 40) ||  
11432        k == me.RETURN ||
11433        k == me.TAB ||
11434        k == me.ESC;
11435     },
11436
11437     
11438     isSpecialKey : function(){
11439         var k = this.normalizeKey(this.keyCode);
11440         return (this.type == 'keypress' && this.ctrlKey) ||
11441         this.isNavKeyPress() ||
11442         (k == this.BACKSPACE) || 
11443         (k >= 16 && k <= 20) || 
11444         (k >= 44 && k <= 46);   
11445     },
11446
11447     
11448     getPoint : function(){
11449         var xy = this.getXY();
11450         return Ext.create('Ext.util.Point', xy[0], xy[1]);
11451     },
11452
11453    
11454     hasModifier : function(){
11455         return this.ctrlKey || this.altKey || this.shiftKey || this.metaKey;
11456     },
11457
11458     
11459     injectEvent: function () {
11460         var API,
11461             dispatchers = {}; 
11462
11463         
11464
11465         
11466         
11467
11468         if (!Ext.isIE && document.createEvent) { 
11469             API = {
11470                 createHtmlEvent: function (doc, type, bubbles, cancelable) {
11471                     var event = doc.createEvent('HTMLEvents');
11472
11473                     event.initEvent(type, bubbles, cancelable);
11474                     return event;
11475                 },
11476
11477                 createMouseEvent: function (doc, type, bubbles, cancelable, detail,
11478                                             clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
11479                                             button, relatedTarget) {
11480                     var event = doc.createEvent('MouseEvents'),
11481                         view = doc.defaultView || window;
11482
11483                     if (event.initMouseEvent) {
11484                         event.initMouseEvent(type, bubbles, cancelable, view, detail,
11485                                     clientX, clientY, clientX, clientY, ctrlKey, altKey,
11486                                     shiftKey, metaKey, button, relatedTarget);
11487                     } else { 
11488                         event = doc.createEvent('UIEvents');
11489                         event.initEvent(type, bubbles, cancelable);
11490                         event.view = view;
11491                         event.detail = detail;
11492                         event.screenX = clientX;
11493                         event.screenY = clientY;
11494                         event.clientX = clientX;
11495                         event.clientY = clientY;
11496                         event.ctrlKey = ctrlKey;
11497                         event.altKey = altKey;
11498                         event.metaKey = metaKey;
11499                         event.shiftKey = shiftKey;
11500                         event.button = button;
11501                         event.relatedTarget = relatedTarget;
11502                     }
11503
11504                     return event;
11505                 },
11506
11507                 createUIEvent: function (doc, type, bubbles, cancelable, detail) {
11508                     var event = doc.createEvent('UIEvents'),
11509                         view = doc.defaultView || window;
11510
11511                     event.initUIEvent(type, bubbles, cancelable, view, detail);
11512                     return event;
11513                 },
11514
11515                 fireEvent: function (target, type, event) {
11516                     target.dispatchEvent(event);
11517                 },
11518
11519                 fixTarget: function (target) {
11520                     
11521                     if (target == window && !target.dispatchEvent) {
11522                         return document;
11523                     }
11524
11525                     return target;
11526                 }
11527             }
11528         } else if (document.createEventObject) { 
11529             var crazyIEButtons = { 0: 1, 1: 4, 2: 2 };
11530
11531             API = {
11532                 createHtmlEvent: function (doc, type, bubbles, cancelable) {
11533                     var event = doc.createEventObject();
11534                     event.bubbles = bubbles;
11535                     event.cancelable = cancelable;
11536                     return event;
11537                 },
11538
11539                 createMouseEvent: function (doc, type, bubbles, cancelable, detail,
11540                                             clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
11541                                             button, relatedTarget) {
11542                     var event = doc.createEventObject();
11543                     event.bubbles = bubbles;
11544                     event.cancelable = cancelable;
11545                     event.detail = detail;
11546                     event.screenX = clientX;
11547                     event.screenY = clientY;
11548                     event.clientX = clientX;
11549                     event.clientY = clientY;
11550                     event.ctrlKey = ctrlKey;
11551                     event.altKey = altKey;
11552                     event.shiftKey = shiftKey;
11553                     event.metaKey = metaKey;
11554                     event.button = crazyIEButtons[button] || button;
11555                     event.relatedTarget = relatedTarget; 
11556                     return event;
11557                 },
11558
11559                 createUIEvent: function (doc, type, bubbles, cancelable, detail) {
11560                     var event = doc.createEventObject();
11561                     event.bubbles = bubbles;
11562                     event.cancelable = cancelable;
11563                     return event;
11564                 },
11565
11566                 fireEvent: function (target, type, event) {
11567                     target.fireEvent('on' + type, event);
11568                 },
11569
11570                 fixTarget: function (target) {
11571                     if (target == document) {
11572                         
11573                         
11574                         return document.documentElement;
11575                     }
11576
11577                     return target;
11578                 }
11579             };
11580         }
11581
11582         
11583         
11584
11585         Ext.Object.each({
11586                 load:   [false, false],
11587                 unload: [false, false],
11588                 select: [true, false],
11589                 change: [true, false],
11590                 submit: [true, true],
11591                 reset:  [true, false],
11592                 resize: [true, false],
11593                 scroll: [true, false]
11594             },
11595             function (name, value) {
11596                 var bubbles = value[0], cancelable = value[1];
11597                 dispatchers[name] = function (targetEl, srcEvent) {
11598                     var e = API.createHtmlEvent(name, bubbles, cancelable);
11599                     API.fireEvent(targetEl, name, e);
11600                 };
11601             });
11602
11603         
11604         
11605
11606         function createMouseEventDispatcher (type, detail) {
11607             var cancelable = (type != 'mousemove');
11608             return function (targetEl, srcEvent) {
11609                 var xy = srcEvent.getXY(),
11610                     e = API.createMouseEvent(targetEl.ownerDocument, type, true, cancelable,
11611                                 detail, xy[0], xy[1], srcEvent.ctrlKey, srcEvent.altKey,
11612                                 srcEvent.shiftKey, srcEvent.metaKey, srcEvent.button,
11613                                 srcEvent.relatedTarget);
11614                 API.fireEvent(targetEl, type, e);
11615             };
11616         }
11617
11618         Ext.each(['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mousemove', 'mouseout'],
11619             function (eventName) {
11620                 dispatchers[eventName] = createMouseEventDispatcher(eventName, 1);
11621             });
11622
11623         
11624         
11625
11626         Ext.Object.each({
11627                 focusin:  [true, false],
11628                 focusout: [true, false],
11629                 activate: [true, true],
11630                 focus:    [false, false],
11631                 blur:     [false, false]
11632             },
11633             function (name, value) {
11634                 var bubbles = value[0], cancelable = value[1];
11635                 dispatchers[name] = function (targetEl, srcEvent) {
11636                     var e = API.createUIEvent(targetEl.ownerDocument, name, bubbles, cancelable, 1);
11637                     API.fireEvent(targetEl, name, e);
11638                 };
11639             });
11640
11641         
11642         if (!API) {
11643             
11644
11645             dispatchers = {}; 
11646
11647             API = {
11648                 fixTarget: function (t) {
11649                     return t;
11650                 }
11651             };
11652         }
11653
11654         function cannotInject (target, srcEvent) {
11655             
11656         }
11657
11658         return function (target) {
11659             var me = this,
11660                 dispatcher = dispatchers[me.type] || cannotInject,
11661                 t = target ? (target.dom || target) : me.getTarget();
11662
11663             t = API.fixTarget(t);
11664             dispatcher(t, me);
11665         };
11666     }() 
11667
11668 }, function() {
11669
11670 Ext.EventObject = new Ext.EventObjectImpl();
11671
11672 });
11673
11674
11675
11676 (function(){
11677     var doc = document,
11678         isCSS1 = doc.compatMode == "CSS1Compat",
11679         ELEMENT = Ext.core.Element,
11680         fly = function(el){
11681             if (!_fly) {
11682                 _fly = new Ext.core.Element.Flyweight();
11683             }
11684             _fly.dom = el;
11685             return _fly;
11686         }, _fly;
11687
11688     Ext.apply(ELEMENT, {
11689         isAncestor : function(p, c) {
11690             var ret = false;
11691
11692             p = Ext.getDom(p);
11693             c = Ext.getDom(c);
11694             if (p && c) {
11695                 if (p.contains) {
11696                     return p.contains(c);
11697                 } else if (p.compareDocumentPosition) {
11698                     return !!(p.compareDocumentPosition(c) & 16);
11699                 } else {
11700                     while ((c = c.parentNode)) {
11701                         ret = c == p || ret;
11702                     }
11703                 }
11704             }
11705             return ret;
11706         },
11707
11708         getViewWidth : function(full) {
11709             return full ? ELEMENT.getDocumentWidth() : ELEMENT.getViewportWidth();
11710         },
11711
11712         getViewHeight : function(full) {
11713             return full ? ELEMENT.getDocumentHeight() : ELEMENT.getViewportHeight();
11714         },
11715
11716         getDocumentHeight: function() {
11717             return Math.max(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, ELEMENT.getViewportHeight());
11718         },
11719
11720         getDocumentWidth: function() {
11721             return Math.max(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, ELEMENT.getViewportWidth());
11722         },
11723
11724         getViewportHeight: function(){
11725             return Ext.isIE ?
11726                    (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :
11727                    self.innerHeight;
11728         },
11729
11730         getViewportWidth : function() {
11731             return (!Ext.isStrict && !Ext.isOpera) ? doc.body.clientWidth :
11732                    Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;
11733         },
11734
11735         getY : function(el) {
11736             return ELEMENT.getXY(el)[1];
11737         },
11738
11739         getX : function(el) {
11740             return ELEMENT.getXY(el)[0];
11741         },
11742
11743         getXY : function(el) {
11744             var p,
11745                 pe,
11746                 b,
11747                 bt,
11748                 bl,
11749                 dbd,
11750                 x = 0,
11751                 y = 0,
11752                 scroll,
11753                 hasAbsolute,
11754                 bd = (doc.body || doc.documentElement),
11755                 ret = [0,0];
11756
11757             el = Ext.getDom(el);
11758
11759             if(el != bd){
11760                 hasAbsolute = fly(el).isStyle("position", "absolute");
11761
11762                 if (el.getBoundingClientRect) {
11763                     b = el.getBoundingClientRect();
11764                     scroll = fly(document).getScroll();
11765                     ret = [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
11766                 } else {
11767                     p = el;
11768
11769                     while (p) {
11770                         pe = fly(p);
11771                         x += p.offsetLeft;
11772                         y += p.offsetTop;
11773
11774                         hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");
11775
11776                         if (Ext.isGecko) {
11777                             y += bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
11778                             x += bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
11779
11780                             if (p != el && !pe.isStyle('overflow','visible')) {
11781                                 x += bl;
11782                                 y += bt;
11783                             }
11784                         }
11785                         p = p.offsetParent;
11786                     }
11787
11788                     if (Ext.isSafari && hasAbsolute) {
11789                         x -= bd.offsetLeft;
11790                         y -= bd.offsetTop;
11791                     }
11792
11793                     if (Ext.isGecko && !hasAbsolute) {
11794                         dbd = fly(bd);
11795                         x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
11796                         y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
11797                     }
11798
11799                     p = el.parentNode;
11800                     while (p && p != bd) {
11801                         if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {
11802                             x -= p.scrollLeft;
11803                             y -= p.scrollTop;
11804                         }
11805                         p = p.parentNode;
11806                     }
11807                     ret = [x,y];
11808                 }
11809             }
11810             return ret;
11811         },
11812
11813         setXY : function(el, xy) {
11814             (el = Ext.fly(el, '_setXY')).position();
11815
11816             var pts = el.translatePoints(xy),
11817                 style = el.dom.style,
11818                 pos;
11819
11820             for (pos in pts) {
11821                 if (!isNaN(pts[pos])) {
11822                     style[pos] = pts[pos] + "px";
11823                 }
11824             }
11825         },
11826
11827         setX : function(el, x) {
11828             ELEMENT.setXY(el, [x, false]);
11829         },
11830
11831         setY : function(el, y) {
11832             ELEMENT.setXY(el, [false, y]);
11833         },
11834
11835         
11836         serializeForm: function(form) {
11837             var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements,
11838                 hasSubmit = false,
11839                 encoder = encodeURIComponent,
11840                 name,
11841                 data = '',
11842                 type,
11843                 hasValue;
11844
11845             Ext.each(fElements, function(element){
11846                 name = element.name;
11847                 type = element.type;
11848
11849                 if (!element.disabled && name) {
11850                     if (/select-(one|multiple)/i.test(type)) {
11851                         Ext.each(element.options, function(opt){
11852                             if (opt.selected) {
11853                                 hasValue = opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttributeNode('value').specified;
11854                                 data += String.format("{0}={1}&", encoder(name), encoder(hasValue ? opt.value : opt.text));
11855                             }
11856                         });
11857                     } else if (!(/file|undefined|reset|button/i.test(type))) {
11858                         if (!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)) {
11859                             data += encoder(name) + '=' + encoder(element.value) + '&';
11860                             hasSubmit = /submit/i.test(type);
11861                         }
11862                     }
11863                 }
11864             });
11865             return data.substr(0, data.length - 1);
11866         }
11867     });
11868 })();
11869
11870
11871
11872 Ext.core.Element.addMethods({
11873
11874     
11875     monitorMouseLeave: function(delay, handler, scope) {
11876         var me = this,
11877             timer,
11878             listeners = {
11879                 mouseleave: function(e) {
11880                     timer = setTimeout(Ext.Function.bind(handler, scope||me, [e]), delay);
11881                 },
11882                 mouseenter: function() {
11883                     clearTimeout(timer);
11884                 },
11885                 freezeEvent: true
11886             };
11887
11888         me.on(listeners);
11889         return listeners;
11890     },
11891
11892     
11893     swallowEvent : function(eventName, preventDefault) {
11894         var me = this;
11895         function fn(e) {
11896             e.stopPropagation();
11897             if (preventDefault) {
11898                 e.preventDefault();
11899             }
11900         }
11901         
11902         if (Ext.isArray(eventName)) {
11903             Ext.each(eventName, function(e) {
11904                  me.on(e, fn);
11905             });
11906             return me;
11907         }
11908         me.on(eventName, fn);
11909         return me;
11910     },
11911
11912     
11913     relayEvent : function(eventName, observable) {
11914         this.on(eventName, function(e) {
11915             observable.fireEvent(eventName, e);
11916         });
11917     },
11918
11919     
11920     clean : function(forceReclean) {
11921         var me  = this,
11922             dom = me.dom,
11923             n   = dom.firstChild,
11924             nx,
11925             ni  = -1;
11926
11927         if (Ext.core.Element.data(dom, 'isCleaned') && forceReclean !== true) {
11928             return me;
11929         }
11930
11931         while (n) {
11932             nx = n.nextSibling;
11933             if (n.nodeType == 3) {
11934                 
11935                 if (!(/\S/.test(n.nodeValue))) {
11936                     dom.removeChild(n);
11937                 
11938                 } else if (nx && nx.nodeType == 3) {
11939                     n.appendData(Ext.String.trim(nx.data));
11940                     dom.removeChild(nx);
11941                     nx = n.nextSibling;
11942                     n.nodeIndex = ++ni;
11943                 }
11944             } else {
11945                 
11946                 Ext.fly(n).clean();
11947                 n.nodeIndex = ++ni;
11948             }
11949             n = nx;
11950         }
11951
11952         Ext.core.Element.data(dom, 'isCleaned', true);
11953         return me;
11954     },
11955
11956     
11957     load : function(options) {
11958         this.getLoader().load(options);
11959         return this;
11960     },
11961
11962     
11963     getLoader : function() {
11964         var dom = this.dom,
11965             data = Ext.core.Element.data,
11966             loader = data(dom, 'loader');
11967             
11968         if (!loader) {
11969             loader = Ext.create('Ext.ElementLoader', {
11970                 target: this
11971             });
11972             data(dom, 'loader', loader);
11973         }
11974         return loader;
11975     },
11976
11977     
11978     update : function(html, loadScripts, callback) {
11979         var me = this,
11980             id,
11981             dom,
11982             interval;
11983             
11984         if (!me.dom) {
11985             return me;
11986         }
11987         html = html || '';
11988         dom = me.dom;
11989
11990         if (loadScripts !== true) {
11991             dom.innerHTML = html;
11992             Ext.callback(callback, me);
11993             return me;
11994         }
11995
11996         id  = Ext.id();
11997         html += '<span id="' + id + '"></span>';
11998
11999         interval = setInterval(function(){
12000             if (!document.getElementById(id)) {
12001                 return false;    
12002             }
12003             clearInterval(interval);
12004             var DOC    = document,
12005                 hd     = DOC.getElementsByTagName("head")[0],
12006                 re     = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
12007                 srcRe  = /\ssrc=([\'\"])(.*?)\1/i,
12008                 typeRe = /\stype=([\'\"])(.*?)\1/i,
12009                 match,
12010                 attrs,
12011                 srcMatch,
12012                 typeMatch,
12013                 el,
12014                 s;
12015
12016             while ((match = re.exec(html))) {
12017                 attrs = match[1];
12018                 srcMatch = attrs ? attrs.match(srcRe) : false;
12019                 if (srcMatch && srcMatch[2]) {
12020                    s = DOC.createElement("script");
12021                    s.src = srcMatch[2];
12022                    typeMatch = attrs.match(typeRe);
12023                    if (typeMatch && typeMatch[2]) {
12024                        s.type = typeMatch[2];
12025                    }
12026                    hd.appendChild(s);
12027                 } else if (match[2] && match[2].length > 0) {
12028                     if (window.execScript) {
12029                        window.execScript(match[2]);
12030                     } else {
12031                        window.eval(match[2]);
12032                     }
12033                 }
12034             }
12035             
12036             el = DOC.getElementById(id);
12037             if (el) {
12038                 Ext.removeNode(el);
12039             }
12040             Ext.callback(callback, me);
12041         }, 20);
12042         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, '');
12043         return me;
12044     },
12045
12046     
12047     removeAllListeners : function() {
12048         this.removeAnchor();
12049         Ext.EventManager.removeAll(this.dom);
12050         return this;
12051     },
12052
12053     
12054     createProxy : function(config, renderTo, matchBox) {
12055         config = (typeof config == 'object') ? config : {tag : "div", cls: config};
12056
12057         var me = this,
12058             proxy = renderTo ? Ext.core.DomHelper.append(renderTo, config, true) :
12059                                Ext.core.DomHelper.insertBefore(me.dom, config, true);
12060
12061         proxy.setVisibilityMode(Ext.core.Element.DISPLAY);
12062         proxy.hide();
12063         if (matchBox && me.setBox && me.getBox) { 
12064            proxy.setBox(me.getBox());
12065         }
12066         return proxy;
12067     }
12068 });
12069 Ext.core.Element.prototype.clearListeners = Ext.core.Element.prototype.removeAllListeners;
12070
12071
12072 Ext.core.Element.addMethods({
12073     
12074     getAnchorXY : function(anchor, local, s){
12075         
12076         
12077         anchor = (anchor || "tl").toLowerCase();
12078         s = s || {};
12079
12080         var me = this,
12081             vp = me.dom == document.body || me.dom == document,
12082             w = s.width || vp ? Ext.core.Element.getViewWidth() : me.getWidth(),
12083             h = s.height || vp ? Ext.core.Element.getViewHeight() : me.getHeight(),
12084             xy,
12085             r = Math.round,
12086             o = me.getXY(),
12087             scroll = me.getScroll(),
12088             extraX = vp ? scroll.left : !local ? o[0] : 0,
12089             extraY = vp ? scroll.top : !local ? o[1] : 0,
12090             hash = {
12091                 c  : [r(w * 0.5), r(h * 0.5)],
12092                 t  : [r(w * 0.5), 0],
12093                 l  : [0, r(h * 0.5)],
12094                 r  : [w, r(h * 0.5)],
12095                 b  : [r(w * 0.5), h],
12096                 tl : [0, 0],
12097                 bl : [0, h],
12098                 br : [w, h],
12099                 tr : [w, 0]
12100             };
12101
12102         xy = hash[anchor];
12103         return [xy[0] + extraX, xy[1] + extraY];
12104     },
12105
12106     
12107     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
12108         var me = this,
12109             dom = me.dom,
12110             scroll = !Ext.isEmpty(monitorScroll),
12111             action = function(){
12112                 Ext.fly(dom).alignTo(el, alignment, offsets, animate);
12113                 Ext.callback(callback, Ext.fly(dom));
12114             },
12115             anchor = this.getAnchor();
12116
12117         
12118         this.removeAnchor();
12119         Ext.apply(anchor, {
12120             fn: action,
12121             scroll: scroll
12122         });
12123
12124         Ext.EventManager.onWindowResize(action, null);
12125
12126         if(scroll){
12127             Ext.EventManager.on(window, 'scroll', action, null,
12128                 {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
12129         }
12130         action.call(me); 
12131         return me;
12132     },
12133
12134     
12135     removeAnchor : function(){
12136         var me = this,
12137             anchor = this.getAnchor();
12138
12139         if(anchor && anchor.fn){
12140             Ext.EventManager.removeResizeListener(anchor.fn);
12141             if(anchor.scroll){
12142                 Ext.EventManager.un(window, 'scroll', anchor.fn);
12143             }
12144             delete anchor.fn;
12145         }
12146         return me;
12147     },
12148
12149     
12150     getAnchor : function(){
12151         var data = Ext.core.Element.data,
12152             dom = this.dom;
12153             if (!dom) {
12154                 return;
12155             }
12156             var anchor = data(dom, '_anchor');
12157
12158         if(!anchor){
12159             anchor = data(dom, '_anchor', {});
12160         }
12161         return anchor;
12162     },
12163
12164     getAlignVector: function(el, spec, offset) {
12165         var me = this,
12166             side = {t:"top", l:"left", r:"right", b: "bottom"},
12167             thisRegion = me.getRegion(),
12168             elRegion;
12169
12170         el = Ext.get(el);
12171         if(!el || !el.dom){
12172             Ext.Error.raise({
12173                 sourceClass: 'Ext.core.Element',
12174                 sourceMethod: 'getAlignVector',
12175                 msg: 'Attempted to align an element that doesn\'t exist'
12176             });
12177         }
12178
12179         elRegion = el.getRegion();
12180     },
12181
12182     
12183     getAlignToXY : function(el, p, o){
12184         el = Ext.get(el);
12185
12186         if(!el || !el.dom){
12187             Ext.Error.raise({
12188                 sourceClass: 'Ext.core.Element',
12189                 sourceMethod: 'getAlignToXY',
12190                 msg: 'Attempted to align an element that doesn\'t exist'
12191             });
12192         }
12193
12194         o = o || [0,0];
12195         p = (!p || p == "?" ? "tl-bl?" : (!(/-/).test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();
12196
12197         var me = this,
12198             d = me.dom,
12199             a1,
12200             a2,
12201             x,
12202             y,
12203             
12204             w,
12205             h,
12206             r,
12207             dw = Ext.core.Element.getViewWidth() -10, 
12208             dh = Ext.core.Element.getViewHeight()-10, 
12209             p1y,
12210             p1x,
12211             p2y,
12212             p2x,
12213             swapY,
12214             swapX,
12215             doc = document,
12216             docElement = doc.documentElement,
12217             docBody = doc.body,
12218             scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
12219             scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
12220             c = false, 
12221             p1 = "",
12222             p2 = "",
12223             m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
12224
12225         if(!m){
12226             Ext.Error.raise({
12227                 sourceClass: 'Ext.core.Element',
12228                 sourceMethod: 'getAlignToXY',
12229                 el: el,
12230                 position: p,
12231                 offset: o,
12232                 msg: 'Attemmpted to align an element with an invalid position: "' + p + '"'
12233             });
12234         }
12235
12236         p1 = m[1];
12237         p2 = m[2];
12238         c = !!m[3];
12239
12240         
12241         
12242         a1 = me.getAnchorXY(p1, true);
12243         a2 = el.getAnchorXY(p2, false);
12244
12245         x = a2[0] - a1[0] + o[0];
12246         y = a2[1] - a1[1] + o[1];
12247
12248         if(c){
12249            w = me.getWidth();
12250            h = me.getHeight();
12251            r = el.getRegion();
12252            
12253            
12254            
12255            p1y = p1.charAt(0);
12256            p1x = p1.charAt(p1.length-1);
12257            p2y = p2.charAt(0);
12258            p2x = p2.charAt(p2.length-1);
12259            swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
12260            swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
12261
12262
12263            if (x + w > dw + scrollX) {
12264                 x = swapX ? r.left-w : dw+scrollX-w;
12265            }
12266            if (x < scrollX) {
12267                x = swapX ? r.right : scrollX;
12268            }
12269            if (y + h > dh + scrollY) {
12270                 y = swapY ? r.top-h : dh+scrollY-h;
12271             }
12272            if (y < scrollY){
12273                y = swapY ? r.bottom : scrollY;
12274            }
12275         }
12276         return [x,y];
12277     },
12278
12279     
12280     alignTo : function(element, position, offsets, animate){
12281         var me = this;
12282         return me.setXY(me.getAlignToXY(element, position, offsets),
12283                         me.anim && !!animate ? me.anim(animate) : false);
12284     },
12285
12286     
12287     adjustForConstraints : function(xy, parent) {
12288         var vector = this.getConstrainVector(parent, xy);
12289         if (vector) {
12290             xy[0] += vector[0];
12291             xy[1] += vector[1];
12292         }
12293         return xy;
12294     },
12295
12296     
12297     getConstrainVector: function(constrainTo, proposedPosition) {
12298         if (!(constrainTo instanceof Ext.util.Region)) {
12299             constrainTo = Ext.get(constrainTo).getViewRegion();
12300         }
12301         var thisRegion = this.getRegion(),
12302             vector = [0, 0],
12303             shadowSize = this.shadow && this.shadow.offset,
12304             overflowed = false;
12305
12306         
12307         if (proposedPosition) {
12308             thisRegion.translateBy(proposedPosition[0] - thisRegion.x, proposedPosition[1] - thisRegion.y);
12309         }
12310
12311         
12312         
12313         if (shadowSize) {
12314             constrainTo.adjust(0, -shadowSize, -shadowSize, shadowSize);
12315         }
12316
12317         
12318         if (thisRegion.right > constrainTo.right) {
12319             overflowed = true;
12320             vector[0] = (constrainTo.right - thisRegion.right);    
12321         }
12322         if (thisRegion.left + vector[0] < constrainTo.left) {
12323             overflowed = true;
12324             vector[0] = (constrainTo.left - thisRegion.left);      
12325         }
12326
12327         
12328         if (thisRegion.bottom > constrainTo.bottom) {
12329             overflowed = true;
12330             vector[1] = (constrainTo.bottom - thisRegion.bottom);  
12331         }
12332         if (thisRegion.top + vector[1] < constrainTo.top) {
12333             overflowed = true;
12334             vector[1] = (constrainTo.top - thisRegion.top);        
12335         }
12336         return overflowed ? vector : false;
12337     },
12338
12339     
12340     getCenterXY : function(){
12341         return this.getAlignToXY(document, 'c-c');
12342     },
12343
12344     
12345     center : function(centerIn){
12346         return this.alignTo(centerIn || document, 'c-c');
12347     }
12348 });
12349
12350
12351 (function(){
12352
12353 var ELEMENT = Ext.core.Element,
12354     LEFT = "left",
12355     RIGHT = "right",
12356     TOP = "top",
12357     BOTTOM = "bottom",
12358     POSITION = "position",
12359     STATIC = "static",
12360     RELATIVE = "relative",
12361     AUTO = "auto",
12362     ZINDEX = "z-index";
12363
12364 Ext.override(Ext.core.Element, {
12365     
12366     getX : function(){
12367         return ELEMENT.getX(this.dom);
12368     },
12369
12370     
12371     getY : function(){
12372         return ELEMENT.getY(this.dom);
12373     },
12374
12375     
12376     getXY : function(){
12377         return ELEMENT.getXY(this.dom);
12378     },
12379
12380     
12381     getOffsetsTo : function(el){
12382         var o = this.getXY(),
12383             e = Ext.fly(el, '_internal').getXY();
12384         return [o[0]-e[0],o[1]-e[1]];
12385     },
12386
12387     
12388     setX : function(x, animate){
12389         return this.setXY([x, this.getY()], animate);
12390     },
12391
12392     
12393     setY : function(y, animate){
12394         return this.setXY([this.getX(), y], animate);
12395     },
12396
12397     
12398     setLeft : function(left){
12399         this.setStyle(LEFT, this.addUnits(left));
12400         return this;
12401     },
12402
12403     
12404     setTop : function(top){
12405         this.setStyle(TOP, this.addUnits(top));
12406         return this;
12407     },
12408
12409     
12410     setRight : function(right){
12411         this.setStyle(RIGHT, this.addUnits(right));
12412         return this;
12413     },
12414
12415     
12416     setBottom : function(bottom){
12417         this.setStyle(BOTTOM, this.addUnits(bottom));
12418         return this;
12419     },
12420
12421     
12422     setXY: function(pos, animate) {
12423         var me = this;
12424         if (!animate || !me.anim) {
12425             ELEMENT.setXY(me.dom, pos);
12426         }
12427         else {
12428             if (!Ext.isObject(animate)) {
12429                 animate = {};
12430             }
12431             me.animate(Ext.applyIf({ to: { x: pos[0], y: pos[1] } }, animate));
12432         }
12433         return me;
12434     },
12435
12436     
12437     setLocation : function(x, y, animate){
12438         return this.setXY([x, y], animate);
12439     },
12440
12441     
12442     moveTo : function(x, y, animate){
12443         return this.setXY([x, y], animate);
12444     },
12445
12446     
12447     getLeft : function(local){
12448         return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
12449     },
12450
12451     
12452     getRight : function(local){
12453         var me = this;
12454         return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
12455     },
12456
12457     
12458     getTop : function(local) {
12459         return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
12460     },
12461
12462     
12463     getBottom : function(local){
12464         var me = this;
12465         return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
12466     },
12467
12468     
12469     position : function(pos, zIndex, x, y) {
12470         var me = this;
12471
12472         if (!pos && me.isStyle(POSITION, STATIC)){
12473             me.setStyle(POSITION, RELATIVE);
12474         } else if(pos) {
12475             me.setStyle(POSITION, pos);
12476         }
12477         if (zIndex){
12478             me.setStyle(ZINDEX, zIndex);
12479         }
12480         if (x || y) {
12481             me.setXY([x || false, y || false]);
12482         }
12483     },
12484
12485     
12486     clearPositioning : function(value){
12487         value = value || '';
12488         this.setStyle({
12489             left : value,
12490             right : value,
12491             top : value,
12492             bottom : value,
12493             "z-index" : "",
12494             position : STATIC
12495         });
12496         return this;
12497     },
12498
12499     
12500     getPositioning : function(){
12501         var l = this.getStyle(LEFT);
12502         var t = this.getStyle(TOP);
12503         return {
12504             "position" : this.getStyle(POSITION),
12505             "left" : l,
12506             "right" : l ? "" : this.getStyle(RIGHT),
12507             "top" : t,
12508             "bottom" : t ? "" : this.getStyle(BOTTOM),
12509             "z-index" : this.getStyle(ZINDEX)
12510         };
12511     },
12512
12513     
12514     setPositioning : function(pc){
12515         var me = this,
12516             style = me.dom.style;
12517
12518         me.setStyle(pc);
12519
12520         if(pc.right == AUTO){
12521             style.right = "";
12522         }
12523         if(pc.bottom == AUTO){
12524             style.bottom = "";
12525         }
12526
12527         return me;
12528     },
12529
12530     
12531     translatePoints: function(x, y) {
12532         if (Ext.isArray(x)) {
12533              y = x[1];
12534              x = x[0];
12535         }
12536         var me = this,
12537             relative = me.isStyle(POSITION, RELATIVE),
12538             o = me.getXY(),
12539             left = parseInt(me.getStyle(LEFT), 10),
12540             top = parseInt(me.getStyle(TOP), 10);
12541
12542         if (!Ext.isNumber(left)) {
12543             left = relative ? 0 : me.dom.offsetLeft;
12544         }
12545         if (!Ext.isNumber(top)) {
12546             top = relative ? 0 : me.dom.offsetTop;
12547         }
12548         left = (Ext.isNumber(x)) ? x - o[0] + left : undefined;
12549         top = (Ext.isNumber(y)) ? y - o[1] + top : undefined;
12550         return {
12551             left: left,
12552             top: top
12553         };
12554     },
12555
12556     
12557     setBox: function(box, adjust, animate) {
12558         var me = this,
12559             w = box.width,
12560             h = box.height;
12561         if ((adjust && !me.autoBoxAdjust) && !me.isBorderBox()) {
12562             w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
12563             h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
12564         }
12565         me.setBounds(box.x, box.y, w, h, animate);
12566         return me;
12567     },
12568
12569     
12570     getBox: function(contentBox, local) {
12571         var me = this,
12572             xy,
12573             left,
12574             top,
12575             getBorderWidth = me.getBorderWidth,
12576             getPadding = me.getPadding,
12577             l, r, t, b, w, h, bx;
12578         if (!local) {
12579             xy = me.getXY();
12580         } else {
12581             left = parseInt(me.getStyle("left"), 10) || 0;
12582             top = parseInt(me.getStyle("top"), 10) || 0;
12583             xy = [left, top];
12584         }
12585         w = me.getWidth();
12586         h = me.getHeight();
12587         if (!contentBox) {
12588             bx = {
12589                 x: xy[0],
12590                 y: xy[1],
12591                 0: xy[0],
12592                 1: xy[1],
12593                 width: w,
12594                 height: h
12595             };
12596         } else {
12597             l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
12598             r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
12599             t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
12600             b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
12601             bx = {
12602                 x: xy[0] + l,
12603                 y: xy[1] + t,
12604                 0: xy[0] + l,
12605                 1: xy[1] + t,
12606                 width: w - (l + r),
12607                 height: h - (t + b)
12608             };
12609         }
12610         bx.right = bx.x + bx.width;
12611         bx.bottom = bx.y + bx.height;
12612         return bx;
12613     },
12614
12615     
12616     move: function(direction, distance, animate) {
12617         var me = this,
12618             xy = me.getXY(),
12619             x = xy[0],
12620             y = xy[1],
12621             left = [x - distance, y],
12622             right = [x + distance, y],
12623             top = [x, y - distance],
12624             bottom = [x, y + distance],
12625             hash = {
12626                 l: left,
12627                 left: left,
12628                 r: right,
12629                 right: right,
12630                 t: top,
12631                 top: top,
12632                 up: top,
12633                 b: bottom,
12634                 bottom: bottom,
12635                 down: bottom
12636             };
12637
12638         direction = direction.toLowerCase();
12639         me.moveTo(hash[direction][0], hash[direction][1], animate);
12640     },
12641
12642     
12643     setLeftTop: function(left, top) {
12644         var me = this,
12645             style = me.dom.style;
12646         style.left = me.addUnits(left);
12647         style.top = me.addUnits(top);
12648         return me;
12649     },
12650
12651     
12652     getRegion: function() {
12653         return this.getPageBox(true);
12654     },
12655
12656     
12657     getViewRegion: function() {
12658         var me = this,
12659             isBody = me.dom === document.body,
12660             scroll, pos, top, left, width, height;
12661             
12662         
12663         if (isBody) {
12664             scroll = me.getScroll();
12665             left = scroll.left;
12666             top = scroll.top;
12667             width = Ext.core.Element.getViewportWidth();
12668             height = Ext.core.Element.getViewportHeight();
12669         }
12670         else {
12671             pos = me.getXY();
12672             left = pos[0] + me.getBorderWidth('l') + me.getPadding('l');
12673             top = pos[1] + me.getBorderWidth('t') + me.getPadding('t');
12674             width = me.getWidth(true);
12675             height = me.getHeight(true);
12676         }
12677
12678         return Ext.create('Ext.util.Region', top, left + width, top + height, left);
12679     },
12680
12681     
12682     getPageBox : function(getRegion) {
12683         var me = this,
12684             el = me.dom,
12685             isDoc = el === document.body,
12686             w = isDoc ? Ext.core.Element.getViewWidth()  : el.offsetWidth,
12687             h = isDoc ? Ext.core.Element.getViewHeight() : el.offsetHeight,
12688             xy = me.getXY(),
12689             t = xy[1],
12690             r = xy[0] + w,
12691             b = xy[1] + h,
12692             l = xy[0];
12693
12694         if (getRegion) {
12695             return Ext.create('Ext.util.Region', t, r, b, l);
12696         }
12697         else {
12698             return {
12699                 left: l,
12700                 top: t,
12701                 width: w,
12702                 height: h,
12703                 right: r,
12704                 bottom: b
12705             };
12706         }
12707     },
12708
12709     
12710     setBounds: function(x, y, width, height, animate) {
12711         var me = this;
12712         if (!animate || !me.anim) {
12713             me.setSize(width, height);
12714             me.setLocation(x, y);
12715         } else {
12716             if (!Ext.isObject(animate)) {
12717                 animate = {};
12718             }
12719             me.animate(Ext.applyIf({
12720                 to: {
12721                     x: x,
12722                     y: y,
12723                     width: me.adjustWidth(width),
12724                     height: me.adjustHeight(height)
12725                 }
12726             }, animate));
12727         }
12728         return me;
12729     },
12730
12731     
12732     setRegion: function(region, animate) {
12733         return this.setBounds(region.left, region.top, region.right - region.left, region.bottom - region.top, animate);
12734     }
12735 });
12736 })();
12737
12738
12739 Ext.override(Ext.core.Element, {
12740     
12741     isScrollable : function(){
12742         var dom = this.dom;
12743         return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
12744     },
12745
12746     
12747     getScroll : function() {
12748         var d = this.dom, 
12749             doc = document,
12750             body = doc.body,
12751             docElement = doc.documentElement,
12752             l,
12753             t,
12754             ret;
12755
12756         if (d == doc || d == body) {
12757             if (Ext.isIE && Ext.isStrict) {
12758                 l = docElement.scrollLeft; 
12759                 t = docElement.scrollTop;
12760             } else {
12761                 l = window.pageXOffset;
12762                 t = window.pageYOffset;
12763             }
12764             ret = {
12765                 left: l || (body ? body.scrollLeft : 0), 
12766                 top : t || (body ? body.scrollTop : 0)
12767             };
12768         } else {
12769             ret = {
12770                 left: d.scrollLeft, 
12771                 top : d.scrollTop
12772             };
12773         }
12774         
12775         return ret;
12776     },
12777     
12778     
12779     scrollTo : function(side, value, animate) {
12780         
12781         var top = /top/i.test(side),
12782             me = this,
12783             dom = me.dom,
12784             obj = {},
12785             prop;
12786         if (!animate || !me.anim) {
12787             
12788             prop = 'scroll' + (top ? 'Top' : 'Left');
12789             dom[prop] = value;
12790         }
12791         else {
12792             if (!Ext.isObject(animate)) {
12793                 animate = {};
12794             }
12795             obj['scroll' + (top ? 'Top' : 'Left')] = value;
12796             me.animate(Ext.applyIf({
12797                 to: obj
12798             }, animate));
12799         }
12800         return me;
12801     },
12802
12803     
12804     scrollIntoView : function(container, hscroll) {
12805         container = Ext.getDom(container) || Ext.getBody().dom;
12806         var el = this.dom,
12807             offsets = this.getOffsetsTo(container),
12808             
12809             left = offsets[0] + container.scrollLeft,
12810             top = offsets[1] + container.scrollTop,
12811             bottom = top + el.offsetHeight,
12812             right = left + el.offsetWidth,
12813             
12814             ctClientHeight = container.clientHeight,
12815             ctScrollTop = parseInt(container.scrollTop, 10),
12816             ctScrollLeft = parseInt(container.scrollLeft, 10),
12817             ctBottom = ctScrollTop + ctClientHeight,
12818             ctRight = ctScrollLeft + container.clientWidth;
12819
12820         if (el.offsetHeight > ctClientHeight || top < ctScrollTop) {
12821             container.scrollTop = top;
12822         } else if (bottom > ctBottom) {
12823             container.scrollTop = bottom - ctClientHeight;
12824         }
12825         
12826         container.scrollTop = container.scrollTop;
12827
12828         if (hscroll !== false) {
12829             if (el.offsetWidth > container.clientWidth || left < ctScrollLeft) {
12830                 container.scrollLeft = left;
12831             }
12832             else if (right > ctRight) {
12833                 container.scrollLeft = right - container.clientWidth;
12834             }
12835             container.scrollLeft = container.scrollLeft;
12836         }
12837         return this;
12838     },
12839
12840     
12841     scrollChildIntoView : function(child, hscroll) {
12842         Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
12843     },
12844
12845     
12846      scroll : function(direction, distance, animate) {
12847         if (!this.isScrollable()) {
12848             return false;
12849         }
12850         var el = this.dom,
12851             l = el.scrollLeft, t = el.scrollTop,
12852             w = el.scrollWidth, h = el.scrollHeight,
12853             cw = el.clientWidth, ch = el.clientHeight,
12854             scrolled = false, v,
12855             hash = {
12856                 l: Math.min(l + distance, w-cw),
12857                 r: v = Math.max(l - distance, 0),
12858                 t: Math.max(t - distance, 0),
12859                 b: Math.min(t + distance, h-ch)
12860             };
12861             hash.d = hash.b;
12862             hash.u = hash.t;
12863
12864         direction = direction.substr(0, 1);
12865         if ((v = hash[direction]) > -1) {
12866             scrolled = true;
12867             this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.anim(animate));
12868         }
12869         return scrolled;
12870     }
12871 });
12872
12873 Ext.core.Element.addMethods(
12874     function() {
12875         var VISIBILITY      = "visibility",
12876             DISPLAY         = "display",
12877             HIDDEN          = "hidden",
12878             NONE            = "none",
12879             XMASKED         = Ext.baseCSSPrefix + "masked",
12880             XMASKEDRELATIVE = Ext.baseCSSPrefix + "masked-relative",
12881             data            = Ext.core.Element.data;
12882
12883         return {
12884             
12885             isVisible : function(deep) {
12886                 var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE),
12887                     p   = this.dom.parentNode;
12888
12889                 if (deep !== true || !vis) {
12890                     return vis;
12891                 }
12892
12893                 while (p && !(/^body/i.test(p.tagName))) {
12894                     if (!Ext.fly(p, '_isVisible').isVisible()) {
12895                         return false;
12896                     }
12897                     p = p.parentNode;
12898                 }
12899                 return true;
12900             },
12901
12902             
12903             isDisplayed : function() {
12904                 return !this.isStyle(DISPLAY, NONE);
12905             },
12906
12907             
12908             enableDisplayMode : function(display) {
12909                 this.setVisibilityMode(Ext.core.Element.DISPLAY);
12910
12911                 if (!Ext.isEmpty(display)) {
12912                     data(this.dom, 'originalDisplay', display);
12913                 }
12914
12915                 return this;
12916             },
12917
12918             
12919             mask : function(msg, msgCls) {
12920                 var me  = this,
12921                     dom = me.dom,
12922                     setExpression = dom.style.setExpression,
12923                     dh  = Ext.core.DomHelper,
12924                     EXTELMASKMSG = Ext.baseCSSPrefix + "mask-msg",
12925                     el,
12926                     mask;
12927
12928                 if (!(/^body/i.test(dom.tagName) && me.getStyle('position') == 'static')) {
12929                     me.addCls(XMASKEDRELATIVE);
12930                 }
12931                 el = data(dom, 'maskMsg');
12932                 if (el) {
12933                     el.remove();
12934                 }
12935                 el = data(dom, 'mask');
12936                 if (el) {
12937                     el.remove();
12938                 }
12939
12940                 mask = dh.append(dom, {cls : Ext.baseCSSPrefix + "mask"}, true);
12941                 data(dom, 'mask', mask);
12942
12943                 me.addCls(XMASKED);
12944                 mask.setDisplayed(true);
12945
12946                 if (typeof msg == 'string') {
12947                     var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
12948                     data(dom, 'maskMsg', mm);
12949                     mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
12950                     mm.dom.firstChild.innerHTML = msg;
12951                     mm.setDisplayed(true);
12952                     mm.center(me);
12953                 }
12954                 
12955                 
12956                 
12957                 
12958                 
12959                 if (!Ext.supports.IncludePaddingInWidthCalculation && setExpression) {
12960                     mask.dom.style.setExpression('width', 'this.parentNode.offsetWidth + "px"');
12961                 }
12962
12963                 
12964                 
12965                 if (!Ext.supports.IncludePaddingInHeightCalculation && setExpression) {
12966                     mask.dom.style.setExpression('height', 'this.parentNode.offsetHeight + "px"');
12967                 }
12968                 
12969                 else if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') {
12970                     mask.setSize(undefined, me.getHeight());
12971                 }
12972                 return mask;
12973             },
12974
12975             
12976             unmask : function() {
12977                 var me      = this,
12978                     dom     = me.dom,
12979                     mask    = data(dom, 'mask'),
12980                     maskMsg = data(dom, 'maskMsg');
12981
12982                 if (mask) {
12983                     
12984                     if (mask.dom.style.clearExpression) {
12985                         mask.dom.style.clearExpression('width');
12986                         mask.dom.style.clearExpression('height');
12987                     }
12988                     if (maskMsg) {
12989                         maskMsg.remove();
12990                         data(dom, 'maskMsg', undefined);
12991                     }
12992
12993                     mask.remove();
12994                     data(dom, 'mask', undefined);
12995                     me.removeCls([XMASKED, XMASKEDRELATIVE]);
12996                 }
12997             },
12998             
12999             isMasked : function() {
13000                 var me = this,
13001                     mask = data(me.dom, 'mask'),
13002                     maskMsg = data(me.dom, 'maskMsg');
13003
13004                 if (mask && mask.isVisible()) {
13005                     if (maskMsg) {
13006                         maskMsg.center(me);
13007                     }
13008                     return true;
13009                 }
13010                 return false;
13011             },
13012
13013             
13014             createShim : function() {
13015                 var el = document.createElement('iframe'),
13016                     shim;
13017
13018                 el.frameBorder = '0';
13019                 el.className = Ext.baseCSSPrefix + 'shim';
13020                 el.src = Ext.SSL_SECURE_URL;
13021                 shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
13022                 shim.autoBoxAdjust = false;
13023                 return shim;
13024             }
13025         };
13026     }()
13027 );
13028
13029 Ext.core.Element.addMethods({
13030     
13031     addKeyListener : function(key, fn, scope){
13032         var config;
13033         if(typeof key != 'object' || Ext.isArray(key)){
13034             config = {
13035                 key: key,
13036                 fn: fn,
13037                 scope: scope
13038             };
13039         }else{
13040             config = {
13041                 key : key.key,
13042                 shift : key.shift,
13043                 ctrl : key.ctrl,
13044                 alt : key.alt,
13045                 fn: fn,
13046                 scope: scope
13047             };
13048         }
13049         return Ext.create('Ext.util.KeyMap', this, config);
13050     },
13051
13052     
13053     addKeyMap : function(config){
13054         return Ext.create('Ext.util.KeyMap', this, config);
13055     }
13056 });
13057
13058
13059
13060 Ext.CompositeElementLite.importElementMethods();
13061
13062
13063 Ext.apply(Ext.CompositeElementLite.prototype, {
13064     addElements : function(els, root){
13065         if(!els){
13066             return this;
13067         }
13068         if(typeof els == "string"){
13069             els = Ext.core.Element.selectorFunction(els, root);
13070         }
13071         var yels = this.elements;
13072         Ext.each(els, function(e) {
13073             yels.push(Ext.get(e));
13074         });
13075         return this;
13076     },
13077
13078     
13079     first : function(){
13080         return this.item(0);
13081     },
13082
13083     
13084     last : function(){
13085         return this.item(this.getCount()-1);
13086     },
13087
13088     
13089     contains : function(el){
13090         return this.indexOf(el) != -1;
13091     },
13092
13093     
13094     removeElement : function(keys, removeDom){
13095         var me = this,
13096             els = this.elements,
13097             el;
13098         Ext.each(keys, function(val){
13099             if ((el = (els[val] || els[val = me.indexOf(val)]))) {
13100                 if(removeDom){
13101                     if(el.dom){
13102                         el.remove();
13103                     }else{
13104                         Ext.removeNode(el);
13105                     }
13106                 }
13107                 els.splice(val, 1);
13108             }
13109         });
13110         return this;
13111     }
13112 });
13113
13114
13115 Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
13116     
13117     constructor : function(els, root){
13118         this.elements = [];
13119         this.add(els, root);
13120     },
13121     
13122     
13123     getElement : function(el){
13124         
13125         return el;
13126     },
13127     
13128     
13129     transformElement : function(el){
13130         return Ext.get(el);
13131     }
13132
13133     
13134
13135     
13136
13137     
13138 });
13139
13140
13141 Ext.core.Element.select = function(selector, unique, root){
13142     var els;
13143     if(typeof selector == "string"){
13144         els = Ext.core.Element.selectorFunction(selector, root);
13145     }else if(selector.length !== undefined){
13146         els = selector;
13147     }else{
13148         Ext.Error.raise({
13149             sourceClass: "Ext.core.Element",
13150             sourceMethod: "select",
13151             selector: selector,
13152             unique: unique,
13153             root: root,
13154             msg: "Invalid selector specified: " + selector
13155         });
13156     }
13157     return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
13158 };
13159
13160
13161 Ext.select = Ext.core.Element.select;
13162
13163
13164
13165
13166
13167 Ext.define('Ext.util.Observable', {
13168
13169     
13170
13171     requires: ['Ext.util.Event'],
13172
13173     statics: {
13174         
13175         releaseCapture: function(o) {
13176             o.fireEvent = this.prototype.fireEvent;
13177         },
13178
13179         
13180         capture: function(o, fn, scope) {
13181             o.fireEvent = Ext.Function.createInterceptor(o.fireEvent, fn, scope);
13182         },
13183
13184         
13185         observe: function(cls, listeners) {
13186             if (cls) {
13187                 if (!cls.isObservable) {
13188                     Ext.applyIf(cls, new this());
13189                     this.capture(cls.prototype, cls.fireEvent, cls);
13190                 }
13191                 if (Ext.isObject(listeners)) {
13192                     cls.on(listeners);
13193                 }
13194                 return cls;
13195             }
13196         }
13197     },
13198
13199     
13200
13201     
13202     
13203     isObservable: true,
13204
13205     constructor: function(config) {
13206         var me = this;
13207
13208         Ext.apply(me, config);
13209         if (me.listeners) {
13210             me.on(me.listeners);
13211             delete me.listeners;
13212         }
13213         me.events = me.events || {};
13214
13215         if (me.bubbleEvents) {
13216             me.enableBubble(me.bubbleEvents);
13217         }
13218     },
13219
13220     
13221     eventOptionsRe : /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|element|vertical|horizontal)$/,
13222
13223     
13224     addManagedListener : function(item, ename, fn, scope, options) {
13225         var me = this,
13226             managedListeners = me.managedListeners = me.managedListeners || [],
13227             config;
13228
13229         if (Ext.isObject(ename)) {
13230             options = ename;
13231             for (ename in options) {
13232                 if (options.hasOwnProperty(ename)) {
13233                     config = options[ename];
13234                     if (!me.eventOptionsRe.test(ename)) {
13235                         me.addManagedListener(item, ename, config.fn || config, config.scope || options.scope, config.fn ? config : options);
13236                     }
13237                 }
13238             }
13239         }
13240         else {
13241             managedListeners.push({
13242                 item: item,
13243                 ename: ename,
13244                 fn: fn,
13245                 scope: scope,
13246                 options: options
13247             });
13248
13249             item.on(ename, fn, scope, options);
13250         }
13251     },
13252
13253     
13254      removeManagedListener : function(item, ename, fn, scope) {
13255         var me = this,
13256             options,
13257             config,
13258             managedListeners,
13259             managedListener,
13260             length,
13261             i;
13262
13263         if (Ext.isObject(ename)) {
13264             options = ename;
13265             for (ename in options) {
13266                 if (options.hasOwnProperty(ename)) {
13267                     config = options[ename];
13268                     if (!me.eventOptionsRe.test(ename)) {
13269                         me.removeManagedListener(item, ename, config.fn || config, config.scope || options.scope);
13270                     }
13271                 }
13272             }
13273         }
13274
13275         managedListeners = me.managedListeners ? me.managedListeners.slice() : [];
13276         length = managedListeners.length;
13277
13278         for (i = 0; i < length; i++) {
13279             managedListener = managedListeners[i];
13280             if (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope)) {
13281                 Ext.Array.remove(me.managedListeners, managedListener);
13282                 item.un(managedListener.ename, managedListener.fn, managedListener.scope);
13283             }
13284         }
13285     },
13286
13287     
13288     fireEvent: function() {
13289         var me = this,
13290             args = Ext.Array.toArray(arguments),
13291             ename = args[0].toLowerCase(),
13292             ret = true,
13293             event = me.events[ename],
13294             queue = me.eventQueue,
13295             parent;
13296
13297         if (me.eventsSuspended === true) {
13298             if (queue) {
13299                 queue.push(args);
13300             }
13301         } else if (event && Ext.isObject(event) && event.bubble) {
13302             if (event.fire.apply(event, args.slice(1)) === false) {
13303                 return false;
13304             }
13305             parent = me.getBubbleTarget && me.getBubbleTarget();
13306             if (parent && parent.isObservable) {
13307                 if (!parent.events[ename] || !Ext.isObject(parent.events[ename]) || !parent.events[ename].bubble) {
13308                     parent.enableBubble(ename);
13309                 }
13310                 return parent.fireEvent.apply(parent, args);
13311             }
13312         } else if (event && Ext.isObject(event)) {
13313             args.shift();
13314             ret = event.fire.apply(event, args);
13315         }
13316         return ret;
13317     },
13318
13319     
13320     addListener: function(ename, fn, scope, options) {
13321         var me = this,
13322             config,
13323             event;
13324
13325         if (Ext.isObject(ename)) {
13326             options = ename;
13327             for (ename in options) {
13328                 if (options.hasOwnProperty(ename)) {
13329                     config = options[ename];
13330                     if (!me.eventOptionsRe.test(ename)) {
13331                         me.addListener(ename, config.fn || config, config.scope || options.scope, config.fn ? config : options);
13332                     }
13333                 }
13334             }
13335         }
13336         else {
13337             ename = ename.toLowerCase();
13338             me.events[ename] = me.events[ename] || true;
13339             event = me.events[ename] || true;
13340             if (Ext.isBoolean(event)) {
13341                 me.events[ename] = event = new Ext.util.Event(me, ename);
13342             }
13343             event.addListener(fn, scope, Ext.isObject(options) ? options : {});
13344         }
13345     },
13346
13347     
13348     removeListener: function(ename, fn, scope) {
13349         var me = this,
13350             config,
13351             event,
13352             options;
13353
13354         if (Ext.isObject(ename)) {
13355             options = ename;
13356             for (ename in options) {
13357                 if (options.hasOwnProperty(ename)) {
13358                     config = options[ename];
13359                     if (!me.eventOptionsRe.test(ename)) {
13360                         me.removeListener(ename, config.fn || config, config.scope || options.scope);
13361                     }
13362                 }
13363             }
13364         } else {
13365             ename = ename.toLowerCase();
13366             event = me.events[ename];
13367             if (event.isEvent) {
13368                 event.removeListener(fn, scope);
13369             }
13370         }
13371     },
13372
13373     
13374     clearListeners: function() {
13375         var events = this.events,
13376             event,
13377             key;
13378
13379         for (key in events) {
13380             if (events.hasOwnProperty(key)) {
13381                 event = events[key];
13382                 if (event.isEvent) {
13383                     event.clearListeners();
13384                 }
13385             }
13386         }
13387
13388         this.clearManagedListeners();
13389     },
13390
13391     purgeListeners : function() {
13392         console.warn('Observable: purgeListeners has been deprecated. Please use clearListeners.');
13393         return this.clearListeners.apply(this, arguments);
13394     },
13395
13396     
13397     clearManagedListeners : function() {
13398         var managedListeners = this.managedListeners || [],
13399             i = 0,
13400             len = managedListeners.length,
13401             managedListener;
13402
13403         for (; i < len; i++) {
13404             managedListener = managedListeners[i];
13405             managedListener.item.un(managedListener.ename, managedListener.fn, managedListener.scope);
13406         }
13407
13408         this.managedListeners = [];
13409     },
13410
13411     purgeManagedListeners : function() {
13412         console.warn('Observable: purgeManagedListeners has been deprecated. Please use clearManagedListeners.');
13413         return this.clearManagedListeners.apply(this, arguments);
13414     },
13415
13416     
13417     addEvents: function(o) {
13418         var me = this,
13419             args,
13420             len,
13421             i;
13422             
13423             me.events = me.events || {};
13424         if (Ext.isString(o)) {
13425             args = arguments;
13426             i = args.length;
13427             
13428             while (i--) {
13429                 me.events[args[i]] = me.events[args[i]] || true;
13430             }
13431         } else {
13432             Ext.applyIf(me.events, o);
13433         }
13434     },
13435
13436     
13437     hasListener: function(ename) {
13438         var event = this.events[ename.toLowerCase()];
13439         return event && event.isEvent === true && event.listeners.length > 0;
13440     },
13441
13442     
13443     suspendEvents: function(queueSuspended) {
13444         this.eventsSuspended = true;
13445         if (queueSuspended && !this.eventQueue) {
13446             this.eventQueue = [];
13447         }
13448     },
13449
13450     
13451     resumeEvents: function() {
13452         var me = this,
13453             queued = me.eventQueue || [];
13454
13455         me.eventsSuspended = false;
13456         delete me.eventQueue;
13457
13458         Ext.each(queued,
13459         function(e) {
13460             me.fireEvent.apply(me, e);
13461         });
13462     },
13463
13464     
13465     relayEvents : function(origin, events, prefix) {
13466         prefix = prefix || '';
13467         var me = this,
13468             len = events.length,
13469             i = 0,
13470             oldName,
13471             newName;
13472
13473         for (; i < len; i++) {
13474             oldName = events[i].substr(prefix.length);
13475             newName = prefix + oldName;
13476             me.events[newName] = me.events[newName] || true;
13477             origin.on(oldName, me.createRelayer(newName));
13478         }
13479     },
13480
13481     
13482     createRelayer: function(newName){
13483         var me = this;
13484         return function(){
13485             return me.fireEvent.apply(me, [newName].concat(Array.prototype.slice.call(arguments, 0, -1)));
13486         };
13487     },
13488
13489     
13490     enableBubble: function(events) {
13491         var me = this;
13492         if (!Ext.isEmpty(events)) {
13493             events = Ext.isArray(events) ? events: Ext.Array.toArray(arguments);
13494             Ext.each(events,
13495             function(ename) {
13496                 ename = ename.toLowerCase();
13497                 var ce = me.events[ename] || true;
13498                 if (Ext.isBoolean(ce)) {
13499                     ce = new Ext.util.Event(me, ename);
13500                     me.events[ename] = ce;
13501                 }
13502                 ce.bubble = true;
13503             });
13504         }
13505     }
13506 }, function() {
13507     
13508
13509     
13510
13511     this.createAlias({
13512         on: 'addListener',
13513         un: 'removeListener',
13514         mon: 'addManagedListener',
13515         mun: 'removeManagedListener'
13516     });
13517
13518     
13519     this.observeClass = this.observe;
13520
13521     Ext.apply(Ext.util.Observable.prototype, function(){
13522         
13523         
13524         
13525         function getMethodEvent(method){
13526             var e = (this.methodEvents = this.methodEvents || {})[method],
13527                 returnValue,
13528                 v,
13529                 cancel,
13530                 obj = this;
13531
13532             if (!e) {
13533                 this.methodEvents[method] = e = {};
13534                 e.originalFn = this[method];
13535                 e.methodName = method;
13536                 e.before = [];
13537                 e.after = [];
13538
13539                 var makeCall = function(fn, scope, args){
13540                     if((v = fn.apply(scope || obj, args)) !== undefined){
13541                         if (typeof v == 'object') {
13542                             if(v.returnValue !== undefined){
13543                                 returnValue = v.returnValue;
13544                             }else{
13545                                 returnValue = v;
13546                             }
13547                             cancel = !!v.cancel;
13548                         }
13549                         else
13550                             if (v === false) {
13551                                 cancel = true;
13552                             }
13553                             else {
13554                                 returnValue = v;
13555                             }
13556                     }
13557                 };
13558
13559                 this[method] = function(){
13560                     var args = Array.prototype.slice.call(arguments, 0),
13561                         b, i, len;
13562                     returnValue = v = undefined;
13563                     cancel = false;
13564
13565                     for(i = 0, len = e.before.length; i < len; i++){
13566                         b = e.before[i];
13567                         makeCall(b.fn, b.scope, args);
13568                         if (cancel) {
13569                             return returnValue;
13570                         }
13571                     }
13572
13573                     if((v = e.originalFn.apply(obj, args)) !== undefined){
13574                         returnValue = v;
13575                     }
13576
13577                     for(i = 0, len = e.after.length; i < len; i++){
13578                         b = e.after[i];
13579                         makeCall(b.fn, b.scope, args);
13580                         if (cancel) {
13581                             return returnValue;
13582                         }
13583                     }
13584                     return returnValue;
13585                 };
13586             }
13587             return e;
13588         }
13589
13590         return {
13591             
13592             
13593             
13594             beforeMethod : function(method, fn, scope){
13595                 getMethodEvent.call(this, method).before.push({
13596                     fn: fn,
13597                     scope: scope
13598                 });
13599             },
13600
13601             
13602             afterMethod : function(method, fn, scope){
13603                 getMethodEvent.call(this, method).after.push({
13604                     fn: fn,
13605                     scope: scope
13606                 });
13607             },
13608
13609             removeMethodListener: function(method, fn, scope){
13610                 var e = this.getMethodEvent(method),
13611                     i, len;
13612                 for(i = 0, len = e.before.length; i < len; i++){
13613                     if(e.before[i].fn == fn && e.before[i].scope == scope){
13614                         e.before.splice(i, 1);
13615                         return;
13616                     }
13617                 }
13618                 for(i = 0, len = e.after.length; i < len; i++){
13619                     if(e.after[i].fn == fn && e.after[i].scope == scope){
13620                         e.after.splice(i, 1);
13621                         return;
13622                     }
13623                 }
13624             },
13625
13626             toggleEventLogging: function(toggle) {
13627                 Ext.util.Observable[toggle ? 'capture' : 'releaseCapture'](this, function(en) {
13628                     if (Ext.isDefined(Ext.global.console)) {
13629                         Ext.global.console.log(en, arguments);
13630                     }
13631                 });
13632             }
13633         };
13634     }());
13635 });
13636
13637
13638 Ext.define('Ext.util.Animate', {
13639
13640     uses: ['Ext.fx.Manager', 'Ext.fx.Anim'],
13641
13642     
13643     animate: function(animObj) {
13644         var me = this;
13645         if (Ext.fx.Manager.hasFxBlock(me.id)) {
13646             return me;
13647         }
13648         Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(animObj)));
13649         return this;
13650     },
13651
13652     
13653     anim: function(config) {
13654         if (!Ext.isObject(config)) {
13655             return (config) ? {} : false;
13656         }
13657
13658         var me = this;
13659
13660         if (config.stopAnimation) {
13661             me.stopAnimation();
13662         }
13663
13664         Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
13665
13666         return Ext.apply({
13667             target: me,
13668             paused: true
13669         }, config);
13670     },
13671
13672     
13673     stopFx: Ext.Function.alias(Ext.util.Animate, 'stopAnimation'),
13674
13675     
13676     stopAnimation: function() {
13677         Ext.fx.Manager.stopAnimation(this.id);
13678     },
13679
13680     
13681     syncFx: function() {
13682         Ext.fx.Manager.setFxDefaults(this.id, {
13683             concurrent: true
13684         });
13685     },
13686
13687     
13688     sequenceFx: function() {
13689         Ext.fx.Manager.setFxDefaults(this.id, {
13690             concurrent: false
13691         });
13692     },
13693
13694     
13695     hasActiveFx: Ext.Function.alias(Ext.util.Animate, 'getActiveAnimation'),
13696
13697     
13698     getActiveAnimation: function() {
13699         return Ext.fx.Manager.getActiveAnimation(this.id);
13700     }
13701 });
13702
13703
13704 Ext.applyIf(Ext.core.Element.prototype, Ext.util.Animate.prototype);
13705
13706 Ext.define('Ext.state.Provider', {
13707     mixins: {
13708         observable: 'Ext.util.Observable'
13709     },
13710     
13711     
13712     prefix: 'ext-',
13713     
13714     constructor : function(config){
13715         config = config || {};
13716         var me = this;
13717         Ext.apply(me, config);
13718         
13719         me.addEvents("statechange");
13720         me.state = {};
13721         me.mixins.observable.constructor.call(me);
13722     },
13723     
13724     
13725     get : function(name, defaultValue){
13726         return typeof this.state[name] == "undefined" ?
13727             defaultValue : this.state[name];
13728     },
13729
13730     
13731     clear : function(name){
13732         var me = this;
13733         delete me.state[name];
13734         me.fireEvent("statechange", me, name, null);
13735     },
13736
13737     
13738     set : function(name, value){
13739         var me = this;
13740         me.state[name] = value;
13741         me.fireEvent("statechange", me, name, value);
13742     },
13743
13744     
13745     decodeValue : function(value){
13746
13747         
13748         
13749         
13750         
13751         
13752         
13753         
13754
13755         var me = this,
13756             re = /^(a|n|d|b|s|o|e)\:(.*)$/,
13757             matches = re.exec(unescape(value)),
13758             all,
13759             type,
13760             value,
13761             keyValue;
13762             
13763         if(!matches || !matches[1]){
13764             return; 
13765         }
13766         
13767         type = matches[1];
13768         value = matches[2];
13769         switch (type) {
13770             case 'e':
13771                 return null;
13772             case 'n':
13773                 return parseFloat(value);
13774             case 'd':
13775                 return new Date(Date.parse(value));
13776             case 'b':
13777                 return (value == '1');
13778             case 'a':
13779                 all = [];
13780                 if(value != ''){
13781                     Ext.each(value.split('^'), function(val){
13782                         all.push(me.decodeValue(val));
13783                     }, me);
13784                 }
13785                 return all;
13786            case 'o':
13787                 all = {};
13788                 if(value != ''){
13789                     Ext.each(value.split('^'), function(val){
13790                         keyValue = val.split('=');
13791                         all[keyValue[0]] = me.decodeValue(keyValue[1]);
13792                     }, me);
13793                 }
13794                 return all;
13795            default:
13796                 return value;
13797         }
13798     },
13799
13800     
13801     encodeValue : function(value){
13802         var flat = '',
13803             i = 0,
13804             enc,
13805             len,
13806             key;
13807             
13808         if (value == null) {
13809             return 'e:1';    
13810         } else if(typeof value == 'number') {
13811             enc = 'n:' + value;
13812         } else if(typeof value == 'boolean') {
13813             enc = 'b:' + (value ? '1' : '0');
13814         } else if(Ext.isDate(value)) {
13815             enc = 'd:' + value.toGMTString();
13816         } else if(Ext.isArray(value)) {
13817             for (len = value.length; i < len; i++) {
13818                 flat += this.encodeValue(value[i]);
13819                 if (i != len - 1) {
13820                     flat += '^';
13821                 }
13822             }
13823             enc = 'a:' + flat;
13824         } else if (typeof value == 'object') {
13825             for (key in value) {
13826                 if (typeof value[key] != 'function' && value[key] !== undefined) {
13827                     flat += key + '=' + this.encodeValue(value[key]) + '^';
13828                 }
13829             }
13830             enc = 'o:' + flat.substring(0, flat.length-1);
13831         } else {
13832             enc = 's:' + value;
13833         }
13834         return escape(enc);
13835     }
13836 });
13837
13838 Ext.define('Ext.util.HashMap', {
13839
13840     
13841
13842     mixins: {
13843         observable: 'Ext.util.Observable'
13844     },
13845
13846     constructor: function(config) {
13847         var me = this;
13848
13849         me.addEvents(
13850             
13851             'add',
13852             
13853             'clear',
13854             
13855             'remove',
13856             
13857             'replace'
13858         );
13859
13860         me.mixins.observable.constructor.call(me, config);
13861         me.clear(true);
13862     },
13863
13864     
13865     getCount: function() {
13866         return this.length;
13867     },
13868
13869     
13870     getData: function(key, value) {
13871         
13872         if (value === undefined) {
13873             value = key;
13874             key = this.getKey(value);
13875         }
13876
13877         return [key, value];
13878     },
13879
13880     
13881     getKey: function(o) {
13882         return o.id;
13883     },
13884
13885     
13886     add: function(key, value) {
13887         var me = this,
13888             data;
13889
13890         if (arguments.length === 1) {
13891             value = key;
13892             key = me.getKey(value);
13893         }
13894
13895         if (me.containsKey(key)) {
13896             me.replace(key, value);
13897         }
13898
13899         data = me.getData(key, value);
13900         key = data[0];
13901         value = data[1];
13902         me.map[key] = value;
13903         ++me.length;
13904         me.fireEvent('add', me, key, value);
13905         return value;
13906     },
13907
13908     
13909     replace: function(key, value) {
13910         var me = this,
13911             map = me.map,
13912             old;
13913
13914         if (!me.containsKey(key)) {
13915             me.add(key, value);
13916         }
13917         old = map[key];
13918         map[key] = value;
13919         me.fireEvent('replace', me, key, value, old);
13920         return value;
13921     },
13922
13923     
13924     remove: function(o) {
13925         var key = this.findKey(o);
13926         if (key !== undefined) {
13927             return this.removeAtKey(key);
13928         }
13929         return false;
13930     },
13931
13932     
13933     removeAtKey: function(key) {
13934         var me = this,
13935             value;
13936
13937         if (me.containsKey(key)) {
13938             value = me.map[key];
13939             delete me.map[key];
13940             --me.length;
13941             me.fireEvent('remove', me, key, value);
13942             return true;
13943         }
13944         return false;
13945     },
13946
13947     
13948     get: function(key) {
13949         return this.map[key];
13950     },
13951
13952     
13953     clear: function( initial) {
13954         var me = this;
13955         me.map = {};
13956         me.length = 0;
13957         if (initial !== true) {
13958             me.fireEvent('clear', me);
13959         }
13960         return me;
13961     },
13962
13963     
13964     containsKey: function(key) {
13965         return this.map[key] !== undefined;
13966     },
13967
13968     
13969     contains: function(value) {
13970         return this.containsKey(this.findKey(value));
13971     },
13972
13973     
13974     getKeys: function() {
13975         return this.getArray(true);
13976     },
13977
13978     
13979     getValues: function() {
13980         return this.getArray(false);
13981     },
13982
13983     
13984     getArray: function(isKey) {
13985         var arr = [],
13986             key,
13987             map = this.map;
13988         for (key in map) {
13989             if (map.hasOwnProperty(key)) {
13990                 arr.push(isKey ? key: map[key]);
13991             }
13992         }
13993         return arr;
13994     },
13995
13996     
13997     each: function(fn, scope) {
13998         
13999         var items = Ext.apply({}, this.map),
14000             key,
14001             length = this.length;
14002
14003         scope = scope || this;
14004         for (key in items) {
14005             if (items.hasOwnProperty(key)) {
14006                 if (fn.call(scope, key, items[key], length) === false) {
14007                     break;
14008                 }
14009             }
14010         }
14011         return this;
14012     },
14013
14014     
14015     clone: function() {
14016         var hash = new this.self(),
14017             map = this.map,
14018             key;
14019
14020         hash.suspendEvents();
14021         for (key in map) {
14022             if (map.hasOwnProperty(key)) {
14023                 hash.add(key, map[key]);
14024             }
14025         }
14026         hash.resumeEvents();
14027         return hash;
14028     },
14029
14030     
14031     findKey: function(value) {
14032         var key,
14033             map = this.map;
14034
14035         for (key in map) {
14036             if (map.hasOwnProperty(key) && map[key] === value) {
14037                 return key;
14038             }
14039         }
14040         return undefined;
14041     }
14042 });
14043
14044
14045
14046 Ext.define('Ext.Template', {
14047
14048     
14049
14050     requires: ['Ext.core.DomHelper', 'Ext.util.Format'],
14051
14052     statics: {
14053         
14054         from: function(el, config) {
14055             el = Ext.getDom(el);
14056             return new this(el.value || el.innerHTML, config || '');
14057         }
14058     },
14059
14060     
14061
14062     constructor: function(html) {
14063         var me = this,
14064             args = arguments,
14065             buffer = [],
14066             i = 0,
14067             length = args.length,
14068             value;
14069
14070         me.initialConfig = {};
14071
14072         if (length > 1) {
14073             for (; i < length; i++) {
14074                 value = args[i];
14075                 if (typeof value == 'object') {
14076                     Ext.apply(me.initialConfig, value);
14077                     Ext.apply(me, value);
14078                 } else {
14079                     buffer.push(value);
14080                 }
14081             }
14082             html = buffer.join('');
14083         } else {
14084             if (Ext.isArray(html)) {
14085                 buffer.push(html.join(''));
14086             } else {
14087                 buffer.push(html);
14088             }
14089         }
14090
14091         
14092         me.html = buffer.join('');
14093
14094         if (me.compiled) {
14095             me.compile();
14096         }
14097     },
14098     isTemplate: true,
14099     
14100     disableFormats: false,
14101
14102     re: /\{([\w\-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
14103     
14104     applyTemplate: function(values) {
14105         var me = this,
14106             useFormat = me.disableFormats !== true,
14107             fm = Ext.util.Format,
14108             tpl = me;
14109
14110         if (me.compiled) {
14111             return me.compiled(values);
14112         }
14113         function fn(m, name, format, args) {
14114             if (format && useFormat) {
14115                 if (args) {
14116                     args = [values[name]].concat(Ext.functionFactory('return ['+ args +'];')());
14117                 } else {
14118                     args = [values[name]];
14119                 }
14120                 if (format.substr(0, 5) == "this.") {
14121                     return tpl[format.substr(5)].apply(tpl, args);
14122                 }
14123                 else {
14124                     return fm[format].apply(fm, args);
14125                 }
14126             }
14127             else {
14128                 return values[name] !== undefined ? values[name] : "";
14129             }
14130         }
14131         return me.html.replace(me.re, fn);
14132     },
14133
14134     
14135     set: function(html, compile) {
14136         var me = this;
14137         me.html = html;
14138         me.compiled = null;
14139         return compile ? me.compile() : me;
14140     },
14141
14142     compileARe: /\\/g,
14143     compileBRe: /(\r\n|\n)/g,
14144     compileCRe: /'/g,
14145     /**
14146      * Compiles the template into an internal function, eliminating the RegEx overhead.
14147      * @return {Ext.Template} this
14148      * @hide repeat doc
14149      */
14150     compile: function() {
14151         var me = this,
14152             fm = Ext.util.Format,
14153             useFormat = me.disableFormats !== true,
14154             body, bodyReturn;
14155
14156         function fn(m, name, format, args) {
14157             if (format && useFormat) {
14158                 args = args ? ',' + args: "";
14159                 if (format.substr(0, 5) != "this.") {
14160                     format = "fm." + format + '(';
14161                 }
14162                 else {
14163                     format = 'this.' + format.substr(5) + '(';
14164                 }
14165             }
14166             else {
14167                 args = '';
14168                 format = "(values['" + name + "'] == undefined ? '' : ";
14169             }
14170             return "'," + format + "values['" + name + "']" + args + ") ,'";
14171         }
14172
14173         bodyReturn = me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn);
14174         body = "this.compiled = function(values){ return ['" + bodyReturn + "'].join('');};";
14175         eval(body);
14176         return me;
14177     },
14178
14179     /**
14180      * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
14181      * @param {Mixed} el The context element
14182      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
14183      * @param {Boolean} returnElement (optional) true to return a Ext.core.Element (defaults to undefined)
14184      * @return {HTMLElement/Ext.core.Element} The new node or Element
14185      */
14186     insertFirst: function(el, values, returnElement) {
14187         return this.doInsert('afterBegin', el, values, returnElement);
14188     },
14189
14190     /**
14191      * Applies the supplied values to the template and inserts the new node(s) before el.
14192      * @param {Mixed} el The context element
14193      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
14194      * @param {Boolean} returnElement (optional) true to return a Ext.core.Element (defaults to undefined)
14195      * @return {HTMLElement/Ext.core.Element} The new node or Element
14196      */
14197     insertBefore: function(el, values, returnElement) {
14198         return this.doInsert('beforeBegin', el, values, returnElement);
14199     },
14200
14201     /**
14202      * Applies the supplied values to the template and inserts the new node(s) after el.
14203      * @param {Mixed} el The context element
14204      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
14205      * @param {Boolean} returnElement (optional) true to return a Ext.core.Element (defaults to undefined)
14206      * @return {HTMLElement/Ext.core.Element} The new node or Element
14207      */
14208     insertAfter: function(el, values, returnElement) {
14209         return this.doInsert('afterEnd', el, values, returnElement);
14210     },
14211
14212     /**
14213      * Applies the supplied <code>values</code> to the template and appends
14214      * the new node(s) to the specified <code>el</code>.
14215      * <p>For example usage {@link #Template see the constructor}.</p>
14216      * @param {Mixed} el The context element
14217      * @param {Object/Array} values
14218      * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
14219      * or an object (i.e. <code>{foo: 'bar'}</code>).
14220      * @param {Boolean} returnElement (optional) true to return an Ext.core.Element (defaults to undefined)
14221      * @return {HTMLElement/Ext.core.Element} The new node or Element
14222      */
14223     append: function(el, values, returnElement) {
14224         return this.doInsert('beforeEnd', el, values, returnElement);
14225     },
14226
14227     doInsert: function(where, el, values, returnEl) {
14228         el = Ext.getDom(el);
14229         var newNode = Ext.core.DomHelper.insertHtml(where, el, this.applyTemplate(values));
14230         return returnEl ? Ext.get(newNode, true) : newNode;
14231     },
14232
14233     /**
14234      * Applies the supplied values to the template and overwrites the content of el with the new node(s).
14235      * @param {Mixed} el The context element
14236      * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
14237      * @param {Boolean} returnElement (optional) true to return a Ext.core.Element (defaults to undefined)
14238      * @return {HTMLElement/Ext.core.Element} The new node or Element
14239      */
14240     overwrite: function(el, values, returnElement) {
14241         el = Ext.getDom(el);
14242         el.innerHTML = this.applyTemplate(values);
14243         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
14244     }
14245 }, function() {
14246
14247     /**
14248      * Alias for {@link #applyTemplate}
14249      * Returns an HTML fragment of this template with the specified <code>values</code> applied.
14250      * @param {Object/Array} values
14251      * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
14252      * or an object (i.e. <code>{foo: 'bar'}</code>).
14253      * @return {String} The HTML fragment
14254      * @member Ext.Template
14255      * @method apply
14256      */
14257     this.createAlias('apply', 'applyTemplate');
14258 });
14259
14260 /**
14261  * @class Ext.ComponentQuery
14262  * @extends Object
14263  *
14264  * Provides searching of Components within Ext.ComponentManager (globally) or a specific
14265  * Ext.container.Container on the document with a similar syntax to a CSS selector.
14266  *
14267  * Components can be retrieved by using their {@link Ext.Component xtype} with an optional . prefix
14268 <ul>
14269     <li>component or .component</li>
14270     <li>gridpanel or .gridpanel</li>
14271 </ul>
14272  *
14273  * An itemId or id must be prefixed with a #
14274 <ul>
14275     <li>#myContainer</li>
14276 </ul>
14277  *
14278  *
14279  * Attributes must be wrapped in brackets
14280 <ul>
14281     <li>component[autoScroll]</li>
14282     <li>panel[title="Test"]</li>
14283 </ul>
14284  *
14285  * Member expressions from candidate Components may be tested. If the expression returns a <i>truthy</i> value,
14286  * the candidate Component will be included in the query:<pre><code>
14287 var disabledFields = myFormPanel.query("{isDisabled()}");
14288 </code></pre>
14289  *
14290  * Pseudo classes may be used to filter results in the same way as in {@link Ext.DomQuery DomQuery}:<code><pre>
14291 // Function receives array and returns a filtered array.
14292 Ext.ComponentQuery.pseudos.invalid = function(items) {
14293     var i = 0, l = items.length, c, result = [];
14294     for (; i < l; i++) {
14295         if (!(c = items[i]).isValid()) {
14296             result.push(c);
14297         }
14298     }
14299     return result;
14300 };
14301
14302 var invalidFields = myFormPanel.query('field:invalid');
14303 if (invalidFields.length) {
14304     invalidFields[0].getEl().scrollIntoView(myFormPanel.body);
14305     for (var i = 0, l = invalidFields.length; i < l; i++) {
14306         invalidFields[i].getEl().frame("red");
14307     }
14308 }
14309 </pre></code>
14310  * <p>
14311  * Default pseudos include:<br />
14312  * - not
14313  * </p>
14314  *
14315  * Queries return an array of components.
14316  * Here are some example queries.
14317 <pre><code>
14318     // retrieve all Ext.Panels in the document by xtype
14319     var panelsArray = Ext.ComponentQuery.query('panel');
14320
14321     // retrieve all Ext.Panels within the container with an id myCt
14322     var panelsWithinmyCt = Ext.ComponentQuery.query('#myCt panel');
14323
14324     // retrieve all direct children which are Ext.Panels within myCt
14325     var directChildPanel = Ext.ComponentQuery.query('#myCt > panel');
14326
14327     // retrieve all gridpanels and listviews
14328     var gridsAndLists = Ext.ComponentQuery.query('gridpanel, listview');
14329 </code></pre>
14330
14331 For easy access to queries based from a particular Container see the {@link Ext.container.Container#query},
14332 {@link Ext.container.Container#down} and {@link Ext.container.Container#child} methods. Also see
14333 {@link Ext.Component#up}.
14334  * @singleton
14335  */
14336 Ext.define('Ext.ComponentQuery', {
14337     singleton: true,
14338     uses: ['Ext.ComponentManager']
14339 }, function() {
14340
14341     var cq = this,
14342
14343         // A function source code pattern with a placeholder which accepts an expression which yields a truth value when applied
14344         // as a member on each item in the passed array.
14345         filterFnPattern = [
14346             'var r = [],',
14347                 'i = 0,',
14348                 'it = items,',
14349                 'l = it.length,',
14350                 'c;',
14351             'for (; i < l; i++) {',
14352                 'c = it[i];',
14353                 'if (c.{0}) {',
14354                    'r.push(c);',
14355                 '}',
14356             '}',
14357             'return r;'
14358         ].join(''),
14359
14360         filterItems = function(items, operation) {
14361             // Argument list for the operation is [ itemsArray, operationArg1, operationArg2...]
14362             // The operation's method loops over each item in the candidate array and
14363             // returns an array of items which match its criteria
14364             return operation.method.apply(this, [ items ].concat(operation.args));
14365         },
14366
14367         getItems = function(items, mode) {
14368             var result = [],
14369                 i = 0,
14370                 length = items.length,
14371                 candidate,
14372                 deep = mode !== '>';
14373                 
14374             for (; i < length; i++) {
14375                 candidate = items[i];
14376                 if (candidate.getRefItems) {
14377                     result = result.concat(candidate.getRefItems(deep));
14378                 }
14379             }
14380             return result;
14381         },
14382
14383         getAncestors = function(items) {
14384             var result = [],
14385                 i = 0,
14386                 length = items.length,
14387                 candidate;
14388             for (; i < length; i++) {
14389                 candidate = items[i];
14390                 while (!!(candidate = (candidate.ownerCt || candidate.floatParent))) {
14391                     result.push(candidate);
14392                 }
14393             }
14394             return result;
14395         },
14396
14397         // Filters the passed candidate array and returns only items which match the passed xtype
14398         filterByXType = function(items, xtype, shallow) {
14399             if (xtype === '*') {
14400                 return items.slice();
14401             }
14402             else {
14403                 var result = [],
14404                     i = 0,
14405                     length = items.length,
14406                     candidate;
14407                 for (; i < length; i++) {
14408                     candidate = items[i];
14409                     if (candidate.isXType(xtype, shallow)) {
14410                         result.push(candidate);
14411                     }
14412                 }
14413                 return result;
14414             }
14415         },
14416
14417         // Filters the passed candidate array and returns only items which have the passed className
14418         filterByClassName = function(items, className) {
14419             var EA = Ext.Array,
14420                 result = [],
14421                 i = 0,
14422                 length = items.length,
14423                 candidate;
14424             for (; i < length; i++) {
14425                 candidate = items[i];
14426                 if (candidate.el ? candidate.el.hasCls(className) : EA.contains(candidate.initCls(), className)) {
14427                     result.push(candidate);
14428                 }
14429             }
14430             return result;
14431         },
14432
14433         // Filters the passed candidate array and returns only items which have the specified property match
14434         filterByAttribute = function(items, property, operator, value) {
14435             var result = [],
14436                 i = 0,
14437                 length = items.length,
14438                 candidate;
14439             for (; i < length; i++) {
14440                 candidate = items[i];
14441                 if (!value ? !!candidate[property] : (String(candidate[property]) === value)) {
14442                     result.push(candidate);
14443                 }
14444             }
14445             return result;
14446         },
14447
14448         // Filters the passed candidate array and returns only items which have the specified itemId or id
14449         filterById = function(items, id) {
14450             var result = [],
14451                 i = 0,
14452                 length = items.length,
14453                 candidate;
14454             for (; i < length; i++) {
14455                 candidate = items[i];
14456                 if (candidate.getItemId() === id) {
14457                     result.push(candidate);
14458                 }
14459             }
14460             return result;
14461         },
14462
14463         // Filters the passed candidate array and returns only items which the named pseudo class matcher filters in
14464         filterByPseudo = function(items, name, value) {
14465             return cq.pseudos[name](items, value);
14466         },
14467
14468         // Determines leading mode
14469         // > for direct child, and ^ to switch to ownerCt axis
14470         modeRe = /^(\s?([>\^])\s?|\s|$)/,
14471
14472         // Matches a token with possibly (true|false) appended for the "shallow" parameter
14473         tokenRe = /^(#)?([\w\-]+|\*)(?:\((true|false)\))?/,
14474
14475         matchers = [{
14476             // Checks for .xtype with possibly (true|false) appended for the "shallow" parameter
14477             re: /^\.([\w\-]+)(?:\((true|false)\))?/,
14478             method: filterByXType
14479         },{
14480             // checks for [attribute=value]
14481             re: /^(?:[\[](?:@)?([\w\-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]])/,
14482             method: filterByAttribute
14483         }, {
14484             // checks for #cmpItemId
14485             re: /^#([\w\-]+)/,
14486             method: filterById
14487         }, {
14488             // checks for :<pseudo_class>(<selector>)
14489             re: /^\:([\w\-]+)(?:\(((?:\{[^\}]+\})|(?:(?!\{)[^\s>\/]*?(?!\})))\))?/,
14490             method: filterByPseudo
14491         }, {
14492             // checks for {<member_expression>}
14493             re: /^(?:\{([^\}]+)\})/,
14494             method: filterFnPattern
14495         }];
14496
14497     /**
14498      * @class Ext.ComponentQuery.Query
14499      * @extends Object
14500      * @private
14501      */
14502     cq.Query = Ext.extend(Object, {
14503         constructor: function(cfg) {
14504             cfg = cfg || {};
14505             Ext.apply(this, cfg);
14506         },
14507
14508         /**
14509          * @private
14510          * Executes this Query upon the selected root.
14511          * The root provides the initial source of candidate Component matches which are progressively
14512          * filtered by iterating through this Query's operations cache.
14513          * If no root is provided, all registered Components are searched via the ComponentManager.
14514          * root may be a Container who's descendant Components are filtered
14515          * root may be a Component with an implementation of getRefItems which provides some nested Components such as the
14516          * docked items within a Panel.
14517          * root may be an array of candidate Components to filter using this Query.
14518          */
14519         execute : function(root) {
14520             var operations = this.operations,
14521                 i = 0,
14522                 length = operations.length,
14523                 operation,
14524                 workingItems;
14525
14526             // no root, use all Components in the document
14527             if (!root) {
14528                 workingItems = Ext.ComponentManager.all.getArray();
14529             }
14530             // Root is a candidate Array
14531             else if (Ext.isArray(root)) {
14532                 workingItems = root;
14533             }
14534
14535             // We are going to loop over our operations and take care of them
14536             // one by one.
14537             for (; i < length; i++) {
14538                 operation = operations[i];
14539
14540                 // The mode operation requires some custom handling.
14541                 // All other operations essentially filter down our current
14542                 // working items, while mode replaces our current working
14543                 // items by getting children from each one of our current
14544                 // working items. The type of mode determines the type of
14545                 // children we get. (e.g. > only gets direct children)
14546                 if (operation.mode === '^') {
14547                     workingItems = getAncestors(workingItems || [root]);
14548                 }
14549                 else if (operation.mode) {
14550                     workingItems = getItems(workingItems || [root], operation.mode);
14551                 }
14552                 else {
14553                     workingItems = filterItems(workingItems || getItems([root]), operation);
14554                 }
14555
14556                 // If this is the last operation, it means our current working
14557                 // items are the final matched items. Thus return them!
14558                 if (i === length -1) {
14559                     return workingItems;
14560                 }
14561             }
14562             return [];
14563         },
14564
14565         is: function(component) {
14566             var operations = this.operations,
14567                 components = Ext.isArray(component) ? component : [component],
14568                 originalLength = components.length,
14569                 lastOperation = operations[operations.length-1],
14570                 ln, i;
14571
14572             components = filterItems(components, lastOperation);
14573             if (components.length === originalLength) {
14574                 if (operations.length > 1) {
14575                     for (i = 0, ln = components.length; i < ln; i++) {
14576                         if (Ext.Array.indexOf(this.execute(), components[i]) === -1) {
14577                             return false;
14578                         }
14579                     }
14580                 }
14581                 return true;
14582             }
14583             return false;
14584         }
14585     });
14586
14587     Ext.apply(this, {
14588
14589         // private cache of selectors and matching ComponentQuery.Query objects
14590         cache: {},
14591
14592         // private cache of pseudo class filter functions
14593         pseudos: {
14594             not: function(components, selector){
14595                 var CQ = Ext.ComponentQuery,
14596                     i = 0,
14597                     length = components.length,
14598                     results = [],
14599                     index = -1,
14600                     component;
14601                 
14602                 for(; i < length; ++i) {
14603                     component = components[i];
14604                     if (!CQ.is(component, selector)) {
14605                         results[++index] = component;
14606                     }
14607                 }
14608                 return results;
14609             }
14610         },
14611
14612         /**
14613          * <p>Returns an array of matched Components from within the passed root object.</p>
14614          * <p>This method filters returned Components in a similar way to how CSS selector based DOM
14615          * queries work using a textual selector string.</p>
14616          * <p>See class summary for details.</p>
14617          * @param selector The selector string to filter returned Components
14618          * @param root <p>The Container within which to perform the query. If omitted, all Components
14619          * within the document are included in the search.</p>
14620          * <p>This parameter may also be an array of Components to filter according to the selector.</p>
14621          * @returns {Array} The matched Components.
14622          * @member Ext.ComponentQuery
14623          * @method query
14624          */
14625         query: function(selector, root) {
14626             var selectors = selector.split(','),
14627                 length = selectors.length,
14628                 i = 0,
14629                 results = [],
14630                 noDupResults = [], 
14631                 dupMatcher = {}, 
14632                 query, resultsLn, cmp;
14633
14634             for (; i < length; i++) {
14635                 selector = Ext.String.trim(selectors[i]);
14636                 query = this.cache[selector];
14637                 if (!query) {
14638                     this.cache[selector] = query = this.parse(selector);
14639                 }
14640                 results = results.concat(query.execute(root));
14641             }
14642
14643             // multiple selectors, potential to find duplicates
14644             // lets filter them out.
14645             if (length > 1) {
14646                 resultsLn = results.length;
14647                 for (i = 0; i < resultsLn; i++) {
14648                     cmp = results[i];
14649                     if (!dupMatcher[cmp.id]) {
14650                         noDupResults.push(cmp);
14651                         dupMatcher[cmp.id] = true;
14652                     }
14653                 }
14654                 results = noDupResults;
14655             }
14656             return results;
14657         },
14658
14659         /**
14660          * Tests whether the passed Component matches the selector string.
14661          * @param component The Component to test
14662          * @param selector The selector string to test against.
14663          * @return {Boolean} True if the Component matches the selector.
14664          * @member Ext.ComponentQuery
14665          * @method query
14666          */
14667         is: function(component, selector) {
14668             if (!selector) {
14669                 return true;
14670             }
14671             var query = this.cache[selector];
14672             if (!query) {
14673                 this.cache[selector] = query = this.parse(selector);
14674             }
14675             return query.is(component);
14676         },
14677
14678         parse: function(selector) {
14679             var operations = [],
14680                 length = matchers.length,
14681                 lastSelector,
14682                 tokenMatch,
14683                 matchedChar,
14684                 modeMatch,
14685                 selectorMatch,
14686                 i, matcher, method;
14687
14688             // We are going to parse the beginning of the selector over and
14689             // over again, slicing off the selector any portions we converted into an
14690             // operation, until it is an empty string.
14691             while (selector && lastSelector !== selector) {
14692                 lastSelector = selector;
14693
14694                 // First we check if we are dealing with a token like #, * or an xtype
14695                 tokenMatch = selector.match(tokenRe);
14696
14697                 if (tokenMatch) {
14698                     matchedChar = tokenMatch[1];
14699
14700                     // If the token is prefixed with a # we push a filterById operation to our stack
14701                     if (matchedChar === '#') {
14702                         operations.push({
14703                             method: filterById,
14704                             args: [Ext.String.trim(tokenMatch[2])]
14705                         });
14706                     }
14707                     // If the token is prefixed with a . we push a filterByClassName operation to our stack
14708                     // FIXME: Not enabled yet. just needs \. adding to the tokenRe prefix
14709                     else if (matchedChar === '.') {
14710                         operations.push({
14711                             method: filterByClassName,
14712                             args: [Ext.String.trim(tokenMatch[2])]
14713                         });
14714                     }
14715                     // If the token is a * or an xtype string, we push a filterByXType
14716                     // operation to the stack.
14717                     else {
14718                         operations.push({
14719                             method: filterByXType,
14720                             args: [Ext.String.trim(tokenMatch[2]), Boolean(tokenMatch[3])]
14721                         });
14722                     }
14723
14724                     // Now we slice of the part we just converted into an operation
14725                     selector = selector.replace(tokenMatch[0], '');
14726                 }
14727
14728                 // If the next part of the query is not a space or > or ^, it means we
14729                 // are going to check for more things that our current selection
14730                 // has to comply to.
14731                 while (!(modeMatch = selector.match(modeRe))) {
14732                     // Lets loop over each type of matcher and execute it
14733                     // on our current selector.
14734                     for (i = 0; selector && i < length; i++) {
14735                         matcher = matchers[i];
14736                         selectorMatch = selector.match(matcher.re);
14737                         method = matcher.method;
14738
14739                         // If we have a match, add an operation with the method
14740                         // associated with this matcher, and pass the regular
14741                         // expression matches are arguments to the operation.
14742                         if (selectorMatch) {
14743                             operations.push({
14744                                 method: Ext.isString(matcher.method)
14745                                     // Turn a string method into a function by formatting the string with our selector matche expression
14746                                     // A new method is created for different match expressions, eg {id=='textfield-1024'}
14747                                     // Every expression may be different in different selectors.
14748                                     ? Ext.functionFactory('items', Ext.String.format.apply(Ext.String, [method].concat(selectorMatch.slice(1))))
14749                                     : matcher.method,
14750                                 args: selectorMatch.slice(1)
14751                             });
14752                             selector = selector.replace(selectorMatch[0], '');
14753                             break; // Break on match
14754                         }
14755                         // Exhausted all matches: It's an error
14756                         if (i === (length - 1)) {
14757                             Ext.Error.raise('Invalid ComponentQuery selector: "' + arguments[0] + '"');
14758                         }
14759                     }
14760                 }
14761
14762                 // Now we are going to check for a mode change. This means a space
14763                 // or a > to determine if we are going to select all the children
14764                 // of the currently matched items, or a ^ if we are going to use the
14765                 // ownerCt axis as the candidate source.
14766                 if (modeMatch[1]) { // Assignment, and test for truthiness!
14767                     operations.push({
14768                         mode: modeMatch[2]||modeMatch[1]
14769                     });
14770                     selector = selector.replace(modeMatch[0], '');
14771                 }
14772             }
14773
14774             //  Now that we have all our operations in an array, we are going
14775             // to create a new Query using these operations.
14776             return new cq.Query({
14777                 operations: operations
14778             });
14779         }
14780     });
14781 });
14782 /**
14783  * @class Ext.util.Filter
14784  * @extends Object
14785  * <p>Represents a filter that can be applied to a {@link Ext.util.MixedCollection MixedCollection}. Can either simply
14786  * filter on a property/value pair or pass in a filter function with custom logic. Filters are always used in the context
14787  * of MixedCollections, though {@link Ext.data.Store Store}s frequently create them when filtering and searching on their
14788  * records. Example usage:</p>
14789 <pre><code>
14790 //set up a fictional MixedCollection containing a few people to filter on
14791 var allNames = new Ext.util.MixedCollection();
14792 allNames.addAll([
14793     {id: 1, name: 'Ed',    age: 25},
14794     {id: 2, name: 'Jamie', age: 37},
14795     {id: 3, name: 'Abe',   age: 32},
14796     {id: 4, name: 'Aaron', age: 26},
14797     {id: 5, name: 'David', age: 32}
14798 ]);
14799
14800 var ageFilter = new Ext.util.Filter({
14801     property: 'age',
14802     value   : 32
14803 });
14804
14805 var longNameFilter = new Ext.util.Filter({
14806     filterFn: function(item) {
14807         return item.name.length > 4;
14808     }
14809 });
14810
14811 //a new MixedCollection with the 3 names longer than 4 characters
14812 var longNames = allNames.filter(longNameFilter);
14813
14814 //a new MixedCollection with the 2 people of age 24:
14815 var youngFolk = allNames.filter(ageFilter);
14816 </code></pre>
14817  * @constructor
14818  * @param {Object} config Config object
14819  */
14820 Ext.define('Ext.util.Filter', {
14821
14822     /* Begin Definitions */
14823
14824     /* End Definitions */
14825     /**
14826      * @cfg {String} property The property to filter on. Required unless a {@link #filter} is passed
14827      */
14828     
14829     /**
14830      * @cfg {Function} filterFn A custom filter function which is passed each item in the {@link Ext.util.MixedCollection} 
14831      * in turn. Should return true to accept each item or false to reject it
14832      */
14833     
14834     /**
14835      * @cfg {Boolean} anyMatch True to allow any match - no regex start/end line anchors will be added. Defaults to false
14836      */
14837     anyMatch: false,
14838     
14839     /**
14840      * @cfg {Boolean} exactMatch True to force exact match (^ and $ characters added to the regex). Defaults to false.
14841      * Ignored if anyMatch is true.
14842      */
14843     exactMatch: false,
14844     
14845     /**
14846      * @cfg {Boolean} caseSensitive True to make the regex case sensitive (adds 'i' switch to regex). Defaults to false.
14847      */
14848     caseSensitive: false,
14849     
14850     /**
14851      * @cfg {String} root Optional root property. This is mostly useful when filtering a Store, in which case we set the
14852      * root to 'data' to make the filter pull the {@link #property} out of the data object of each item
14853      */
14854     
14855     constructor: function(config) {
14856         Ext.apply(this, config);
14857         
14858         //we're aliasing filter to filterFn mostly for API cleanliness reasons, despite the fact it dirties the code here.
14859         //Ext.util.Sorter takes a sorterFn property but allows .sort to be called - we do the same here
14860         this.filter = this.filter || this.filterFn;
14861         
14862         if (this.filter == undefined) {
14863             if (this.property == undefined || this.value == undefined) {
14864                 // Commented this out temporarily because it stops us using string ids in models. TODO: Remove this once
14865                 // Model has been updated to allow string ids
14866                 
14867                 // Ext.Error.raise("A Filter requires either a property or a filterFn to be set");
14868             } else {
14869                 this.filter = this.createFilterFn();
14870             }
14871             
14872             this.filterFn = this.filter;
14873         }
14874     },
14875     
14876     /**
14877      * @private
14878      * Creates a filter function for the configured property/value/anyMatch/caseSensitive options for this Filter
14879      */
14880     createFilterFn: function() {
14881         var me       = this,
14882             matcher  = me.createValueMatcher(),
14883             property = me.property;
14884         
14885         return function(item) {
14886             return matcher.test(me.getRoot.call(me, item)[property]);
14887         };
14888     },
14889     
14890     /**
14891      * @private
14892      * Returns the root property of the given item, based on the configured {@link #root} property
14893      * @param {Object} item The item
14894      * @return {Object} The root property of the object
14895      */
14896     getRoot: function(item) {
14897         return this.root == undefined ? item : item[this.root];
14898     },
14899     
14900     /**
14901      * @private
14902      * Returns a regular expression based on the given value and matching options
14903      */
14904     createValueMatcher : function() {
14905         var me            = this,
14906             value         = me.value,
14907             anyMatch      = me.anyMatch,
14908             exactMatch    = me.exactMatch,
14909             caseSensitive = me.caseSensitive,
14910             escapeRe      = Ext.String.escapeRegex;
14911         
14912         if (!value.exec) { // not a regex
14913             value = String(value);
14914
14915             if (anyMatch === true) {
14916                 value = escapeRe(value);
14917             } else {
14918                 value = '^' + escapeRe(value);
14919                 if (exactMatch === true) {
14920                     value += '$';
14921                 }
14922             }
14923             value = new RegExp(value, caseSensitive ? '' : 'i');
14924          }
14925          
14926          return value;
14927     }
14928 });
14929 /**
14930  * @class Ext.util.Sorter
14931  * @extends Object
14932  * Represents a single sorter that can be applied to a Store
14933  */
14934 Ext.define('Ext.util.Sorter', {
14935
14936     /**
14937      * @cfg {String} property The property to sort by. Required unless {@link #sorter} is provided
14938      */
14939     
14940     /**
14941      * @cfg {Function} sorterFn A specific sorter function to execute. Can be passed instead of {@link #property}
14942      */
14943     
14944     /**
14945      * @cfg {String} root Optional root property. This is mostly useful when sorting a Store, in which case we set the
14946      * root to 'data' to make the filter pull the {@link #property} out of the data object of each item
14947      */
14948     
14949     /**
14950      * @cfg {Function} transform A function that will be run on each value before
14951      * it is compared in the sorter. The function will receive a single argument,
14952      * the value.
14953      */
14954     
14955     /**
14956      * @cfg {String} direction The direction to sort by. Defaults to ASC
14957      */
14958     direction: "ASC",
14959     
14960     constructor: function(config) {
14961         var me = this;
14962         
14963         Ext.apply(me, config);
14964         
14965         if (me.property == undefined && me.sorterFn == undefined) {
14966             Ext.Error.raise("A Sorter requires either a property or a sorter function");
14967         }
14968         
14969         me.updateSortFunction();
14970     },
14971     
14972     /**
14973      * @private
14974      * Creates and returns a function which sorts an array by the given property and direction
14975      * @return {Function} A function which sorts by the property/direction combination provided
14976      */
14977     createSortFunction: function(sorterFn) {
14978         var me        = this,
14979             property  = me.property,
14980             direction = me.direction || "ASC",
14981             modifier  = direction.toUpperCase() == "DESC" ? -1 : 1;
14982         
14983         //create a comparison function. Takes 2 objects, returns 1 if object 1 is greater,
14984         //-1 if object 2 is greater or 0 if they are equal
14985         return function(o1, o2) {
14986             return modifier * sorterFn.call(me, o1, o2);
14987         };
14988     },
14989     
14990     /**
14991      * @private
14992      * Basic default sorter function that just compares the defined property of each object
14993      */
14994     defaultSorterFn: function(o1, o2) {
14995         var me = this,
14996             transform = me.transform,
14997             v1 = me.getRoot(o1)[me.property],
14998             v2 = me.getRoot(o2)[me.property];
14999             
15000         if (transform) {
15001             v1 = transform(v1);
15002             v2 = transform(v2);
15003         }
15004
15005         return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
15006     },
15007     
15008     /**
15009      * @private
15010      * Returns the root property of the given item, based on the configured {@link #root} property
15011      * @param {Object} item The item
15012      * @return {Object} The root property of the object
15013      */
15014     getRoot: function(item) {
15015         return this.root == undefined ? item : item[this.root];
15016     },
15017     
15018     // @TODO: Add docs for these three methods
15019     setDirection: function(direction) {
15020         var me = this;
15021         me.direction = direction;
15022         me.updateSortFunction();
15023     },
15024     
15025     toggle: function() {
15026         var me = this;
15027         me.direction = Ext.String.toggle(me.direction, "ASC", "DESC");
15028         me.updateSortFunction();
15029     },
15030     
15031     updateSortFunction: function() {
15032         var me = this;
15033         me.sort = me.createSortFunction(me.sorterFn || me.defaultSorterFn);
15034     }
15035 });
15036 /**
15037  * @class Ext.ElementLoader
15038  * A class used to load remote content to an Element. Sample usage:
15039  * <pre><code>
15040 Ext.get('el').load({
15041     url: 'myPage.php',
15042     scripts: true,
15043     params: {
15044         id: 1
15045     }
15046 });
15047  * </code></pre>
15048  * <p>
15049  * In general this class will not be instanced directly, rather the {@link Ext.core.Element#load} method
15050  * will be used.
15051  * </p>
15052  */
15053 Ext.define('Ext.ElementLoader', {
15054
15055     /* Begin Definitions */
15056
15057     mixins: {
15058         observable: 'Ext.util.Observable'
15059     },
15060
15061     uses: [
15062         'Ext.data.Connection',
15063         'Ext.Ajax'
15064     ],
15065     
15066     statics: {
15067         Renderer: {
15068             Html: function(loader, response, active){
15069                 loader.getTarget().update(response.responseText, active.scripts === true);
15070                 return true;
15071             }
15072         }     
15073     },
15074
15075     /* End Definitions */
15076
15077     /**
15078      * @cfg {String} url The url to retrieve the content from. Defaults to <tt>null</tt>.
15079      */
15080     url: null,
15081
15082     /**
15083      * @cfg {Object} params Any params to be attached to the Ajax request. These parameters will
15084      * be overridden by any params in the load options. Defaults to <tt>null</tt>.
15085      */
15086     params: null,
15087
15088     /**
15089      * @cfg {Object} baseParams Params that will be attached to every request. These parameters
15090      * will not be overridden by any params in the load options. Defaults to <tt>null</tt>.
15091      */
15092     baseParams: null,
15093
15094     /**
15095      * @cfg {Boolean/Object} autoLoad True to have the loader make a request as soon as it is created. Defaults to <tt>false</tt>.
15096      * This argument can also be a set of options that will be passed to {@link #load} is called.
15097      */
15098     autoLoad: false,
15099
15100     /**
15101      * @cfg {Mixed} target The target element for the loader. It can be the DOM element, the id or an Ext.Element.
15102      */
15103     target: null,
15104
15105     /**
15106      * @cfg {Mixed} loadMask True or a string to show when the element is loading.
15107      */
15108     loadMask: false,
15109
15110     /**
15111      * @cfg {Object} ajaxOptions Any additional options to be passed to the request, for example timeout or headers. Defaults to <tt>null</tt>.
15112      */
15113     ajaxOptions: null,
15114     
15115     /**
15116      * @cfg {Boolean} scripts True to parse any inline script tags in the response.
15117      */
15118     scripts: false,
15119
15120     /**
15121      * @cfg {Function} success A function to be called when a load request is successful.
15122      */
15123
15124     /**
15125      * @cfg {Function} failure A function to be called when a load request fails.
15126      */
15127
15128     /**
15129      * @cfg {Object} scope The scope to execute the {@link #success} and {@link #failure} functions in.
15130      */
15131     
15132     /**
15133      * @cfg {Function} renderer A custom function to render the content to the element. The passed parameters
15134      * are
15135      * <ul>
15136      * <li>The loader</li>
15137      * <li>The response</li>
15138      * <li>The active request</li>
15139      * </ul>
15140      */
15141
15142     isLoader: true,
15143
15144     constructor: function(config) {
15145         var me = this,
15146             autoLoad;
15147         
15148         config = config || {};
15149         Ext.apply(me, config);
15150         me.setTarget(me.target);
15151         me.addEvents(
15152             /**
15153              * @event beforeload
15154              * Fires before a load request is made to the server.
15155              * Returning false from an event listener can prevent the load
15156              * from occurring.
15157              * @param {Ext.ElementLoader} this
15158              * @param {Object} options The options passed to the request
15159              */
15160             'beforeload',
15161
15162             /**
15163              * @event exception
15164              * Fires after an unsuccessful load.
15165              * @param {Ext.ElementLoader} this
15166              * @param {Object} response The response from the server
15167              * @param {Object} options The options passed to the request
15168              */
15169             'exception',
15170
15171             /**
15172              * @event exception
15173              * Fires after a successful load.
15174              * @param {Ext.ElementLoader} this
15175              * @param {Object} response The response from the server
15176              * @param {Object} options The options passed to the request
15177              */
15178             'load'
15179         );
15180
15181         // don't pass config because we have already applied it.
15182         me.mixins.observable.constructor.call(me);
15183
15184         if (me.autoLoad) {
15185             autoLoad = me.autoLoad;
15186             if (autoLoad === true) {
15187                 autoLoad = {};
15188             }
15189             me.load(autoLoad);
15190         }
15191     },
15192
15193     /**
15194      * Set an {Ext.Element} as the target of this loader. Note that if the target is changed,
15195      * any active requests will be aborted.
15196      * @param {Mixed} target The element
15197      */
15198     setTarget: function(target){
15199         var me = this;
15200         target = Ext.get(target);
15201         if (me.target && me.target != target) {
15202             me.abort();
15203         }
15204         me.target = target;
15205     },
15206
15207     /**
15208      * Get the target of this loader.
15209      * @return {Ext.Component} target The target, null if none exists.
15210      */
15211     getTarget: function(){
15212         return this.target || null;
15213     },
15214
15215     /**
15216      * Aborts the active load request
15217      */
15218     abort: function(){
15219         var active = this.active;
15220         if (active !== undefined) {
15221             Ext.Ajax.abort(active.request);
15222             if (active.mask) {
15223                 this.removeMask();
15224             }
15225             delete this.active;
15226         }
15227     },
15228     
15229     /**
15230      * Remove the mask on the target
15231      * @private
15232      */
15233     removeMask: function(){
15234         this.target.unmask();
15235     },
15236     
15237     /**
15238      * Add the mask on the target
15239      * @private
15240      * @param {Mixed} mask The mask configuration
15241      */
15242     addMask: function(mask){
15243         this.target.mask(mask === true ? null : mask);
15244     },
15245
15246     /**
15247      * Load new data from the server.
15248      * @param {Object} options The options for the request. They can be any configuration option that can be specified for
15249      * the class, with the exception of the target option. Note that any options passed to the method will override any
15250      * class defaults.
15251      */
15252     load: function(options) {
15253         if (!this.target) {
15254             Ext.Error.raise('A valid target is required when loading content');
15255         }
15256
15257         options = Ext.apply({}, options);
15258
15259         var me = this,
15260             target = me.target,
15261             mask = Ext.isDefined(options.loadMask) ? options.loadMask : me.loadMask,
15262             params = Ext.apply({}, options.params),
15263             ajaxOptions = Ext.apply({}, options.ajaxOptions),
15264             callback = options.callback || me.callback,
15265             scope = options.scope || me.scope || me,
15266             request;
15267
15268         Ext.applyIf(ajaxOptions, me.ajaxOptions);
15269         Ext.applyIf(options, ajaxOptions);
15270
15271         Ext.applyIf(params, me.params);
15272         Ext.apply(params, me.baseParams);
15273
15274         Ext.applyIf(options, {
15275             url: me.url
15276         });
15277
15278         if (!options.url) {
15279             Ext.Error.raise('You must specify the URL from which content should be loaded');
15280         }
15281
15282         Ext.apply(options, {
15283             scope: me,
15284             params: params,
15285             callback: me.onComplete
15286         });
15287
15288         if (me.fireEvent('beforeload', me, options) === false) {
15289             return;
15290         }
15291
15292         if (mask) {
15293             me.addMask(mask);
15294         }
15295
15296         request = Ext.Ajax.request(options);
15297         me.active = {
15298             request: request,
15299             options: options,
15300             mask: mask,
15301             scope: scope,
15302             callback: callback,
15303             success: options.success || me.success,
15304             failure: options.failure || me.failure,
15305             renderer: options.renderer || me.renderer,
15306             scripts: Ext.isDefined(options.scripts) ? options.scripts : me.scripts
15307         };
15308         me.setOptions(me.active, options);
15309     },
15310     
15311     /**
15312      * Set any additional options on the active request
15313      * @private
15314      * @param {Object} active The active request
15315      * @param {Object} options The initial options
15316      */
15317     setOptions: Ext.emptyFn,
15318
15319     /**
15320      * Parse the response after the request completes
15321      * @private
15322      * @param {Object} options Ajax options
15323      * @param {Boolean} success Success status of the request
15324      * @param {Object} response The response object
15325      */
15326     onComplete: function(options, success, response) {
15327         var me = this,
15328             active = me.active,
15329             scope = active.scope,
15330             renderer = me.getRenderer(active.renderer);
15331
15332
15333         if (success) {
15334             success = renderer.call(me, me, response, active);
15335         }
15336
15337         if (success) {
15338             Ext.callback(active.success, scope, [me, response, options]);
15339             me.fireEvent('load', me, response, options);
15340         } else {
15341             Ext.callback(active.failure, scope, [me, response, options]);
15342             me.fireEvent('exception', me, response, options);
15343         }
15344         Ext.callback(active.callback, scope, [me, success, response, options]);
15345
15346         if (active.mask) {
15347             me.removeMask();
15348         }
15349
15350         delete me.active;
15351     },
15352
15353     /**
15354      * Gets the renderer to use
15355      * @private
15356      * @param {String/Function} renderer The renderer to use
15357      * @return {Function} A rendering function to use.
15358      */
15359     getRenderer: function(renderer){
15360         if (Ext.isFunction(renderer)) {
15361             return renderer;
15362         }
15363         return this.statics().Renderer.Html;
15364     },
15365     
15366     /**
15367      * Automatically refreshes the content over a specified period.
15368      * @param {Number} interval The interval to refresh in ms.
15369      * @param {Object} options (optional) The options to pass to the load method. See {@link #load}
15370      */
15371     startAutoRefresh: function(interval, options){
15372         var me = this;
15373         me.stopAutoRefresh();
15374         me.autoRefresh = setInterval(function(){
15375             me.load(options);
15376         }, interval);
15377     },
15378     
15379     /**
15380      * Clears any auto refresh. See {@link #startAutoRefresh}.
15381      */
15382     stopAutoRefresh: function(){
15383         clearInterval(this.autoRefresh);
15384         delete this.autoRefresh;
15385     },
15386     
15387     /**
15388      * Checks whether the loader is automatically refreshing. See {@link #startAutoRefresh}.
15389      * @return {Boolean} True if the loader is automatically refreshing
15390      */
15391     isAutoRefreshing: function(){
15392         return Ext.isDefined(this.autoRefresh);
15393     },
15394
15395     /**
15396      * Destroys the loader. Any active requests will be aborted.
15397      */
15398     destroy: function(){
15399         var me = this;
15400         me.stopAutoRefresh();
15401         delete me.target;
15402         me.abort();
15403         me.clearListeners();
15404     }
15405 });
15406
15407 /**
15408  * @class Ext.layout.Layout
15409  * @extends Object
15410  * @private
15411  * Base Layout class - extended by ComponentLayout and ContainerLayout
15412  */
15413
15414 Ext.define('Ext.layout.Layout', {
15415
15416     /* Begin Definitions */
15417
15418     /* End Definitions */
15419
15420     isLayout: true,
15421     initialized: false,
15422
15423     statics: {
15424         create: function(layout, defaultType) {
15425             var type;
15426             if (layout instanceof Ext.layout.Layout) {
15427                 return Ext.createByAlias('layout.' + layout);
15428             } else {
15429                 if (Ext.isObject(layout)) {
15430                     type = layout.type;
15431                 }
15432                 else {
15433                     type = layout || defaultType;
15434                     layout = {};
15435                 }
15436                 return Ext.createByAlias('layout.' + type, layout || {});
15437             }
15438         }
15439     },
15440
15441     constructor : function(config) {
15442         this.id = Ext.id(null, this.type + '-');
15443         Ext.apply(this, config);
15444     },
15445
15446     /**
15447      * @private
15448      */
15449     layout : function() {
15450         var me = this;
15451         me.layoutBusy = true;
15452         me.initLayout();
15453
15454         if (me.beforeLayout.apply(me, arguments) !== false) {
15455             me.layoutCancelled = false;
15456             me.onLayout.apply(me, arguments);
15457             me.childrenChanged = false;
15458             me.owner.needsLayout = false;
15459             me.layoutBusy = false;
15460             me.afterLayout.apply(me, arguments);
15461         }
15462         else {
15463             me.layoutCancelled = true;
15464         }
15465         me.layoutBusy = false;
15466         me.doOwnerCtLayouts();
15467     },
15468
15469     beforeLayout : function() {
15470         this.renderItems(this.getLayoutItems(), this.getRenderTarget());
15471         return true;
15472     },
15473
15474     /**
15475      * @private
15476      * Iterates over all passed items, ensuring they are rendered.  If the items are already rendered,
15477      * also determines if the items are in the proper place dom.
15478      */
15479     renderItems : function(items, target) {
15480         var ln = items.length,
15481             i = 0,
15482             item;
15483
15484         for (; i < ln; i++) {
15485             item = items[i];
15486             if (item && !item.rendered) {
15487                 this.renderItem(item, target, i);
15488             }
15489             else if (!this.isValidParent(item, target, i)) {
15490                 this.moveItem(item, target, i);
15491             }
15492         }
15493     },
15494
15495     // @private - Validates item is in the proper place in the dom.
15496     isValidParent : function(item, target, position) {
15497         var dom = item.el ? item.el.dom : Ext.getDom(item);
15498         if (dom && target && target.dom) {
15499             if (Ext.isNumber(position) && dom !== target.dom.childNodes[position]) {
15500                 return false;
15501             }
15502             return (dom.parentNode == (target.dom || target));
15503         }
15504         return false;
15505     },
15506
15507     /**
15508      * @private
15509      * Renders the given Component into the target Element.
15510      * @param {Ext.Component} item The Component to render
15511      * @param {Ext.core.Element} target The target Element
15512      * @param {Number} position The position within the target to render the item to
15513      */
15514     renderItem : function(item, target, position) {
15515         if (!item.rendered) {
15516             item.render(target, position);
15517             this.configureItem(item);
15518             this.childrenChanged = true;
15519         }
15520     },
15521
15522     /**
15523      * @private
15524      * Moved Component to the provided target instead.
15525      */
15526     moveItem : function(item, target, position) {
15527         // Make sure target is a dom element
15528         target = target.dom || target;
15529         if (typeof position == 'number') {
15530             position = target.childNodes[position];
15531         }
15532         target.insertBefore(item.el.dom, position || null);
15533         item.container = Ext.get(target);
15534         this.configureItem(item);
15535         this.childrenChanged = true;
15536     },
15537
15538     /**
15539      * @private
15540      * Adds the layout's targetCls if necessary and sets
15541      * initialized flag when complete.
15542      */
15543     initLayout : function() {
15544         if (!this.initialized && !Ext.isEmpty(this.targetCls)) {
15545             this.getTarget().addCls(this.targetCls);
15546         }
15547         this.initialized = true;
15548     },
15549
15550     // @private Sets the layout owner
15551     setOwner : function(owner) {
15552         this.owner = owner;
15553     },
15554
15555     // @private - Returns empty array
15556     getLayoutItems : function() {
15557         return [];
15558     },
15559
15560     /**
15561      * @private
15562      * Applies itemCls
15563      */
15564     configureItem: function(item) {
15565         var me = this,
15566             el = item.el,
15567             owner = me.owner;
15568             
15569         if (me.itemCls) {
15570             el.addCls(me.itemCls);
15571         }
15572         if (owner.itemCls) {
15573             el.addCls(owner.itemCls);
15574         }
15575     },
15576     
15577     // Placeholder empty functions for subclasses to extend
15578     onLayout : Ext.emptyFn,
15579     afterLayout : Ext.emptyFn,
15580     onRemove : Ext.emptyFn,
15581     onDestroy : Ext.emptyFn,
15582     doOwnerCtLayouts : Ext.emptyFn,
15583
15584     /**
15585      * @private
15586      * Removes itemCls
15587      */
15588     afterRemove : function(item) {
15589         var me = this,
15590             el = item.el,
15591             owner = me.owner;
15592             
15593         if (item.rendered) {
15594             if (me.itemCls) {
15595                 el.removeCls(me.itemCls);
15596             }
15597             if (owner.itemCls) {
15598                 el.removeCls(owner.itemCls);
15599             }
15600         }
15601     },
15602
15603     /*
15604      * Destroys this layout. This is a template method that is empty by default, but should be implemented
15605      * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
15606      * @protected
15607      */
15608     destroy : function() {
15609         if (!Ext.isEmpty(this.targetCls)) {
15610             var target = this.getTarget();
15611             if (target) {
15612                 target.removeCls(this.targetCls);
15613             }
15614         }
15615         this.onDestroy();
15616     }
15617 });
15618 /**
15619  * @class Ext.layout.component.Component
15620  * @extends Ext.layout.Layout
15621  * @private
15622  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Component#componentLayout layout}</b></tt>
15623  * configuration property.  See <tt><b>{@link Ext.Component#componentLayout}</b></tt> for additional details.</p>
15624  */
15625
15626 Ext.define('Ext.layout.component.Component', {
15627
15628     /* Begin Definitions */
15629
15630     extend: 'Ext.layout.Layout',
15631
15632     /* End Definitions */
15633
15634     type: 'component',
15635
15636     monitorChildren: true,
15637
15638     initLayout : function() {
15639         var me = this,
15640             owner = me.owner,
15641             ownerEl = owner.el;
15642
15643         if (!me.initialized) {
15644             if (owner.frameSize) {
15645                 me.frameSize = owner.frameSize;
15646             }
15647             else {
15648                 owner.frameSize = me.frameSize = {
15649                     top: 0,
15650                     left: 0,
15651                     bottom: 0,
15652                     right: 0
15653                 }; 
15654             }
15655         }
15656         me.callParent(arguments);
15657     },
15658
15659     beforeLayout : function(width, height, isSetSize, layoutOwner) {
15660         this.callParent(arguments);
15661
15662         var me = this,
15663             owner = me.owner,
15664             ownerCt = owner.ownerCt,
15665             layout = owner.layout,
15666             isVisible = owner.isVisible(true),
15667             ownerElChild = owner.el.child,
15668             layoutCollection;
15669
15670         /**
15671         * Do not layout calculatedSized components for fixedLayouts unless the ownerCt == layoutOwner
15672         * fixedLayouts means layouts which are never auto/auto in the sizing that comes from their ownerCt.
15673         * Currently 3 layouts MAY be auto/auto (Auto, Border, and Box)
15674         * The reason for not allowing component layouts is to stop component layouts from things such as Updater and
15675         * form Validation.
15676         */
15677         if (!isSetSize && !(Ext.isNumber(width) && Ext.isNumber(height)) && ownerCt && ownerCt.layout && ownerCt.layout.fixedLayout && ownerCt != layoutOwner) {
15678             me.doContainerLayout();
15679             return false;
15680         }
15681
15682         // If an ownerCt is hidden, add my reference onto the layoutOnShow stack.  Set the needsLayout flag.
15683         // If the owner itself is a directly hidden floater, set the needsLayout object on that for when it is shown.
15684         if (!isVisible && (owner.hiddenAncestor || owner.floating)) {
15685             if (owner.hiddenAncestor) {
15686                 layoutCollection = owner.hiddenAncestor.layoutOnShow;
15687                 layoutCollection.remove(owner);
15688                 layoutCollection.add(owner);
15689             }
15690             owner.needsLayout = {
15691                 width: width,
15692                 height: height,
15693                 isSetSize: false
15694             };
15695         }
15696
15697         if (isVisible && this.needsLayout(width, height)) {
15698             me.rawWidth = width;
15699             me.rawHeight = height;
15700             return owner.beforeComponentLayout(width, height, isSetSize, layoutOwner);
15701         }
15702         else {
15703             return false;
15704         }
15705     },
15706
15707     /**
15708     * Check if the new size is different from the current size and only
15709     * trigger a layout if it is necessary.
15710     * @param {Mixed} width The new width to set.
15711     * @param {Mixed} height The new height to set.
15712     */
15713     needsLayout : function(width, height) {
15714         this.lastComponentSize = this.lastComponentSize || {
15715             width: -Infinity,
15716             height: -Infinity
15717         };
15718         return (this.childrenChanged || this.lastComponentSize.width !== width || this.lastComponentSize.height !== height);
15719     },
15720
15721     /**
15722     * Set the size of any element supporting undefined, null, and values.
15723     * @param {Mixed} width The new width to set.
15724     * @param {Mixed} height The new height to set.
15725     */
15726     setElementSize: function(el, width, height) {
15727         if (width !== undefined && height !== undefined) {
15728             el.setSize(width, height);
15729         }
15730         else if (height !== undefined) {
15731             el.setHeight(height);
15732         }
15733         else if (width !== undefined) {
15734             el.setWidth(width);
15735         }
15736     },
15737
15738     /**
15739      * Returns the owner component's resize element.
15740      * @return {Ext.core.Element}
15741      */
15742      getTarget : function() {
15743          return this.owner.el;
15744      },
15745
15746     /**
15747      * <p>Returns the element into which rendering must take place. Defaults to the owner Component's encapsulating element.</p>
15748      * May be overridden in Component layout managers which implement an inner element.
15749      * @return {Ext.core.Element}
15750      */
15751     getRenderTarget : function() {
15752         return this.owner.el;
15753     },
15754
15755     /**
15756     * Set the size of the target element.
15757     * @param {Mixed} width The new width to set.
15758     * @param {Mixed} height The new height to set.
15759     */
15760     setTargetSize : function(width, height) {
15761         var me = this;
15762         me.setElementSize(me.owner.el, width, height);
15763
15764         if (me.owner.frameBody) {
15765             var targetInfo = me.getTargetInfo(),
15766                 padding = targetInfo.padding,
15767                 border = targetInfo.border,
15768                 frameSize = me.frameSize;
15769
15770             me.setElementSize(me.owner.frameBody,
15771                 Ext.isNumber(width) ? (width - frameSize.left - frameSize.right - padding.left - padding.right - border.left - border.right) : width,
15772                 Ext.isNumber(height) ? (height - frameSize.top - frameSize.bottom - padding.top - padding.bottom - border.top - border.bottom) : height
15773             );
15774         }
15775
15776         me.autoSized = {
15777             width: !Ext.isNumber(width),
15778             height: !Ext.isNumber(height)
15779         };
15780
15781         me.lastComponentSize = {
15782             width: width,
15783             height: height
15784         };
15785     },
15786
15787     getTargetInfo : function() {
15788         if (!this.targetInfo) {
15789             var target = this.getTarget(),
15790                 body = this.owner.getTargetEl();
15791
15792             this.targetInfo = {
15793                 padding: {
15794                     top: target.getPadding('t'),
15795                     right: target.getPadding('r'),
15796                     bottom: target.getPadding('b'),
15797                     left: target.getPadding('l')
15798                 },
15799                 border: {
15800                     top: target.getBorderWidth('t'),
15801                     right: target.getBorderWidth('r'),
15802                     bottom: target.getBorderWidth('b'),
15803                     left: target.getBorderWidth('l')
15804                 },
15805                 bodyMargin: {
15806                     top: body.getMargin('t'),
15807                     right: body.getMargin('r'),
15808                     bottom: body.getMargin('b'),
15809                     left: body.getMargin('l')
15810                 } 
15811             };
15812         }
15813         return this.targetInfo;
15814     },
15815
15816     // Start laying out UP the ownerCt's layout when flagged to do so.
15817     doOwnerCtLayouts: function() {
15818         var owner = this.owner,
15819             ownerCt = owner.ownerCt,
15820             ownerCtComponentLayout, ownerCtContainerLayout;
15821
15822         if (!ownerCt) {
15823             return;
15824         }
15825
15826         ownerCtComponentLayout = ownerCt.componentLayout;
15827         ownerCtContainerLayout = ownerCt.layout;
15828
15829         if (!owner.floating && ownerCtComponentLayout && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
15830             if (!ownerCt.suspendLayout && ownerCtContainerLayout && !ownerCtContainerLayout.layoutBusy) {
15831                 // AutoContainer Layout and Dock with auto in some dimension
15832                 if (ownerCtContainerLayout.bindToOwnerCtComponent === true) {
15833                     ownerCt.doComponentLayout();
15834                 }
15835                 // Box Layouts
15836                 else if (ownerCtContainerLayout.bindToOwnerCtContainer === true) {
15837                     ownerCtContainerLayout.layout();
15838                 }
15839             }
15840         }
15841     },
15842
15843     doContainerLayout: function() {
15844         var me = this,
15845             owner = me.owner,
15846             ownerCt = owner.ownerCt,
15847             layout = owner.layout,
15848             ownerCtComponentLayout;
15849
15850         // Run the container layout if it exists (layout for child items)
15851         // **Unless automatic laying out is suspended, or the layout is currently running**
15852         if (!owner.suspendLayout && layout && layout.isLayout && !layout.layoutBusy) {
15853             layout.layout();
15854         }
15855
15856         // Tell the ownerCt that it's child has changed and can be re-layed by ignoring the lastComponentSize cache.
15857         if (ownerCt && ownerCt.componentLayout) {
15858             ownerCtComponentLayout = ownerCt.componentLayout;
15859             if (!owner.floating && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
15860                 ownerCtComponentLayout.childrenChanged = true;
15861             }
15862         }
15863     },
15864
15865     afterLayout : function(width, height, isSetSize, layoutOwner) {
15866         this.doContainerLayout();
15867         this.owner.afterComponentLayout(width, height, isSetSize, layoutOwner);
15868     }
15869 });
15870
15871 /**
15872  * @class Ext.state.Manager
15873  * This is the global state manager. By default all components that are "state aware" check this class
15874  * for state information if you don't pass them a custom state provider. In order for this class
15875  * to be useful, it must be initialized with a provider when your application initializes. Example usage:
15876  <pre><code>
15877 // in your initialization function
15878 init : function(){
15879    Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
15880    var win = new Window(...);
15881    win.restoreState();
15882 }
15883  </code></pre>
15884  * This class passes on calls from components to the underlying {@link Ext.state.Provider} so that
15885  * there is a common interface that can be used without needing to refer to a specific provider instance
15886  * in every component.
15887  * @singleton
15888  * @docauthor Evan Trimboli <evan@sencha.com>
15889  */
15890 Ext.define('Ext.state.Manager', {
15891     singleton: true,
15892     requires: ['Ext.state.Provider'],
15893     constructor: function() {
15894         this.provider = Ext.create('Ext.state.Provider');
15895     },
15896     
15897     
15898     /**
15899      * Configures the default state provider for your application
15900      * @param {Provider} stateProvider The state provider to set
15901      */
15902     setProvider : function(stateProvider){
15903         this.provider = stateProvider;
15904     },
15905
15906     /**
15907      * Returns the current value for a key
15908      * @param {String} name The key name
15909      * @param {Mixed} defaultValue The default value to return if the key lookup does not match
15910      * @return {Mixed} The state data
15911      */
15912     get : function(key, defaultValue){
15913         return this.provider.get(key, defaultValue);
15914     },
15915
15916     /**
15917      * Sets the value for a key
15918      * @param {String} name The key name
15919      * @param {Mixed} value The state data
15920      */
15921      set : function(key, value){
15922         this.provider.set(key, value);
15923     },
15924
15925     /**
15926      * Clears a value from the state
15927      * @param {String} name The key name
15928      */
15929     clear : function(key){
15930         this.provider.clear(key);
15931     },
15932
15933     /**
15934      * Gets the currently configured state provider
15935      * @return {Provider} The state provider
15936      */
15937     getProvider : function(){
15938         return this.provider;
15939     }
15940 });
15941 /**
15942  * @class Ext.state.Stateful
15943  * A mixin for being able to save the state of an object to an underlying 
15944  * {@link Ext.state.Provider}.
15945  */
15946 Ext.define('Ext.state.Stateful', {
15947     
15948     /* Begin Definitions */
15949    
15950    mixins: {
15951         observable: 'Ext.util.Observable'
15952     },
15953     
15954     requires: ['Ext.state.Manager'],
15955     
15956     /* End Definitions */
15957     
15958     /**
15959      * @cfg {Boolean} stateful
15960      * <p>A flag which causes the object to attempt to restore the state of
15961      * internal properties from a saved state on startup. The object must have
15962      * a <code>{@link #stateId}</code> for state to be managed. 
15963      * Auto-generated ids are not guaranteed to be stable across page loads and 
15964      * cannot be relied upon to save and restore the same state for a object.<p>
15965      * <p>For state saving to work, the state manager's provider must have been
15966      * set to an implementation of {@link Ext.state.Provider} which overrides the
15967      * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get}
15968      * methods to save and recall name/value pairs. A built-in implementation,
15969      * {@link Ext.state.CookieProvider} is available.</p>
15970      * <p>To set the state provider for the current page:</p>
15971      * <pre><code>
15972 Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
15973     expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
15974 }));
15975      * </code></pre>
15976      * <p>A stateful object attempts to save state when one of the events
15977      * listed in the <code>{@link #stateEvents}</code> configuration fires.</p>
15978      * <p>To save state, a stateful object first serializes its state by
15979      * calling <b><code>{@link #getState}</code></b>. By default, this function does
15980      * nothing. The developer must provide an implementation which returns an
15981      * object hash which represents the restorable state of the object.</p>
15982      * <p>The value yielded by getState is passed to {@link Ext.state.Manager#set}
15983      * which uses the configured {@link Ext.state.Provider} to save the object
15984      * keyed by the <code>{@link stateId}</code></p>.
15985      * <p>During construction, a stateful object attempts to <i>restore</i>
15986      * its state by calling {@link Ext.state.Manager#get} passing the
15987      * <code>{@link #stateId}</code></p>
15988      * <p>The resulting object is passed to <b><code>{@link #applyState}</code></b>.
15989      * The default implementation of <code>{@link #applyState}</code> simply copies
15990      * properties into the object, but a developer may override this to support
15991      * more behaviour.</p>
15992      * <p>You can perform extra processing on state save and restore by attaching
15993      * handlers to the {@link #beforestaterestore}, {@link #staterestore},
15994      * {@link #beforestatesave} and {@link #statesave} events.</p>
15995      */
15996     stateful: true,
15997     
15998     /**
15999      * @cfg {String} stateId
16000      * The unique id for this object to use for state management purposes.
16001      * <p>See {@link #stateful} for an explanation of saving and restoring state.</p>
16002      */
16003     
16004     /**
16005      * @cfg {Array} stateEvents
16006      * <p>An array of events that, when fired, should trigger this object to
16007      * save its state (defaults to none). <code>stateEvents</code> may be any type
16008      * of event supported by this object, including browser or custom events
16009      * (e.g., <tt>['click', 'customerchange']</tt>).</p>
16010      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
16011      * restoring object state.</p>
16012      */
16013     
16014     /**
16015      * @cfg {Number} saveBuffer A buffer to be applied if many state events are fired within
16016      * a short period. Defaults to 100.
16017      */
16018     saveDelay: 100,
16019     
16020     autoGenIdRe: /^((\w+-)|(ext-comp-))\d{4,}$/i,
16021     
16022     constructor: function(config) {
16023         var me = this;
16024         
16025         config = config || {};
16026         if (Ext.isDefined(config.stateful)) {
16027             me.stateful = config.stateful;
16028         }
16029         if (Ext.isDefined(config.saveDelay)) {
16030             me.saveDelay = config.saveDelay;
16031         }
16032         me.stateId = config.stateId;
16033         
16034         if (!me.stateEvents) {
16035             me.stateEvents = [];
16036         }
16037         if (config.stateEvents) {
16038             me.stateEvents.concat(config.stateEvents);
16039         }
16040         this.addEvents(
16041             /**
16042              * @event beforestaterestore
16043              * Fires before the state of the object is restored. Return false from an event handler to stop the restore.
16044              * @param {Ext.state.Stateful} this
16045              * @param {Object} state The hash of state values returned from the StateProvider. If this
16046              * event is not vetoed, then the state object is passed to <b><tt>applyState</tt></b>. By default,
16047              * that simply copies property values into this object. The method maybe overriden to
16048              * provide custom state restoration.
16049              */
16050             'beforestaterestore',
16051             
16052             /**
16053              * @event staterestore
16054              * Fires after the state of the object is restored.
16055              * @param {Ext.state.Stateful} this
16056              * @param {Object} state The hash of state values returned from the StateProvider. This is passed
16057              * to <b><tt>applyState</tt></b>. By default, that simply copies property values into this
16058              * object. The method maybe overriden to provide custom state restoration.
16059              */
16060             'staterestore',
16061             
16062             /**
16063              * @event beforestatesave
16064              * Fires before the state of the object is saved to the configured state provider. Return false to stop the save.
16065              * @param {Ext.state.Stateful} this
16066              * @param {Object} state The hash of state values. This is determined by calling
16067              * <b><tt>getState()</tt></b> on the object. This method must be provided by the
16068              * developer to return whetever representation of state is required, by default, Ext.state.Stateful
16069              * has a null implementation.
16070              */
16071             'beforestatesave',
16072             
16073             /**
16074              * @event statesave
16075              * Fires after the state of the object is saved to the configured state provider.
16076              * @param {Ext.state.Stateful} this
16077              * @param {Object} state The hash of state values. This is determined by calling
16078              * <b><tt>getState()</tt></b> on the object. This method must be provided by the
16079              * developer to return whetever representation of state is required, by default, Ext.state.Stateful
16080              * has a null implementation.
16081              */
16082             'statesave'
16083         );
16084         me.mixins.observable.constructor.call(me);
16085         if (me.stateful !== false) {
16086             me.initStateEvents();
16087             me.initState();
16088         }
16089     },
16090     
16091     /**
16092      * Initializes any state events for this object.
16093      * @private
16094      */
16095     initStateEvents: function() {
16096         this.addStateEvents(this.stateEvents);
16097     },
16098     
16099     /**
16100      * Add events that will trigger the state to be saved.
16101      * @param {String/Array} events The event name or an array of event names.
16102      */
16103     addStateEvents: function(events){
16104         if (!Ext.isArray(events)) {
16105             events = [events];
16106         }
16107         
16108         var me = this,
16109             i = 0,
16110             len = events.length;
16111             
16112         for (; i < len; ++i) {
16113             me.on(events[i], me.onStateChange, me);
16114         }
16115     },
16116     
16117     /**
16118      * This method is called when any of the {@link #stateEvents} are fired.
16119      * @private
16120      */
16121     onStateChange: function(){
16122         var me = this,
16123             delay = me.saveDelay;
16124         
16125         if (delay > 0) {
16126             if (!me.stateTask) {
16127                 me.stateTask = Ext.create('Ext.util.DelayedTask', me.saveState, me);
16128             }
16129             me.stateTask.delay(me.saveDelay);
16130         } else {
16131             me.saveState();
16132         }
16133     },
16134     
16135     /**
16136      * Saves the state of the object to the persistence store.
16137      * @private
16138      */
16139     saveState: function() {
16140         var me = this,
16141             id,
16142             state;
16143         
16144         if (me.stateful !== false) {
16145             id = me.getStateId();
16146             if (id) {
16147                 state = me.getState();
16148                 if (me.fireEvent('beforestatesave', me, state) !== false) {
16149                     Ext.state.Manager.set(id, state);
16150                     me.fireEvent('statesave', me, state);
16151                 }
16152             }
16153         }
16154     },
16155     
16156     /**
16157      * Gets the current state of the object. By default this function returns null,
16158      * it should be overridden in subclasses to implement methods for getting the state.
16159      * @return {Object} The current state
16160      */
16161     getState: function(){
16162         return null;    
16163     },
16164     
16165     /**
16166      * Applies the state to the object. This should be overridden in subclasses to do
16167      * more complex state operations. By default it applies the state properties onto
16168      * the current object.
16169      * @param {Object} state The state
16170      */
16171     applyState: function(state) {
16172         if (state) {
16173             Ext.apply(this, state);
16174         }
16175     },
16176     
16177     /**
16178      * Gets the state id for this object.
16179      * @return {String} The state id, null if not found.
16180      */
16181     getStateId: function() {
16182         var me = this,
16183             id = me.stateId;
16184         
16185         if (!id) {
16186             id = me.autoGenIdRe.test(String(me.id)) ? null : me.id;
16187         }
16188         return id;
16189     },
16190     
16191     /**
16192      * Initializes the state of the object upon construction.
16193      * @private
16194      */
16195     initState: function(){
16196         var me = this,
16197             id = me.getStateId(),
16198             state;
16199             
16200         if (me.stateful !== false) {
16201             if (id) {
16202                 state = Ext.state.Manager.get(id);
16203                 if (state) {
16204                     state = Ext.apply({}, state);
16205                     if (me.fireEvent('beforestaterestore', me, state) !== false) {
16206                         me.applyState(state);
16207                         me.fireEvent('staterestore', me, state);
16208                     }
16209                 }
16210             }
16211         }
16212     },
16213     
16214     /**
16215      * Destroys this stateful object.
16216      */
16217     destroy: function(){
16218         var task = this.stateTask;
16219         if (task) {
16220             task.cancel();
16221         }
16222         this.clearListeners();
16223         
16224     }
16225     
16226 });
16227
16228 /**
16229  * @class Ext.AbstractManager
16230  * @extends Object
16231  * @ignore
16232  * Base Manager class
16233  */
16234
16235 Ext.define('Ext.AbstractManager', {
16236
16237     /* Begin Definitions */
16238
16239     requires: ['Ext.util.HashMap'],
16240
16241     /* End Definitions */
16242
16243     typeName: 'type',
16244
16245     constructor: function(config) {
16246         Ext.apply(this, config || {});
16247
16248         /**
16249          * Contains all of the items currently managed
16250          * @property all
16251          * @type Ext.util.MixedCollection
16252          */
16253         this.all = Ext.create('Ext.util.HashMap');
16254
16255         this.types = {};
16256     },
16257
16258     /**
16259      * Returns an item by id.
16260      * For additional details see {@link Ext.util.HashMap#get}.
16261      * @param {String} id The id of the item
16262      * @return {Mixed} The item, <code>undefined</code> if not found.
16263      */
16264     get : function(id) {
16265         return this.all.get(id);
16266     },
16267
16268     /**
16269      * Registers an item to be managed
16270      * @param {Mixed} item The item to register
16271      */
16272     register: function(item) {
16273         this.all.add(item);
16274     },
16275
16276     /**
16277      * Unregisters an item by removing it from this manager
16278      * @param {Mixed} item The item to unregister
16279      */
16280     unregister: function(item) {
16281         this.all.remove(item);
16282     },
16283
16284     /**
16285      * <p>Registers a new item constructor, keyed by a type key.
16286      * @param {String} type The mnemonic string by which the class may be looked up.
16287      * @param {Constructor} cls The new instance class.
16288      */
16289     registerType : function(type, cls) {
16290         this.types[type] = cls;
16291         cls[this.typeName] = type;
16292     },
16293
16294     /**
16295      * Checks if an item type is registered.
16296      * @param {String} type The mnemonic string by which the class may be looked up
16297      * @return {Boolean} Whether the type is registered.
16298      */
16299     isRegistered : function(type){
16300         return this.types[type] !== undefined;
16301     },
16302
16303     /**
16304      * Creates and returns an instance of whatever this manager manages, based on the supplied type and config object
16305      * @param {Object} config The config object
16306      * @param {String} defaultType If no type is discovered in the config object, we fall back to this type
16307      * @return {Mixed} The instance of whatever this manager is managing
16308      */
16309     create: function(config, defaultType) {
16310         var type        = config[this.typeName] || config.type || defaultType,
16311             Constructor = this.types[type];
16312
16313         if (Constructor == undefined) {
16314             Ext.Error.raise("The '" + type + "' type has not been registered with this manager");
16315         }
16316
16317         return new Constructor(config);
16318     },
16319
16320     /**
16321      * Registers a function that will be called when an item with the specified id is added to the manager. This will happen on instantiation.
16322      * @param {String} id The item id
16323      * @param {Function} fn The callback function. Called with a single parameter, the item.
16324      * @param {Object} scope The scope (<code>this</code> reference) in which the callback is executed. Defaults to the item.
16325      */
16326     onAvailable : function(id, fn, scope){
16327         var all = this.all,
16328             item;
16329         
16330         if (all.containsKey(id)) {
16331             item = all.get(id);
16332             fn.call(scope || item, item);
16333         } else {
16334             all.on('add', function(map, key, item){
16335                 if (key == id) {
16336                     fn.call(scope || item, item);
16337                     all.un('add', fn, scope);
16338                 }
16339             });
16340         }
16341     },
16342     
16343     /**
16344      * Executes the specified function once for each item in the collection.
16345      * Returning false from the function will cease iteration.
16346      * 
16347      * The paramaters passed to the function are:
16348      * <div class="mdetail-params"><ul>
16349      * <li><b>key</b> : String<p class="sub-desc">The key of the item</p></li>
16350      * <li><b>value</b> : Number<p class="sub-desc">The value of the item</p></li>
16351      * <li><b>length</b> : Number<p class="sub-desc">The total number of items in the collection</p></li>
16352      * </ul></div>
16353      * @param {Object} fn The function to execute.
16354      * @param {Object} scope The scope to execute in. Defaults to <tt>this</tt>.
16355      */
16356     each: function(fn, scope){
16357         this.all.each(fn, scope || this);    
16358     },
16359     
16360     /**
16361      * Gets the number of items in the collection.
16362      * @return {Number} The number of items in the collection.
16363      */
16364     getCount: function(){
16365         return this.all.getCount();
16366     }
16367 });
16368
16369 /**
16370  * @class Ext.PluginManager
16371  * @extends Ext.AbstractManager
16372  * <p>Provides a registry of available Plugin <i>classes</i> indexed by a mnemonic code known as the Plugin's ptype.
16373  * The <code>{@link Ext.Component#xtype xtype}</code> provides a way to avoid instantiating child Components
16374  * when creating a full, nested config object for a complete Ext page.</p>
16375  * <p>A child Component may be specified simply as a <i>config object</i>
16376  * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component
16377  * needs rendering, the correct type can be looked up for lazy instantiation.</p>
16378  * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p>
16379  * @singleton
16380  */
16381 Ext.define('Ext.PluginManager', {
16382     extend: 'Ext.AbstractManager',
16383     alternateClassName: 'Ext.PluginMgr',
16384     singleton: true,
16385     typeName: 'ptype',
16386
16387     /**
16388      * Creates a new Plugin from the specified config object using the
16389      * config object's ptype to determine the class to instantiate.
16390      * @param {Object} config A configuration object for the Plugin you wish to create.
16391      * @param {Constructor} defaultType The constructor to provide the default Plugin type if
16392      * the config object does not contain a <code>ptype</code>. (Optional if the config contains a <code>ptype</code>).
16393      * @return {Ext.Component} The newly instantiated Plugin.
16394      */
16395     //create: function(plugin, defaultType) {
16396     //    if (plugin instanceof this) {
16397     //        return plugin;
16398     //    } else {
16399     //        var type, config = {};
16400     //
16401     //        if (Ext.isString(plugin)) {
16402     //            type = plugin;
16403     //        }
16404     //        else {
16405     //            type = plugin[this.typeName] || defaultType;
16406     //            config = plugin;
16407     //        }
16408     //
16409     //        return Ext.createByAlias('plugin.' + type, config);
16410     //    }
16411     //},
16412
16413     create : function(config, defaultType){
16414         if (config.init) {
16415             return config;
16416         } else {
16417             return Ext.createByAlias('plugin.' + (config.ptype || defaultType), config);
16418         }
16419         
16420         // Prior system supported Singleton plugins.
16421         //var PluginCls = this.types[config.ptype || defaultType];
16422         //if (PluginCls.init) {
16423         //    return PluginCls;
16424         //} else {
16425         //    return new PluginCls(config);
16426         //}
16427     },
16428
16429     /**
16430      * Returns all plugins registered with the given type. Here, 'type' refers to the type of plugin, not its ptype.
16431      * @param {String} type The type to search for
16432      * @param {Boolean} defaultsOnly True to only return plugins of this type where the plugin's isDefault property is truthy
16433      * @return {Array} All matching plugins
16434      */
16435     findByType: function(type, defaultsOnly) {
16436         var matches = [],
16437             types   = this.types;
16438
16439         for (var name in types) {
16440             if (!types.hasOwnProperty(name)) {
16441                 continue;
16442             }
16443             var item = types[name];
16444
16445             if (item.type == type && (!defaultsOnly || (defaultsOnly === true && item.isDefault))) {
16446                 matches.push(item);
16447             }
16448         }
16449
16450         return matches;
16451     }
16452 }, function() {    
16453     /**
16454      * Shorthand for {@link Ext.PluginManager#registerType}
16455      * @param {String} ptype The ptype mnemonic string by which the Plugin class
16456      * may be looked up.
16457      * @param {Constructor} cls The new Plugin class.
16458      * @member Ext
16459      * @method preg
16460      */
16461     Ext.preg = function() {
16462         return Ext.PluginManager.registerType.apply(Ext.PluginManager, arguments);
16463     };
16464 });
16465
16466 /**
16467  * @class Ext.ComponentManager
16468  * @extends Ext.AbstractManager
16469  * <p>Provides a registry of all Components (instances of {@link Ext.Component} or any subclass
16470  * thereof) on a page so that they can be easily accessed by {@link Ext.Component component}
16471  * {@link Ext.Component#id id} (see {@link #get}, or the convenience method {@link Ext#getCmp Ext.getCmp}).</p>
16472  * <p>This object also provides a registry of available Component <i>classes</i>
16473  * indexed by a mnemonic code known as the Component's {@link Ext.Component#xtype xtype}.
16474  * The <code>xtype</code> provides a way to avoid instantiating child Components
16475  * when creating a full, nested config object for a complete Ext page.</p>
16476  * <p>A child Component may be specified simply as a <i>config object</i>
16477  * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component
16478  * needs rendering, the correct type can be looked up for lazy instantiation.</p>
16479  * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p>
16480  * @singleton
16481  */
16482 Ext.define('Ext.ComponentManager', {
16483     extend: 'Ext.AbstractManager',
16484     alternateClassName: 'Ext.ComponentMgr',
16485     
16486     singleton: true,
16487     
16488     typeName: 'xtype',
16489     
16490     /**
16491      * Creates a new Component from the specified config object using the
16492      * config object's xtype to determine the class to instantiate.
16493      * @param {Object} config A configuration object for the Component you wish to create.
16494      * @param {Constructor} defaultType The constructor to provide the default Component type if
16495      * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
16496      * @return {Ext.Component} The newly instantiated Component.
16497      */
16498     create: function(component, defaultType){
16499         if (component instanceof Ext.AbstractComponent) {
16500             return component;
16501         }
16502         else if (Ext.isString(component)) {
16503             return Ext.createByAlias('widget.' + component);
16504         }
16505         else {
16506             var type = component.xtype || defaultType,
16507                 config = component;
16508             
16509             return Ext.createByAlias('widget.' + type, config);
16510         }
16511     },
16512
16513     registerType: function(type, cls) {
16514         this.types[type] = cls;
16515         cls[this.typeName] = type;
16516         cls.prototype[this.typeName] = type;
16517     }
16518 });
16519 /**
16520  * @class Ext.XTemplate
16521  * @extends Ext.Template
16522  * <p>A template class that supports advanced functionality like:<div class="mdetail-params"><ul>
16523  * <li>Autofilling arrays using templates and sub-templates</li>
16524  * <li>Conditional processing with basic comparison operators</li>
16525  * <li>Basic math function support</li>
16526  * <li>Execute arbitrary inline code with special built-in template variables</li>
16527  * <li>Custom member functions</li>
16528  * <li>Many special tags and built-in operators that aren't defined as part of
16529  * the API, but are supported in the templates that can be created</li>
16530  * </ul></div></p>
16531  * <p>XTemplate provides the templating mechanism built into:<div class="mdetail-params"><ul>
16532  * <li>{@link Ext.view.View}</li>
16533  * </ul></div></p>
16534  *
16535  * The {@link Ext.Template} describes
16536  * the acceptable parameters to pass to the constructor. The following
16537  * examples demonstrate all of the supported features.</p>
16538  *
16539  * <div class="mdetail-params"><ul>
16540  *
16541  * <li><b><u>Sample Data</u></b>
16542  * <div class="sub-desc">
16543  * <p>This is the data object used for reference in each code example:</p>
16544  * <pre><code>
16545 var data = {
16546 name: 'Tommy Maintz',
16547 title: 'Lead Developer',
16548 company: 'Sencha Inc.',
16549 email: 'tommy@sencha.com',
16550 address: '5 Cups Drive',
16551 city: 'Palo Alto',
16552 state: 'CA',
16553 zip: '44102',
16554 drinks: ['Coffee', 'Soda', 'Water'],
16555 kids: [{
16556         name: 'Joshua',
16557         age:3
16558     },{
16559         name: 'Matthew',
16560         age:2
16561     },{
16562         name: 'Solomon',
16563         age:0
16564 }]
16565 };
16566  </code></pre>
16567  * </div>
16568  * </li>
16569  *
16570  *
16571  * <li><b><u>Auto filling of arrays</u></b>
16572  * <div class="sub-desc">
16573  * <p>The <b><tt>tpl</tt></b> tag and the <b><tt>for</tt></b> operator are used
16574  * to process the provided data object:
16575  * <ul>
16576  * <li>If the value specified in <tt>for</tt> is an array, it will auto-fill,
16577  * repeating the template block inside the <tt>tpl</tt> tag for each item in the
16578  * array.</li>
16579  * <li>If <tt>for="."</tt> is specified, the data object provided is examined.</li>
16580  * <li>While processing an array, the special variable <tt>{#}</tt>
16581  * will provide the current array index + 1 (starts at 1, not 0).</li>
16582  * </ul>
16583  * </p>
16584  * <pre><code>
16585 &lt;tpl <b>for</b>=".">...&lt;/tpl>       // loop through array at root node
16586 &lt;tpl <b>for</b>="foo">...&lt;/tpl>     // loop through array at foo node
16587 &lt;tpl <b>for</b>="foo.bar">...&lt;/tpl> // loop through array at foo.bar node
16588  </code></pre>
16589  * Using the sample data above:
16590  * <pre><code>
16591 var tpl = new Ext.XTemplate(
16592     '&lt;p>Kids: ',
16593     '&lt;tpl <b>for</b>=".">',       // process the data.kids node
16594         '&lt;p>{#}. {name}&lt;/p>',  // use current array index to autonumber
16595     '&lt;/tpl>&lt;/p>'
16596 );
16597 tpl.overwrite(panel.body, data.kids); // pass the kids property of the data object
16598  </code></pre>
16599  * <p>An example illustrating how the <b><tt>for</tt></b> property can be leveraged
16600  * to access specified members of the provided data object to populate the template:</p>
16601  * <pre><code>
16602 var tpl = new Ext.XTemplate(
16603     '&lt;p>Name: {name}&lt;/p>',
16604     '&lt;p>Title: {title}&lt;/p>',
16605     '&lt;p>Company: {company}&lt;/p>',
16606     '&lt;p>Kids: ',
16607     '&lt;tpl <b>for="kids"</b>>',     // interrogate the kids property within the data
16608         '&lt;p>{name}&lt;/p>',
16609     '&lt;/tpl>&lt;/p>'
16610 );
16611 tpl.overwrite(panel.body, data);  // pass the root node of the data object
16612  </code></pre>
16613  * <p>Flat arrays that contain values (and not objects) can be auto-rendered
16614  * using the special <b><tt>{.}</tt></b> variable inside a loop.  This variable
16615  * will represent the value of the array at the current index:</p>
16616  * <pre><code>
16617 var tpl = new Ext.XTemplate(
16618     '&lt;p>{name}\&#39;s favorite beverages:&lt;/p>',
16619     '&lt;tpl for="drinks">',
16620         '&lt;div> - {.}&lt;/div>',
16621     '&lt;/tpl>'
16622 );
16623 tpl.overwrite(panel.body, data);
16624  </code></pre>
16625  * <p>When processing a sub-template, for example while looping through a child array,
16626  * you can access the parent object's members via the <b><tt>parent</tt></b> object:</p>
16627  * <pre><code>
16628 var tpl = new Ext.XTemplate(
16629     '&lt;p>Name: {name}&lt;/p>',
16630     '&lt;p>Kids: ',
16631     '&lt;tpl for="kids">',
16632         '&lt;tpl if="age &amp;gt; 1">',
16633             '&lt;p>{name}&lt;/p>',
16634             '&lt;p>Dad: {<b>parent</b>.name}&lt;/p>',
16635         '&lt;/tpl>',
16636     '&lt;/tpl>&lt;/p>'
16637 );
16638 tpl.overwrite(panel.body, data);
16639  </code></pre>
16640  * </div>
16641  * </li>
16642  *
16643  *
16644  * <li><b><u>Conditional processing with basic comparison operators</u></b>
16645  * <div class="sub-desc">
16646  * <p>The <b><tt>tpl</tt></b> tag and the <b><tt>if</tt></b> operator are used
16647  * to provide conditional checks for deciding whether or not to render specific
16648  * parts of the template. Notes:<div class="sub-desc"><ul>
16649  * <li>Double quotes must be encoded if used within the conditional</li>
16650  * <li>There is no <tt>else</tt> operator &mdash; if needed, two opposite
16651  * <tt>if</tt> statements should be used.</li>
16652  * </ul></div>
16653  * <pre><code>
16654 &lt;tpl if="age &gt; 1 &amp;&amp; age &lt; 10">Child&lt;/tpl>
16655 &lt;tpl if="age >= 10 && age < 18">Teenager&lt;/tpl>
16656 &lt;tpl <b>if</b>="this.isGirl(name)">...&lt;/tpl>
16657 &lt;tpl <b>if</b>="id==\'download\'">...&lt;/tpl>
16658 &lt;tpl <b>if</b>="needsIcon">&lt;img src="{icon}" class="{iconCls}"/>&lt;/tpl>
16659 // no good:
16660 &lt;tpl if="name == "Tommy"">Hello&lt;/tpl>
16661 // encode &#34; if it is part of the condition, e.g.
16662 &lt;tpl if="name == &#38;quot;Tommy&#38;quot;">Hello&lt;/tpl>
16663  * </code></pre>
16664  * Using the sample data above:
16665  * <pre><code>
16666 var tpl = new Ext.XTemplate(
16667     '&lt;p>Name: {name}&lt;/p>',
16668     '&lt;p>Kids: ',
16669     '&lt;tpl for="kids">',
16670         '&lt;tpl if="age &amp;gt; 1">',
16671             '&lt;p>{name}&lt;/p>',
16672         '&lt;/tpl>',
16673     '&lt;/tpl>&lt;/p>'
16674 );
16675 tpl.overwrite(panel.body, data);
16676  </code></pre>
16677  * </div>
16678  * </li>
16679  *
16680  *
16681  * <li><b><u>Basic math support</u></b>
16682  * <div class="sub-desc">
16683  * <p>The following basic math operators may be applied directly on numeric
16684  * data values:</p><pre>
16685  * + - * /
16686  * </pre>
16687  * For example:
16688  * <pre><code>
16689 var tpl = new Ext.XTemplate(
16690     '&lt;p>Name: {name}&lt;/p>',
16691     '&lt;p>Kids: ',
16692     '&lt;tpl for="kids">',
16693         '&lt;tpl if="age &amp;gt; 1">',  // <-- Note that the &gt; is encoded
16694             '&lt;p>{#}: {name}&lt;/p>',  // <-- Auto-number each item
16695             '&lt;p>In 5 Years: {age+5}&lt;/p>',  // <-- Basic math
16696             '&lt;p>Dad: {parent.name}&lt;/p>',
16697         '&lt;/tpl>',
16698     '&lt;/tpl>&lt;/p>'
16699 );
16700 tpl.overwrite(panel.body, data);
16701  </code></pre>
16702  * </div>
16703  * </li>
16704  *
16705  *
16706  * <li><b><u>Execute arbitrary inline code with special built-in template variables</u></b>
16707  * <div class="sub-desc">
16708  * <p>Anything between <code>{[ ... ]}</code> is considered code to be executed
16709  * in the scope of the template. There are some special variables available in that code:
16710  * <ul>
16711  * <li><b><tt>values</tt></b>: The values in the current scope. If you are using
16712  * scope changing sub-templates, you can change what <tt>values</tt> is.</li>
16713  * <li><b><tt>parent</tt></b>: The scope (values) of the ancestor template.</li>
16714  * <li><b><tt>xindex</tt></b>: If you are in a looping template, the index of the
16715  * loop you are in (1-based).</li>
16716  * <li><b><tt>xcount</tt></b>: If you are in a looping template, the total length
16717  * of the array you are looping.</li>
16718  * </ul>
16719  * This example demonstrates basic row striping using an inline code block and the
16720  * <tt>xindex</tt> variable:</p>
16721  * <pre><code>
16722 var tpl = new Ext.XTemplate(
16723     '&lt;p>Name: {name}&lt;/p>',
16724     '&lt;p>Company: {[values.company.toUpperCase() + ", " + values.title]}&lt;/p>',
16725     '&lt;p>Kids: ',
16726     '&lt;tpl for="kids">',
16727         '&lt;div class="{[xindex % 2 === 0 ? "even" : "odd"]}">',
16728         '{name}',
16729         '&lt;/div>',
16730     '&lt;/tpl>&lt;/p>'
16731  );
16732 tpl.overwrite(panel.body, data);
16733  </code></pre>
16734  * </div>
16735  * </li>
16736  *
16737  * <li><b><u>Template member functions</u></b>
16738  * <div class="sub-desc">
16739  * <p>One or more member functions can be specified in a configuration
16740  * object passed into the XTemplate constructor for more complex processing:</p>
16741  * <pre><code>
16742 var tpl = new Ext.XTemplate(
16743     '&lt;p>Name: {name}&lt;/p>',
16744     '&lt;p>Kids: ',
16745     '&lt;tpl for="kids">',
16746         '&lt;tpl if="this.isGirl(name)">',
16747             '&lt;p>Girl: {name} - {age}&lt;/p>',
16748         '&lt;/tpl>',
16749          // use opposite if statement to simulate 'else' processing:
16750         '&lt;tpl if="this.isGirl(name) == false">',
16751             '&lt;p>Boy: {name} - {age}&lt;/p>',
16752         '&lt;/tpl>',
16753         '&lt;tpl if="this.isBaby(age)">',
16754             '&lt;p>{name} is a baby!&lt;/p>',
16755         '&lt;/tpl>',
16756     '&lt;/tpl>&lt;/p>',
16757     {
16758         // XTemplate configuration:
16759         compiled: true,
16760         // member functions:
16761         isGirl: function(name){
16762            return name == 'Sara Grace';
16763         },
16764         isBaby: function(age){
16765            return age < 1;
16766         }
16767     }
16768 );
16769 tpl.overwrite(panel.body, data);
16770  </code></pre>
16771  * </div>
16772  * </li>
16773  *
16774  * </ul></div>
16775  *
16776  * @param {Mixed} config
16777  */
16778
16779 Ext.define('Ext.XTemplate', {
16780
16781     /* Begin Definitions */
16782
16783     extend: 'Ext.Template',
16784
16785     statics: {
16786         /**
16787          * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
16788          * @param {String/HTMLElement} el A DOM element or its id
16789          * @return {Ext.Template} The created template
16790          * @static
16791          */
16792         from: function(el, config) {
16793             el = Ext.getDom(el);
16794             return new this(el.value || el.innerHTML, config || {});
16795         }
16796     },
16797
16798     
16799
16800     argsRe: /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
16801     nameRe: /^<tpl\b[^>]*?for="(.*?)"/,
16802     ifRe: /^<tpl\b[^>]*?if="(.*?)"/,
16803     execRe: /^<tpl\b[^>]*?exec="(.*?)"/,
16804     constructor: function() {
16805         this.callParent(arguments);
16806
16807         var me = this,
16808             html = me.html,
16809             argsRe = me.argsRe,
16810             nameRe = me.nameRe,
16811             ifRe = me.ifRe,
16812             execRe = me.execRe,
16813             id = 0,
16814             tpls = [],
16815             VALUES = 'values',
16816             PARENT = 'parent',
16817             XINDEX = 'xindex',
16818             XCOUNT = 'xcount',
16819             RETURN = 'return ',
16820             WITHVALUES = 'with(values){ ',
16821             m, matchName, matchIf, matchExec, exp, fn, exec, name, i;
16822
16823         html = ['<tpl>', html, '</tpl>'].join('');
16824
16825         while ((m = html.match(argsRe))) {
16826             exp = null;
16827             fn = null;
16828             exec = null;
16829             matchName = m[0].match(nameRe);
16830             matchIf = m[0].match(ifRe);
16831             matchExec = m[0].match(execRe);
16832
16833             exp = matchIf ? matchIf[1] : null;
16834             if (exp) {
16835                 fn = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + 'try{' + RETURN + Ext.String.htmlDecode(exp) + ';}catch(e){return;}}');
16836             }
16837
16838             exp = matchExec ? matchExec[1] : null;
16839             if (exp) {
16840                 exec = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + Ext.String.htmlDecode(exp) + ';}');
16841             }
16842
16843             name = matchName ? matchName[1] : null;
16844             if (name) {
16845                 if (name === '.') {
16846                     name = VALUES;
16847                 } else if (name === '..') {
16848                     name = PARENT;
16849                 }
16850                 name = Ext.functionFactory(VALUES, PARENT, 'try{' + WITHVALUES + RETURN + name + ';}}catch(e){return;}');
16851             }
16852
16853             tpls.push({
16854                 id: id,
16855                 target: name,
16856                 exec: exec,
16857                 test: fn,
16858                 body: m[1] || ''
16859             });
16860
16861             html = html.replace(m[0], '{xtpl' + id + '}');
16862             id = id + 1;
16863         }
16864
16865         for (i = tpls.length - 1; i >= 0; --i) {
16866             me.compileTpl(tpls[i]);
16867         }
16868         me.master = tpls[tpls.length - 1];
16869         me.tpls = tpls;
16870     },
16871
16872     
16873     applySubTemplate: function(id, values, parent, xindex, xcount) {
16874         var me = this, t = me.tpls[id];
16875         return t.compiled.call(me, values, parent, xindex, xcount);
16876     },
16877     
16878     codeRe: /\{\[((?:\\\]|.|\n)*?)\]\}/g,
16879
16880     re: /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\/]\s?[\d\.\+\-\*\/\(\)]+)?\}/g,
16881
16882     
16883     compileTpl: function(tpl) {
16884         var fm = Ext.util.Format,
16885             me = this,
16886             useFormat = me.disableFormats !== true,
16887             body, bodyReturn, evaluatedFn;
16888
16889         function fn(m, name, format, args, math) {
16890             var v;
16891             
16892             
16893             if (name.substr(0, 4) == 'xtpl') {
16894                 return "',this.applySubTemplate(" + name.substr(4) + ", values, parent, xindex, xcount),'";
16895             }
16896             
16897             if (name == '.') {
16898                 
16899                 v = 'Ext.Array.indexOf(["string", "number", "boolean"], typeof values) > -1 || Ext.isDate(values) ? values : ""';
16900             }
16901
16902             
16903             else if (name == '#') {
16904                 v = 'xindex';
16905             }
16906             else if (name.substr(0, 7) == "parent.") {
16907                 v = name;
16908             }
16909             
16910             else if (name.indexOf('.') != -1) {
16911                 v = "values." + name;
16912             }
16913
16914             
16915             else {
16916                 v = "values['" + name + "']";
16917             }
16918             if (math) {
16919                 v = '(' + v + math + ')';
16920             }
16921             if (format && useFormat) {
16922                 args = args ? ',' + args : "";
16923                 if (format.substr(0, 5) != "this.") {
16924                     format = "fm." + format + '(';
16925                 }
16926                 else {
16927                     format = 'this.' + format.substr(5) + '(';
16928                 }
16929             }
16930             else {
16931                 args = '';
16932                 format = "(" + v + " === undefined ? '' : ";
16933             }
16934             return "'," + format + v + args + "),'";
16935         }
16936
16937         function codeFn(m, code) {
16938             
16939             return "',(" + code.replace(me.compileARe, "'") + "),'";
16940         }
16941
16942         bodyReturn = tpl.body.replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn).replace(me.codeRe, codeFn);
16943         body = "evaluatedFn = function(values, parent, xindex, xcount){return ['" + bodyReturn + "'].join('');};";
16944         eval(body);
16945
16946         tpl.compiled = function(values, parent, xindex, xcount) {
16947             var vs,
16948                 length,
16949                 buffer,
16950                 i;
16951
16952             if (tpl.test && !tpl.test.call(me, values, parent, xindex, xcount)) {
16953                 return '';
16954             }
16955
16956             vs = tpl.target ? tpl.target.call(me, values, parent) : values;
16957             if (!vs) {
16958                return '';
16959             }
16960
16961             parent = tpl.target ? values : parent;
16962             if (tpl.target && Ext.isArray(vs)) {
16963                 buffer = [];
16964                 length = vs.length;
16965                 if (tpl.exec) {
16966                     for (i = 0; i < length; i++) {
16967                         buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
16968                         tpl.exec.call(me, vs[i], parent, i + 1, length);
16969                     }
16970                 } else {
16971                     for (i = 0; i < length; i++) {
16972                         buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
16973                     }
16974                 }
16975                 return buffer.join('');
16976             }
16977
16978             if (tpl.exec) {
16979                 tpl.exec.call(me, vs, parent, xindex, xcount);
16980             }
16981             return evaluatedFn.call(me, vs, parent, xindex, xcount);
16982         };
16983
16984         return this;
16985     },
16986
16987     
16988     applyTemplate: function(values) {
16989         return this.master.compiled.call(this, values, {}, 1, 1);
16990     },
16991
16992     
16993     compile: function() {
16994         return this;
16995     }
16996 }, function() {
16997     
16998     this.createAlias('apply', 'applyTemplate');
16999 });
17000
17001
17002 Ext.define('Ext.util.AbstractMixedCollection', {
17003     requires: ['Ext.util.Filter'],
17004     
17005     mixins: {
17006         observable: 'Ext.util.Observable'
17007     },
17008
17009     constructor: function(allowFunctions, keyFn) {
17010         var me = this;
17011
17012         me.items = [];
17013         me.map = {};
17014         me.keys = [];
17015         me.length = 0;
17016
17017         me.addEvents(
17018             
17019             'clear',
17020
17021             
17022             'add',
17023
17024             
17025             'replace',
17026
17027             
17028             'remove'
17029         );
17030
17031         me.allowFunctions = allowFunctions === true;
17032
17033         if (keyFn) {
17034             me.getKey = keyFn;
17035         }
17036
17037         me.mixins.observable.constructor.call(me);
17038     },
17039     
17040     
17041     allowFunctions : false,
17042
17043     
17044     add : function(key, obj){
17045         var me = this,
17046             myObj = obj,
17047             myKey = key,
17048             old;
17049
17050         if (arguments.length == 1) {
17051             myObj = myKey;
17052             myKey = me.getKey(myObj);
17053         }
17054         if (typeof myKey != 'undefined' && myKey !== null) {
17055             old = me.map[myKey];
17056             if (typeof old != 'undefined') {
17057                 return me.replace(myKey, myObj);
17058             }
17059             me.map[myKey] = myObj;
17060         }
17061         me.length++;
17062         me.items.push(myObj);
17063         me.keys.push(myKey);
17064         me.fireEvent('add', me.length - 1, myObj, myKey);
17065         return myObj;
17066     },
17067
17068     
17069     getKey : function(o){
17070          return o.id;
17071     },
17072
17073     
17074     replace : function(key, o){
17075         var me = this,
17076             old,
17077             index;
17078
17079         if (arguments.length == 1) {
17080             o = arguments[0];
17081             key = me.getKey(o);
17082         }
17083         old = me.map[key];
17084         if (typeof key == 'undefined' || key === null || typeof old == 'undefined') {
17085              return me.add(key, o);
17086         }
17087         index = me.indexOfKey(key);
17088         me.items[index] = o;
17089         me.map[key] = o;
17090         me.fireEvent('replace', key, old, o);
17091         return o;
17092     },
17093
17094     
17095     addAll : function(objs){
17096         var me = this,
17097             i = 0,
17098             args,
17099             len,
17100             key;
17101
17102         if (arguments.length > 1 || Ext.isArray(objs)) {
17103             args = arguments.length > 1 ? arguments : objs;
17104             for (len = args.length; i < len; i++) {
17105                 me.add(args[i]);
17106             }
17107         } else {
17108             for (key in objs) {
17109                 if (objs.hasOwnProperty(key)) {
17110                     if (me.allowFunctions || typeof objs[key] != 'function') {
17111                         me.add(key, objs[key]);
17112                     }
17113                 }
17114             }
17115         }
17116     },
17117
17118     
17119     each : function(fn, scope){
17120         var items = [].concat(this.items), 
17121             i = 0,
17122             len = items.length,
17123             item;
17124
17125         for (; i < len; i++) {
17126             item = items[i];
17127             if (fn.call(scope || item, item, i, len) === false) {
17128                 break;
17129             }
17130         }
17131     },
17132
17133     
17134     eachKey : function(fn, scope){
17135         var keys = this.keys,
17136             items = this.items,
17137             i = 0,
17138             len = keys.length;
17139
17140         for (; i < len; i++) {
17141             fn.call(scope || window, keys[i], items[i], i, len);
17142         }
17143     },
17144
17145     
17146     findBy : function(fn, scope) {
17147         var keys = this.keys,
17148             items = this.items,
17149             i = 0,
17150             len = items.length;
17151
17152         for (; i < len; i++) {
17153             if (fn.call(scope || window, items[i], keys[i])) {
17154                 return items[i];
17155             }
17156         }
17157         return null;
17158     },
17159
17160     find : function() {
17161         if (Ext.isDefined(Ext.global.console)) {
17162             Ext.global.console.warn('Ext.util.MixedCollection: find has been deprecated. Use findBy instead.');
17163         }
17164         return this.findBy.apply(this, arguments);
17165     },
17166
17167     
17168     insert : function(index, key, obj){
17169         var me = this,
17170             myKey = key,
17171             myObj = obj;
17172
17173         if (arguments.length == 2) {
17174             myObj = myKey;
17175             myKey = me.getKey(myObj);
17176         }
17177         if (me.containsKey(myKey)) {
17178             me.suspendEvents();
17179             me.removeAtKey(myKey);
17180             me.resumeEvents();
17181         }
17182         if (index >= me.length) {
17183             return me.add(myKey, myObj);
17184         }
17185         me.length++;
17186         me.items.splice(index, 0, myObj);
17187         if (typeof myKey != 'undefined' && myKey !== null) {
17188             me.map[myKey] = myObj;
17189         }
17190         me.keys.splice(index, 0, myKey);
17191         me.fireEvent('add', index, myObj, myKey);
17192         return myObj;
17193     },
17194
17195     
17196     remove : function(o){
17197         return this.removeAt(this.indexOf(o));
17198     },
17199
17200     
17201     removeAll : function(items){
17202         Ext.each(items || [], function(item) {
17203             this.remove(item);
17204         }, this);
17205
17206         return this;
17207     },
17208
17209     
17210     removeAt : function(index){
17211         var me = this,
17212             o,
17213             key;
17214
17215         if (index < me.length && index >= 0) {
17216             me.length--;
17217             o = me.items[index];
17218             me.items.splice(index, 1);
17219             key = me.keys[index];
17220             if (typeof key != 'undefined') {
17221                 delete me.map[key];
17222             }
17223             me.keys.splice(index, 1);
17224             me.fireEvent('remove', o, key);
17225             return o;
17226         }
17227         return false;
17228     },
17229
17230     
17231     removeAtKey : function(key){
17232         return this.removeAt(this.indexOfKey(key));
17233     },
17234
17235     
17236     getCount : function(){
17237         return this.length;
17238     },
17239
17240     
17241     indexOf : function(o){
17242         return Ext.Array.indexOf(this.items, o);
17243     },
17244
17245     
17246     indexOfKey : function(key){
17247         return Ext.Array.indexOf(this.keys, key);
17248     },
17249
17250     
17251     get : function(key) {
17252         var me = this,
17253             mk = me.map[key],
17254             item = mk !== undefined ? mk : (typeof key == 'number') ? me.items[key] : undefined;
17255         return typeof item != 'function' || me.allowFunctions ? item : null; 
17256     },
17257
17258     
17259     getAt : function(index) {
17260         return this.items[index];
17261     },
17262
17263     
17264     getByKey : function(key) {
17265         return this.map[key];
17266     },
17267
17268     
17269     contains : function(o){
17270         return Ext.Array.contains(this.items, o);
17271     },
17272
17273     
17274     containsKey : function(key){
17275         return typeof this.map[key] != 'undefined';
17276     },
17277
17278     
17279     clear : function(){
17280         var me = this;
17281
17282         me.length = 0;
17283         me.items = [];
17284         me.keys = [];
17285         me.map = {};
17286         me.fireEvent('clear');
17287     },
17288
17289     
17290     first : function() {
17291         return this.items[0];
17292     },
17293
17294     
17295     last : function() {
17296         return this.items[this.length - 1];
17297     },
17298
17299     
17300     sum: function(property, root, start, end) {
17301         var values = this.extractValues(property, root),
17302             length = values.length,
17303             sum    = 0,
17304             i;
17305
17306         start = start || 0;
17307         end   = (end || end === 0) ? end : length - 1;
17308
17309         for (i = start; i <= end; i++) {
17310             sum += values[i];
17311         }
17312
17313         return sum;
17314     },
17315
17316     
17317     collect: function(property, root, allowNull) {
17318         var values = this.extractValues(property, root),
17319             length = values.length,
17320             hits   = {},
17321             unique = [],
17322             value, strValue, i;
17323
17324         for (i = 0; i < length; i++) {
17325             value = values[i];
17326             strValue = String(value);
17327
17328             if ((allowNull || !Ext.isEmpty(value)) && !hits[strValue]) {
17329                 hits[strValue] = true;
17330                 unique.push(value);
17331             }
17332         }
17333
17334         return unique;
17335     },
17336
17337     
17338     extractValues: function(property, root) {
17339         var values = this.items;
17340
17341         if (root) {
17342             values = Ext.Array.pluck(values, root);
17343         }
17344
17345         return Ext.Array.pluck(values, property);
17346     },
17347
17348     
17349     getRange : function(start, end){
17350         var me = this,
17351             items = me.items,
17352             range = [],
17353             i;
17354
17355         if (items.length < 1) {
17356             return range;
17357         }
17358
17359         start = start || 0;
17360         end = Math.min(typeof end == 'undefined' ? me.length - 1 : end, me.length - 1);
17361         if (start <= end) {
17362             for (i = start; i <= end; i++) {
17363                 range[range.length] = items[i];
17364             }
17365         } else {
17366             for (i = start; i >= end; i--) {
17367                 range[range.length] = items[i];
17368             }
17369         }
17370         return range;
17371     },
17372
17373     
17374     filter : function(property, value, anyMatch, caseSensitive) {
17375         var filters = [],
17376             filterFn;
17377
17378         
17379         if (Ext.isString(property)) {
17380             filters.push(Ext.create('Ext.util.Filter', {
17381                 property     : property,
17382                 value        : value,
17383                 anyMatch     : anyMatch,
17384                 caseSensitive: caseSensitive
17385             }));
17386         } else if (Ext.isArray(property) || property instanceof Ext.util.Filter) {
17387             filters = filters.concat(property);
17388         }
17389
17390         
17391         
17392         filterFn = function(record) {
17393             var isMatch = true,
17394                 length = filters.length,
17395                 i;
17396
17397             for (i = 0; i < length; i++) {
17398                 var filter = filters[i],
17399                     fn     = filter.filterFn,
17400                     scope  = filter.scope;
17401
17402                 isMatch = isMatch && fn.call(scope, record);
17403             }
17404
17405             return isMatch;
17406         };
17407
17408         return this.filterBy(filterFn);
17409     },
17410
17411     
17412     filterBy : function(fn, scope) {
17413         var me = this,
17414             newMC  = new this.self(),
17415             keys   = me.keys,
17416             items  = me.items,
17417             length = items.length,
17418             i;
17419
17420         newMC.getKey = me.getKey;
17421
17422         for (i = 0; i < length; i++) {
17423             if (fn.call(scope || me, items[i], keys[i])) {
17424                 newMC.add(keys[i], items[i]);
17425             }
17426         }
17427
17428         return newMC;
17429     },
17430
17431     
17432     findIndex : function(property, value, start, anyMatch, caseSensitive){
17433         if(Ext.isEmpty(value, false)){
17434             return -1;
17435         }
17436         value = this.createValueMatcher(value, anyMatch, caseSensitive);
17437         return this.findIndexBy(function(o){
17438             return o && value.test(o[property]);
17439         }, null, start);
17440     },
17441
17442     
17443     findIndexBy : function(fn, scope, start){
17444         var me = this,
17445             keys = me.keys,
17446             items = me.items,
17447             i = start || 0,
17448             len = items.length;
17449
17450         for (; i < len; i++) {
17451             if (fn.call(scope || me, items[i], keys[i])) {
17452                 return i;
17453             }
17454         }
17455         return -1;
17456     },
17457
17458     
17459     createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
17460         if (!value.exec) { 
17461             var er = Ext.String.escapeRegex;
17462             value = String(value);
17463
17464             if (anyMatch === true) {
17465                 value = er(value);
17466             } else {
17467                 value = '^' + er(value);
17468                 if (exactMatch === true) {
17469                     value += '$';
17470                 }
17471             }
17472             value = new RegExp(value, caseSensitive ? '' : 'i');
17473         }
17474         return value;
17475     },
17476
17477     
17478     clone : function() {
17479         var me = this,
17480             copy = new this.self(),
17481             keys = me.keys,
17482             items = me.items,
17483             i = 0,
17484             len = items.length;
17485
17486         for(; i < len; i++){
17487             copy.add(keys[i], items[i]);
17488         }
17489         copy.getKey = me.getKey;
17490         return copy;
17491     }
17492 });
17493
17494
17495 Ext.define("Ext.util.Sortable", {
17496     
17497     isSortable: true,
17498     
17499     
17500     defaultSortDirection: "ASC",
17501     
17502     requires: [
17503         'Ext.util.Sorter'
17504     ],
17505
17506         
17507     sortRoot: null,
17508     
17509     
17510     initSortable: function() {
17511         var me = this,
17512             sorters = me.sorters;
17513         
17514         
17515         me.sorters = Ext.create('Ext.util.AbstractMixedCollection', false, function(item) {
17516             return item.id || item.property;
17517         });
17518         
17519         if (sorters) {
17520             me.sorters.addAll(me.decodeSorters(sorters));
17521         }
17522     },
17523
17524     
17525     sort: function(sorters, direction, where, doSort) {
17526         var me = this,
17527             sorter, sorterFn,
17528             newSorters;
17529         
17530         if (Ext.isArray(sorters)) {
17531             doSort = where;
17532             where = direction;
17533             newSorters = sorters;
17534         }
17535         else if (Ext.isObject(sorters)) {
17536             doSort = where;
17537             where = direction;
17538             newSorters = [sorters];
17539         }
17540         else if (Ext.isString(sorters)) {
17541             sorter = me.sorters.get(sorters);
17542
17543             if (!sorter) {
17544                 sorter = {
17545                     property : sorters,
17546                     direction: direction
17547                 };
17548                 newSorters = [sorter];
17549             }
17550             else if (direction === undefined) {
17551                 sorter.toggle();
17552             }
17553             else {
17554                 sorter.setDirection(direction);
17555             }
17556         }
17557         
17558         if (newSorters && newSorters.length) {
17559             newSorters = me.decodeSorters(newSorters);
17560             if (Ext.isString(where)) {
17561                 if (where === 'prepend') {
17562                     sorters = me.sorters.clone().items;
17563                     
17564                     me.sorters.clear();
17565                     me.sorters.addAll(newSorters);
17566                     me.sorters.addAll(sorters);
17567                 }
17568                 else {
17569                     me.sorters.addAll(newSorters);
17570                 }
17571             }
17572             else {
17573                 me.sorters.clear();
17574                 me.sorters.addAll(newSorters);
17575             }
17576             
17577             if (doSort !== false) {
17578                 me.onBeforeSort(newSorters);
17579             }
17580         }
17581         
17582         if (doSort !== false) {
17583             sorters = me.sorters.items;
17584             if (sorters.length) {
17585                 
17586                 sorterFn = function(r1, r2) {
17587                     var result = sorters[0].sort(r1, r2),
17588                         length = sorters.length,
17589                         i;
17590
17591                         
17592                         for (i = 1; i < length; i++) {
17593                             result = result || sorters[i].sort.call(this, r1, r2);
17594                         }
17595
17596                     return result;
17597                 };
17598
17599                 me.doSort(sorterFn);                
17600             }
17601         }
17602         
17603         return sorters;
17604     },
17605     
17606     onBeforeSort: Ext.emptyFn,
17607         
17608     
17609     decodeSorters: function(sorters) {
17610         if (!Ext.isArray(sorters)) {
17611             if (sorters === undefined) {
17612                 sorters = [];
17613             } else {
17614                 sorters = [sorters];
17615             }
17616         }
17617
17618         var length = sorters.length,
17619             Sorter = Ext.util.Sorter,
17620             fields = this.model ? this.model.prototype.fields : null,
17621             field,
17622             config, i;
17623
17624         for (i = 0; i < length; i++) {
17625             config = sorters[i];
17626
17627             if (!(config instanceof Sorter)) {
17628                 if (Ext.isString(config)) {
17629                     config = {
17630                         property: config
17631                     };
17632                 }
17633                 
17634                 Ext.applyIf(config, {
17635                     root     : this.sortRoot,
17636                     direction: "ASC"
17637                 });
17638
17639                 
17640                 if (config.fn) {
17641                     config.sorterFn = config.fn;
17642                 }
17643
17644                 
17645                 if (typeof config == 'function') {
17646                     config = {
17647                         sorterFn: config
17648                     };
17649                 }
17650
17651                 
17652                 if (fields && !config.transform) {
17653                     field = fields.get(config.property);
17654                     config.transform = field ? field.sortType : undefined;
17655                 }
17656                 sorters[i] = Ext.create('Ext.util.Sorter', config);
17657             }
17658         }
17659
17660         return sorters;
17661     },
17662     
17663     getSorters: function() {
17664         return this.sorters.items;
17665     },
17666     
17667     
17668     getSortState : function() {
17669         return this.sortInfo;
17670     }
17671 });
17672
17673 Ext.define('Ext.util.MixedCollection', {
17674     extend: 'Ext.util.AbstractMixedCollection',
17675     mixins: {
17676         sortable: 'Ext.util.Sortable'
17677     },
17678
17679     constructor: function() {
17680         var me = this;
17681         me.callParent(arguments);
17682         me.addEvents('sort');
17683         me.mixins.sortable.initSortable.call(me);
17684     },
17685
17686     doSort: function(sorterFn) {
17687         this.sortBy(sorterFn);
17688     },
17689
17690     
17691     _sort : function(property, dir, fn){
17692         var me = this,
17693             i, len,
17694             dsc   = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
17695
17696             
17697             c     = [],
17698             keys  = me.keys,
17699             items = me.items;
17700
17701         
17702         fn = fn || function(a, b) {
17703             return a - b;
17704         };
17705
17706         
17707         for(i = 0, len = items.length; i < len; i++){
17708             c[c.length] = {
17709                 key  : keys[i],
17710                 value: items[i],
17711                 index: i
17712             };
17713         }
17714
17715         
17716         Ext.Array.sort(c, function(a, b){
17717             var v = fn(a[property], b[property]) * dsc;
17718             if(v === 0){
17719                 v = (a.index < b.index ? -1 : 1);
17720             }
17721             return v;
17722         });
17723
17724         
17725         for(i = 0, len = c.length; i < len; i++){
17726             items[i] = c[i].value;
17727             keys[i]  = c[i].key;
17728         }
17729
17730         me.fireEvent('sort', me);
17731     },
17732
17733     
17734     sortBy: function(sorterFn) {
17735         var me     = this,
17736             items  = me.items,
17737             keys   = me.keys,
17738             length = items.length,
17739             temp   = [],
17740             i;
17741
17742         
17743         for (i = 0; i < length; i++) {
17744             temp[i] = {
17745                 key  : keys[i],
17746                 value: items[i],
17747                 index: i
17748             };
17749         }
17750
17751         Ext.Array.sort(temp, function(a, b) {
17752             var v = sorterFn(a.value, b.value);
17753             if (v === 0) {
17754                 v = (a.index < b.index ? -1 : 1);
17755             }
17756
17757             return v;
17758         });
17759
17760         
17761         for (i = 0; i < length; i++) {
17762             items[i] = temp[i].value;
17763             keys[i]  = temp[i].key;
17764         }
17765         
17766         me.fireEvent('sort', me, items, keys);
17767     },
17768
17769     
17770     reorder: function(mapping) {
17771         var me = this,
17772             items = me.items,
17773             index = 0,
17774             length = items.length,
17775             order = [],
17776             remaining = [],
17777             oldIndex;
17778
17779         me.suspendEvents();
17780
17781         
17782         for (oldIndex in mapping) {
17783             order[mapping[oldIndex]] = items[oldIndex];
17784         }
17785
17786         for (index = 0; index < length; index++) {
17787             if (mapping[index] == undefined) {
17788                 remaining.push(items[index]);
17789             }
17790         }
17791
17792         for (index = 0; index < length; index++) {
17793             if (order[index] == undefined) {
17794                 order[index] = remaining.shift();
17795             }
17796         }
17797
17798         me.clear();
17799         me.addAll(order);
17800
17801         me.resumeEvents();
17802         me.fireEvent('sort', me);
17803     },
17804
17805     
17806     sortByKey : function(dir, fn){
17807         this._sort('key', dir, fn || function(a, b){
17808             var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
17809             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
17810         });
17811     }
17812 });
17813
17814
17815 Ext.define('Ext.data.StoreManager', {
17816     extend: 'Ext.util.MixedCollection',
17817     alternateClassName: ['Ext.StoreMgr', 'Ext.data.StoreMgr', 'Ext.StoreManager'],
17818     singleton: true,
17819     uses: ['Ext.data.ArrayStore'],
17820     
17821     
17822
17823     
17824     register : function() {
17825         for (var i = 0, s; (s = arguments[i]); i++) {
17826             this.add(s);
17827         }
17828     },
17829
17830     
17831     unregister : function() {
17832         for (var i = 0, s; (s = arguments[i]); i++) {
17833             this.remove(this.lookup(s));
17834         }
17835     },
17836
17837     
17838     lookup : function(store) {
17839         
17840         if (Ext.isArray(store)) {
17841             var fields = ['field1'], 
17842                 expand = !Ext.isArray(store[0]),
17843                 data = store,
17844                 i,
17845                 len;
17846                 
17847             if(expand){
17848                 data = [];
17849                 for (i = 0, len = store.length; i < len; ++i) {
17850                     data.push([store[i]]);
17851                 }
17852             } else {
17853                 for(i = 2, len = store[0].length; i <= len; ++i){
17854                     fields.push('field' + i);
17855                 }
17856             }
17857             return Ext.create('Ext.data.ArrayStore', {
17858                 data  : data,
17859                 fields: fields,
17860                 autoDestroy: true,
17861                 autoCreated: true,
17862                 expanded: expand
17863             });
17864         }
17865         
17866         if (Ext.isString(store)) {
17867             
17868             return this.get(store);
17869         } else {
17870             
17871             return Ext.data.AbstractStore.create(store);
17872         }
17873     },
17874
17875     
17876     getKey : function(o) {
17877          return o.storeId;
17878     }
17879 }, function() {    
17880     
17881     Ext.regStore = function(name, config) {
17882         var store;
17883
17884         if (Ext.isObject(name)) {
17885             config = name;
17886         } else {
17887             config.storeId = name;
17888         }
17889
17890         if (config instanceof Ext.data.Store) {
17891             store = config;
17892         } else {
17893             store = Ext.create('Ext.data.Store', config);
17894         }
17895
17896         return Ext.data.StoreManager.register(store);
17897     };
17898
17899     
17900     Ext.getStore = function(name) {
17901         return Ext.data.StoreManager.lookup(name);
17902     };
17903 });
17904
17905
17906
17907 Ext.define('Ext.LoadMask', {
17908
17909     
17910
17911     mixins: {
17912         observable: 'Ext.util.Observable'
17913     },
17914
17915     requires: ['Ext.data.StoreManager'],
17916
17917     
17918
17919     
17920
17921     
17922     msg : 'Loading...',
17923     
17924     msgCls : Ext.baseCSSPrefix + 'mask-loading',
17925     
17926     
17927     useMsg: true,
17928
17929     
17930     disabled: false,
17931
17932     constructor : function(el, config) {
17933         var me = this;
17934
17935         if (el.isComponent) {
17936             me.bindComponent(el);
17937         } else {
17938             me.el = Ext.get(el);
17939         }
17940         Ext.apply(me, config);
17941
17942         me.addEvents('beforeshow', 'show', 'hide');
17943         if (me.store) {
17944             me.bindStore(me.store, true);
17945         }
17946         me.mixins.observable.constructor.call(me, config);
17947     },
17948
17949     bindComponent: function(comp) {
17950         var me = this,
17951             listeners = {
17952                 resize: me.onComponentResize,
17953                 scope: me
17954             };
17955
17956         if (comp.el) {
17957             me.onComponentRender(comp);
17958         } else {
17959             listeners.render = {
17960                 fn: me.onComponentRender,
17961                 scope: me,
17962                 single: true
17963             };
17964         }
17965         me.mon(comp, listeners);
17966     },
17967
17968     
17969     onComponentRender: function(comp) {
17970         this.el = comp.getContentTarget();
17971     },
17972
17973     
17974     onComponentResize: function(comp, w, h) {
17975         this.el.isMasked();
17976     },
17977
17978     
17979     bindStore : function(store, initial) {
17980         var me = this;
17981
17982         if (!initial && me.store) {
17983             me.mun(me.store, {
17984                 scope: me,
17985                 beforeload: me.onBeforeLoad,
17986                 load: me.onLoad,
17987                 exception: me.onLoad
17988             });
17989             if(!store) {
17990                 me.store = null;
17991             }
17992         }
17993         if (store) {
17994             store = Ext.data.StoreManager.lookup(store);
17995             me.mon(store, {
17996                 scope: me,
17997                 beforeload: me.onBeforeLoad,
17998                 load: me.onLoad,
17999                 exception: me.onLoad
18000             });
18001
18002         }
18003         me.store = store;
18004         if (store && store.isLoading()) {
18005             me.onBeforeLoad();
18006         }
18007     },
18008
18009     
18010     disable : function() {
18011         var me = this;
18012
18013        me.disabled = true;
18014        if (me.loading) {
18015            me.onLoad();
18016        }
18017     },
18018
18019     
18020     enable : function() {
18021         this.disabled = false;
18022     },
18023
18024     
18025     isDisabled : function() {
18026         return this.disabled;
18027     },
18028
18029     
18030     onLoad : function() {
18031         var me = this;
18032
18033         me.loading = false;
18034         me.el.unmask();
18035         me.fireEvent('hide', me, me.el, me.store);
18036     },
18037
18038     
18039     onBeforeLoad : function() {
18040         var me = this;
18041
18042         if (!me.disabled && !me.loading && me.fireEvent('beforeshow', me, me.el, me.store) !== false) {
18043             if (me.useMsg) {
18044                 me.el.mask(me.msg, me.msgCls, false);
18045             } else {
18046                 me.el.mask();
18047             }
18048             
18049             me.fireEvent('show', me, me.el, me.store);
18050             me.loading = true;
18051         }
18052     },
18053
18054     
18055     show: function() {
18056         this.onBeforeLoad();
18057     },
18058
18059     
18060     hide: function() {
18061         this.onLoad();
18062     },
18063
18064     
18065     destroy : function() {
18066         this.hide();
18067         this.clearListeners();
18068     }
18069 });
18070
18071
18072 Ext.define('Ext.ComponentLoader', {
18073
18074     
18075     
18076     extend: 'Ext.ElementLoader',
18077
18078     statics: {
18079         Renderer: {
18080             Data: function(loader, response, active){
18081                 var success = true;
18082                 try {
18083                     loader.getTarget().update(Ext.decode(response.responseText));
18084                 } catch (e) {
18085                     success = false;
18086                 }
18087                 return success;
18088             },
18089
18090             Component: function(loader, response, active){
18091                 var success = true,
18092                     target = loader.getTarget(),
18093                     items = [];
18094
18095                 if (!target.isContainer) {
18096                     Ext.Error.raise({
18097                         target: target,
18098                         msg: 'Components can only be loaded into a container'
18099                     });
18100                 }
18101
18102                 try {
18103                     items = Ext.decode(response.responseText);
18104                 } catch (e) {
18105                     success = false;
18106                 }
18107
18108                 if (success) {
18109                     if (active.removeAll) {
18110                         target.removeAll();
18111                     }
18112                     target.add(items);
18113                 }
18114                 return success;
18115             }
18116         }
18117     },
18118
18119     
18120
18121     
18122     target: null,
18123
18124     
18125     loadMask: false,
18126     
18127     
18128
18129     
18130     renderer: 'html',
18131
18132     
18133     setTarget: function(target){
18134         var me = this;
18135         
18136         if (Ext.isString(target)) {
18137             target = Ext.getCmp(target);
18138         }
18139
18140         if (me.target && me.target != target) {
18141             me.abort();
18142         }
18143         me.target = target;
18144     },
18145     
18146     
18147     removeMask: function(){
18148         this.target.setLoading(false);
18149     },
18150     
18151     
18152     addMask: function(mask){
18153         this.target.setLoading(mask);
18154     },
18155
18156     
18157     
18158     setOptions: function(active, options){
18159         active.removeAll = Ext.isDefined(options.removeAll) ? options.removeAll : this.removeAll;
18160     },
18161
18162     
18163     getRenderer: function(renderer){
18164         if (Ext.isFunction(renderer)) {
18165             return renderer;
18166         }
18167
18168         var renderers = this.statics().Renderer;
18169         switch (renderer) {
18170             case 'component':
18171                 return renderers.Component;
18172             case 'data':
18173                 return renderers.Data;
18174             default:
18175                 return Ext.ElementLoader.Renderer.Html;
18176         }
18177     }
18178 });
18179
18180
18181
18182 Ext.define('Ext.layout.component.Auto', {
18183
18184     
18185
18186     alias: 'layout.autocomponent',
18187
18188     extend: 'Ext.layout.component.Component',
18189
18190     
18191
18192     type: 'autocomponent',
18193
18194     onLayout : function(width, height) {
18195         this.setTargetSize(width, height);
18196     }
18197 });
18198
18199
18200 Ext.define('Ext.AbstractComponent', {
18201
18202     
18203
18204     mixins: {
18205         observable: 'Ext.util.Observable',
18206         animate: 'Ext.util.Animate',
18207         state: 'Ext.state.Stateful'
18208     },
18209
18210     requires: [
18211         'Ext.PluginManager',
18212         'Ext.ComponentManager',
18213         'Ext.core.Element',
18214         'Ext.core.DomHelper',
18215         'Ext.XTemplate',
18216         'Ext.ComponentQuery',
18217         'Ext.LoadMask',
18218         'Ext.ComponentLoader',
18219         'Ext.EventManager',
18220         'Ext.layout.Layout',
18221         'Ext.layout.component.Auto'
18222     ],
18223
18224     
18225     
18226     uses: [
18227         'Ext.ZIndexManager'
18228     ],
18229
18230     statics: {
18231         AUTO_ID: 1000
18232     },
18233
18234     
18235
18236     isComponent: true,
18237
18238     getAutoId: function() {
18239         return ++Ext.AbstractComponent.AUTO_ID;
18240     },
18241
18242     
18243
18244     
18245
18246     
18247
18248     
18249
18250     
18251     renderTpl: null,
18252
18253     
18254
18255     
18256
18257     
18258
18259     
18260
18261     
18262
18263     
18264
18265     
18266
18267     
18268     tplWriteMode: 'overwrite',
18269
18270     
18271     baseCls: Ext.baseCSSPrefix + 'component',
18272
18273     
18274
18275     
18276
18277     
18278
18279     
18280     disabledCls: Ext.baseCSSPrefix + 'item-disabled',
18281
18282     
18283     ui: 'default',
18284     
18285     
18286     uiCls: [],
18287     
18288     
18289
18290     
18291
18292     
18293
18294     
18295
18296     
18297
18298     
18299
18300     
18301     hidden: false,
18302
18303     
18304     disabled: false,
18305
18306     
18307
18308     
18309     draggable: false,
18310
18311     
18312     floating: false,
18313
18314     
18315     hideMode: 'display',
18316
18317     
18318
18319     
18320
18321     
18322     styleHtmlContent: false,
18323
18324     
18325     styleHtmlCls: Ext.baseCSSPrefix + 'html',
18326
18327     
18328     
18329     
18330     
18331
18332     
18333
18334      
18335      allowDomMove: true,
18336
18337      
18338      autoShow: false,
18339
18340     
18341      autoRender: false,
18342
18343      needsLayout: false,
18344
18345     
18346
18347     
18348     rendered: false,
18349
18350     weight: 0,
18351
18352     trimRe: /^\s+|\s+$/g,
18353     spacesRe: /\s+/,
18354     
18355     
18356          
18357     maskOnDisable: true,
18358
18359     constructor : function(config) {
18360         var me = this,
18361             i, len;
18362
18363         config = config || {};
18364         me.initialConfig = config;
18365         Ext.apply(me, config);
18366
18367         me.addEvents(
18368             
18369              'beforeactivate',
18370             
18371              'activate',
18372             
18373              'beforedeactivate',
18374             
18375              'deactivate',
18376             
18377              'added',
18378             
18379              'disable',
18380             
18381              'enable',
18382             
18383              'beforeshow',
18384             
18385              'show',
18386             
18387              'beforehide',
18388             
18389              'hide',
18390             
18391              'removed',
18392             
18393              'beforerender',
18394             
18395              'render',
18396             
18397              'afterrender',
18398             
18399              'beforedestroy',
18400             
18401              'destroy',
18402             
18403              'resize',
18404             
18405              'move'
18406         );
18407
18408         me.getId();
18409
18410         me.mons = [];
18411         me.additionalCls = [];
18412         me.renderData = me.renderData || {};
18413         me.renderSelectors = me.renderSelectors || {};
18414
18415         if (me.plugins) {
18416             me.plugins = [].concat(me.plugins);
18417             for (i = 0, len = me.plugins.length; i < len; i++) {
18418                 me.plugins[i] = me.constructPlugin(me.plugins[i]);
18419             }
18420         }
18421         
18422         me.initComponent();
18423
18424         
18425         Ext.ComponentManager.register(me);
18426
18427         
18428         me.mixins.observable.constructor.call(me);
18429         me.mixins.state.constructor.call(me, config);
18430
18431         
18432         if (me.plugins) {
18433             me.plugins = [].concat(me.plugins);
18434             for (i = 0, len = me.plugins.length; i < len; i++) {
18435                 me.plugins[i] = me.initPlugin(me.plugins[i]);
18436             }
18437         }
18438
18439         me.loader = me.getLoader();
18440
18441         if (me.renderTo) {
18442             me.render(me.renderTo);
18443         }
18444
18445         if (me.autoShow) {
18446             me.show();
18447         }
18448         
18449         if (Ext.isDefined(me.disabledClass)) {
18450             if (Ext.isDefined(Ext.global.console)) {
18451                 Ext.global.console.warn('Ext.Component: disabledClass has been deprecated. Please use disabledCls.');
18452             }
18453             me.disabledCls = me.disabledClass;
18454             delete me.disabledClass;
18455         }
18456     },
18457
18458     initComponent: Ext.emptyFn,
18459
18460     show: Ext.emptyFn,
18461
18462     animate: function(animObj) {
18463         var me = this,
18464             to;
18465
18466         animObj = animObj || {};
18467         to = animObj.to || {};
18468
18469         if (Ext.fx.Manager.hasFxBlock(me.id)) {
18470             return me;
18471         }
18472         
18473         if (!animObj.dynamic && (to.height || to.width)) {
18474             var curWidth = me.getWidth(),
18475                 w = curWidth,
18476                 curHeight = me.getHeight(),
18477                 h = curHeight,
18478                 needsResize = false;
18479
18480             if (to.height && to.height > curHeight) {
18481                 h = to.height;
18482                 needsResize = true;
18483             }
18484             if (to.width && to.width > curWidth) {
18485                 w = to.width;
18486                 needsResize = true;
18487             }
18488
18489             
18490             
18491             
18492             if (needsResize) {
18493                 var clearWidth = !Ext.isNumber(me.width),
18494                     clearHeight = !Ext.isNumber(me.height);
18495
18496                 me.componentLayout.childrenChanged = true;
18497                 me.setSize(w, h, me.ownerCt);
18498                 me.el.setSize(curWidth, curHeight);
18499                 if (clearWidth) {
18500                     delete me.width;
18501                 }
18502                 if (clearHeight) {
18503                     delete me.height;
18504                 }
18505             }
18506         }
18507         return me.mixins.animate.animate.apply(me, arguments);
18508     },
18509
18510     
18511     findLayoutController: function() {
18512         return this.findParentBy(function(c) {
18513             
18514             
18515             return !c.ownerCt || (c.layout.layoutBusy && !c.ownerCt.layout.layoutBusy);
18516         });
18517     },
18518
18519     onShow : function() {
18520         
18521         var needsLayout = this.needsLayout;
18522         if (Ext.isObject(needsLayout)) {
18523             this.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
18524         }
18525     },
18526
18527     constructPlugin: function(plugin) {
18528         if (plugin.ptype && typeof plugin.init != 'function') {
18529             plugin.cmp = this;
18530             plugin = Ext.PluginManager.create(plugin);
18531         }
18532         else if (typeof plugin == 'string') {
18533             plugin = Ext.PluginManager.create({
18534                 ptype: plugin,
18535                 cmp: this
18536             });
18537         }
18538         return plugin;
18539     },
18540
18541
18542     
18543     initPlugin : function(plugin) {
18544         plugin.init(this);
18545
18546         return plugin;
18547     },
18548
18549     
18550     doAutoRender: function() {
18551         var me = this;
18552         if (me.floating) {
18553             me.render(document.body);
18554         } else {
18555             me.render(Ext.isBoolean(me.autoRender) ? Ext.getBody() : me.autoRender);
18556         }
18557     },
18558
18559     
18560     render : function(container, position) {
18561         var me = this;
18562
18563         if (!me.rendered && me.fireEvent('beforerender', me) !== false) {
18564             
18565             
18566             if (me.el) {
18567                 me.el = Ext.get(me.el);
18568             }
18569
18570             
18571             if (me.floating) {
18572                 me.onFloatRender();
18573             }
18574
18575             container = me.initContainer(container);
18576
18577             me.onRender(container, position);
18578
18579             
18580             
18581             me.el.setVisibilityMode(Ext.core.Element[me.hideMode.toUpperCase()]);
18582
18583             if (me.overCls) {
18584                 me.el.hover(me.addOverCls, me.removeOverCls, me);
18585             }
18586
18587             me.fireEvent('render', me);
18588
18589             me.initContent();
18590
18591             me.afterRender(container);
18592             me.fireEvent('afterrender', me);
18593
18594             me.initEvents();
18595
18596             if (me.hidden) {
18597                 
18598                 
18599                 
18600                 me.el.hide();
18601             }
18602
18603             if (me.disabled) {
18604                 
18605                 me.disable(true);
18606             }
18607         }
18608         return me;
18609     },
18610
18611     
18612     onRender : function(container, position) {
18613         var me = this,
18614             el = me.el,
18615             cls = me.initCls(),
18616             styles = me.initStyles(),
18617             renderTpl, renderData, i;
18618
18619         position = me.getInsertPosition(position);
18620
18621         if (!el) {
18622             if (position) {
18623                 el = Ext.core.DomHelper.insertBefore(position, me.getElConfig(), true);
18624             }
18625             else {
18626                 el = Ext.core.DomHelper.append(container, me.getElConfig(), true);
18627             }
18628         }
18629         else if (me.allowDomMove !== false) {
18630             if (position) {
18631                 container.dom.insertBefore(el.dom, position);
18632             } else {
18633                 container.dom.appendChild(el.dom);
18634             }
18635         }
18636
18637         if (Ext.scopeResetCSS && !me.ownerCt) {
18638             
18639             if (el.dom == Ext.getBody().dom) {
18640                 el.parent().addCls(Ext.baseCSSPrefix + 'reset');
18641             }
18642             else {
18643                 
18644                 me.resetEl = el.wrap({
18645                     cls: Ext.baseCSSPrefix + 'reset'
18646                 });
18647             }
18648         }
18649
18650         el.addCls(cls);
18651         el.setStyle(styles);
18652
18653         
18654         
18655         
18656         
18657         
18658         
18659         
18660         
18661         
18662         
18663
18664         me.el = el;
18665         
18666         me.rendered = true;
18667         me.addUIToElement(true);
18668         
18669         for (i = 0; i < me.uiCls.length; i++) {
18670             me.addUIClsToElement(me.uiCls[i], true);
18671         }
18672         me.rendered = false;
18673         me.initFrame();
18674
18675         renderTpl = me.initRenderTpl();
18676         if (renderTpl) {
18677             renderData = me.initRenderData();
18678             renderTpl.append(me.getTargetEl(), renderData);
18679         }
18680
18681         me.applyRenderSelectors();
18682         
18683         me.rendered = true;
18684         
18685         me.setUI(me.ui);
18686     },
18687
18688     
18689     afterRender : function() {
18690         var me = this,
18691             pos,
18692             xy;
18693
18694         me.getComponentLayout();
18695
18696         
18697         if (!me.ownerCt || (me.height || me.width)) {
18698             me.setSize(me.width, me.height);
18699         }
18700
18701         
18702         
18703         if (me.floating && (me.x === undefined || me.y === undefined)) {
18704             if (me.floatParent) {
18705                 xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c');
18706                 pos = me.floatParent.getTargetEl().translatePoints(xy[0], xy[1]);
18707             } else {
18708                 xy = me.el.getAlignToXY(me.container, 'c-c');
18709                 pos = me.container.translatePoints(xy[0], xy[1]);
18710             }
18711             me.x = me.x === undefined ? pos.left: me.x;
18712             me.y = me.y === undefined ? pos.top: me.y;
18713         }
18714
18715         if (Ext.isDefined(me.x) || Ext.isDefined(me.y)) {
18716             me.setPosition(me.x, me.y);
18717         }
18718
18719         if (me.styleHtmlContent) {
18720             me.getTargetEl().addCls(me.styleHtmlCls);
18721         }
18722     },
18723
18724     frameCls: Ext.baseCSSPrefix + 'frame',
18725
18726     frameTpl: [
18727         '<tpl if="top">',
18728             '<tpl if="left"><div class="{frameCls}-tl {baseCls}-tl {baseCls}-{ui}-tl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tl</tpl></tpl>" style="background-position: {tl}; padding-left: {frameWidth}px" role="presentation"></tpl>',
18729                 '<tpl if="right"><div class="{frameCls}-tr {baseCls}-tr {baseCls}-{ui}-tr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tr</tpl></tpl>" style="background-position: {tr}; padding-right: {frameWidth}px" role="presentation"></tpl>',
18730                     '<div class="{frameCls}-tc {baseCls}-tc {baseCls}-{ui}-tc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tc</tpl></tpl>" style="background-position: {tc}; height: {frameWidth}px" role="presentation"></div>',
18731                 '<tpl if="right"></div></tpl>',
18732             '<tpl if="left"></div></tpl>',
18733         '</tpl>',
18734         '<tpl if="left"><div class="{frameCls}-ml {baseCls}-ml {baseCls}-{ui}-ml<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-ml</tpl></tpl>" style="background-position: {ml}; padding-left: {frameWidth}px" role="presentation"></tpl>',
18735             '<tpl if="right"><div class="{frameCls}-mr {baseCls}-mr {baseCls}-{ui}-mr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mr</tpl></tpl>" style="background-position: {mr}; padding-right: {frameWidth}px" role="presentation"></tpl>',
18736                 '<div class="{frameCls}-mc {baseCls}-mc {baseCls}-{ui}-mc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mc</tpl></tpl>" role="presentation"></div>',
18737             '<tpl if="right"></div></tpl>',
18738         '<tpl if="left"></div></tpl>',
18739         '<tpl if="bottom">',
18740             '<tpl if="left"><div class="{frameCls}-bl {baseCls}-bl {baseCls}-{ui}-bl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bl</tpl></tpl>" style="background-position: {bl}; padding-left: {frameWidth}px" role="presentation"></tpl>',
18741                 '<tpl if="right"><div class="{frameCls}-br {baseCls}-br {baseCls}-{ui}-br<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-br</tpl></tpl>" style="background-position: {br}; padding-right: {frameWidth}px" role="presentation"></tpl>',
18742                     '<div class="{frameCls}-bc {baseCls}-bc {baseCls}-{ui}-bc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bc</tpl></tpl>" style="background-position: {bc}; height: {frameWidth}px" role="presentation"></div>',
18743                 '<tpl if="right"></div></tpl>',
18744             '<tpl if="left"></div></tpl>',
18745         '</tpl>'
18746     ],
18747
18748     frameTableTpl: [
18749         '<table><tbody>',
18750             '<tpl if="top">',
18751                 '<tr>',
18752                     '<tpl if="left"><td class="{frameCls}-tl {baseCls}-tl {baseCls}-{ui}-tl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tl</tpl></tpl>" style="background-position: {tl}; padding-left:{frameWidth}px" role="presentation"></td></tpl>',
18753                     '<td class="{frameCls}-tc {baseCls}-tc {baseCls}-{ui}-tc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tc</tpl></tpl>" style="background-position: {tc}; height: {frameWidth}px" role="presentation"></td>',
18754                     '<tpl if="right"><td class="{frameCls}-tr {baseCls}-tr {baseCls}-{ui}-tr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tr</tpl></tpl>" style="background-position: {tr}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
18755                 '</tr>',
18756             '</tpl>',
18757             '<tr>',
18758                 '<tpl if="left"><td class="{frameCls}-ml {baseCls}-ml {baseCls}-{ui}-ml<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-ml</tpl></tpl>" style="background-position: {ml}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
18759                 '<td class="{frameCls}-mc {baseCls}-mc {baseCls}-{ui}-mc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mc</tpl></tpl>" style="background-position: 0 0;" role="presentation"></td>',
18760                 '<tpl if="right"><td class="{frameCls}-mr {baseCls}-mr {baseCls}-{ui}-mr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mr</tpl></tpl>" style="background-position: {mr}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
18761             '</tr>',
18762             '<tpl if="bottom">',
18763                 '<tr>',
18764                     '<tpl if="left"><td class="{frameCls}-bl {baseCls}-bl {baseCls}-{ui}-bl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bl</tpl></tpl>" style="background-position: {bl}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
18765                     '<td class="{frameCls}-bc {baseCls}-bc {baseCls}-{ui}-bc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bc</tpl></tpl>" style="background-position: {bc}; height: {frameWidth}px" role="presentation"></td>',
18766                     '<tpl if="right"><td class="{frameCls}-br {baseCls}-br {baseCls}-{ui}-br<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-br</tpl></tpl>" style="background-position: {br}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
18767                 '</tr>',
18768             '</tpl>',
18769         '</tbody></table>'
18770     ],
18771     
18772     
18773     initFrame : function() {
18774         if (Ext.supports.CSS3BorderRadius) {
18775             return false;
18776         }
18777         
18778         var me = this,
18779             frameInfo = me.getFrameInfo(),
18780             frameWidth = frameInfo.width,
18781             frameTpl = me.getFrameTpl(frameInfo.table);
18782                         
18783         if (me.frame) {
18784             
18785             frameTpl.insertFirst(me.el, Ext.apply({}, {
18786                 ui:         me.ui,
18787                 uiCls:      me.uiCls,
18788                 frameCls:   me.frameCls,
18789                 baseCls:    me.baseCls,
18790                 frameWidth: frameWidth,
18791                 top:        !!frameInfo.top,
18792                 left:       !!frameInfo.left,
18793                 right:      !!frameInfo.right,
18794                 bottom:     !!frameInfo.bottom
18795             }, me.getFramePositions(frameInfo)));
18796
18797             
18798             me.frameBody = me.el.down('.' + me.frameCls + '-mc');
18799             
18800             
18801             Ext.apply(me.renderSelectors, {
18802                 frameTL: '.' + me.baseCls + '-tl',
18803                 frameTC: '.' + me.baseCls + '-tc',
18804                 frameTR: '.' + me.baseCls + '-tr',
18805                 frameML: '.' + me.baseCls + '-ml',
18806                 frameMC: '.' + me.baseCls + '-mc',
18807                 frameMR: '.' + me.baseCls + '-mr',
18808                 frameBL: '.' + me.baseCls + '-bl',
18809                 frameBC: '.' + me.baseCls + '-bc',
18810                 frameBR: '.' + me.baseCls + '-br'
18811             });
18812         }
18813     },
18814     
18815     updateFrame: function() {
18816         if (Ext.supports.CSS3BorderRadius) {
18817             return false;
18818         }
18819         
18820         var me = this,
18821             wasTable = this.frameSize && this.frameSize.table,
18822             oldFrameTL = this.frameTL,
18823             oldFrameBL = this.frameBL,
18824             oldFrameML = this.frameML,
18825             oldFrameMC = this.frameMC,
18826             newMCClassName;
18827         
18828         this.initFrame();
18829         
18830         if (oldFrameMC) {
18831             if (me.frame) {                
18832                 
18833                 delete me.frameTL;
18834                 delete me.frameTC;
18835                 delete me.frameTR;
18836                 delete me.frameML;
18837                 delete me.frameMC;
18838                 delete me.frameMR;
18839                 delete me.frameBL;
18840                 delete me.frameBC;
18841                 delete me.frameBR;    
18842                 this.applyRenderSelectors();
18843                 
18844                 
18845                 newMCClassName = this.frameMC.dom.className;
18846                 
18847                 
18848                 oldFrameMC.insertAfter(this.frameMC);
18849                 this.frameMC.remove();
18850                 
18851                 
18852                 this.frameBody = this.frameMC = oldFrameMC;
18853                 
18854                 
18855                 oldFrameMC.dom.className = newMCClassName;
18856                 
18857                 
18858                 if (wasTable) {
18859                     me.el.query('> table')[1].remove();
18860                 }                                
18861                 else {
18862                     if (oldFrameTL) {
18863                         oldFrameTL.remove();
18864                     }
18865                     if (oldFrameBL) {
18866                         oldFrameBL.remove();
18867                     }
18868                     oldFrameML.remove();
18869                 }
18870             }
18871             else {
18872                 
18873                 
18874             }
18875         }
18876         else if (me.frame) {
18877             this.applyRenderSelectors();
18878         }
18879     },
18880     
18881     getFrameInfo: function() {
18882         if (Ext.supports.CSS3BorderRadius) {
18883             return false;
18884         }
18885         
18886         var me = this,
18887             left = me.el.getStyle('background-position-x'),
18888             top = me.el.getStyle('background-position-y'),
18889             info, frameInfo = false, max;
18890
18891         
18892         
18893         if (!left && !top) {
18894             info = me.el.getStyle('background-position').split(' ');
18895             left = info[0];
18896             top = info[1];
18897         }
18898         
18899         
18900         
18901         
18902         if (parseInt(left, 10) >= 1000000 && parseInt(top, 10) >= 1000000) {
18903             max = Math.max;
18904             
18905             frameInfo = {
18906                 
18907                 table: left.substr(0, 3) == '110',
18908                 
18909                 
18910                 vertical: top.substr(0, 3) == '110',
18911                 
18912                 
18913                 top:    max(left.substr(3, 2), left.substr(5, 2)),
18914                 right:  max(left.substr(5, 2), top.substr(3, 2)),
18915                 bottom: max(top.substr(3, 2), top.substr(5, 2)),
18916                 left:   max(top.substr(5, 2), left.substr(3, 2))
18917             };
18918             
18919             frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left);
18920
18921             
18922             me.el.setStyle('background-image', 'none');
18923         }        
18924         
18925         
18926         
18927         if (me.frame === true && !frameInfo) {
18928             Ext.Error.raise("You have set frame: true explicity on this component while it doesn't have any " +
18929                             "framing defined in the CSS template. In this case IE can't figure out what sizes " +
18930                             "to use and thus framing on this component will be disabled.");
18931         }
18932         
18933         me.frame = me.frame || !!frameInfo;
18934         me.frameSize = frameInfo || false;
18935         
18936         return frameInfo;
18937     },
18938     
18939     getFramePositions: function(frameInfo) {
18940         var me = this,
18941             frameWidth = frameInfo.width,
18942             dock = me.dock,
18943             positions, tc, bc, ml, mr;
18944             
18945         if (frameInfo.vertical) {
18946             tc = '0 -' + (frameWidth * 0) + 'px';
18947             bc = '0 -' + (frameWidth * 1) + 'px';
18948             
18949             if (dock && dock == "right") {
18950                 tc = 'right -' + (frameWidth * 0) + 'px';
18951                 bc = 'right -' + (frameWidth * 1) + 'px';
18952             }
18953             
18954             positions = {
18955                 tl: '0 -' + (frameWidth * 0) + 'px',
18956                 tr: '0 -' + (frameWidth * 1) + 'px',
18957                 bl: '0 -' + (frameWidth * 2) + 'px',
18958                 br: '0 -' + (frameWidth * 3) + 'px',
18959
18960                 ml: '-' + (frameWidth * 1) + 'px 0',
18961                 mr: 'right 0',
18962
18963                 tc: tc,
18964                 bc: bc
18965             };
18966         } else {
18967             ml = '-' + (frameWidth * 0) + 'px 0';
18968             mr = 'right 0';
18969             
18970             if (dock && dock == "bottom") {
18971                 ml = 'left bottom';
18972                 mr = 'right bottom';
18973             }
18974             
18975             positions = {
18976                 tl: '0 -' + (frameWidth * 2) + 'px',
18977                 tr: 'right -' + (frameWidth * 3) + 'px',
18978                 bl: '0 -' + (frameWidth * 4) + 'px',
18979                 br: 'right -' + (frameWidth * 5) + 'px',
18980
18981                 ml: ml,
18982                 mr: mr,
18983
18984                 tc: '0 -' + (frameWidth * 0) + 'px',
18985                 bc: '0 -' + (frameWidth * 1) + 'px'
18986             };
18987         }
18988         
18989         return positions;
18990     },
18991     
18992     
18993     getFrameTpl : function(table) {
18994         return table ? this.getTpl('frameTableTpl') : this.getTpl('frameTpl');
18995     },
18996
18997     
18998     initCls: function() {
18999         var me = this,
19000             cls = [];
19001
19002         cls.push(me.baseCls);
19003
19004         if (Ext.isDefined(me.cmpCls)) {
19005             if (Ext.isDefined(Ext.global.console)) {
19006                 Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.');
19007             }
19008             me.componentCls = me.cmpCls;
19009             delete me.cmpCls;
19010         }
19011
19012         if (me.componentCls) {
19013             cls.push(me.componentCls);
19014         } else {
19015             me.componentCls = me.baseCls;
19016         }
19017         if (me.cls) {
19018             cls.push(me.cls);
19019             delete me.cls;
19020         }
19021
19022         return cls.concat(me.additionalCls);
19023     },
19024     
19025     
19026     setUI: function(ui) {
19027         var me = this,
19028             oldUICls = Ext.Array.clone(me.uiCls),
19029             newUICls = [],
19030             cls,
19031             i;
19032         
19033         
19034         for (i = 0; i < oldUICls.length; i++) {
19035             cls = oldUICls[i];
19036             
19037             me.removeClsWithUI(cls);
19038             newUICls.push(cls);
19039         }
19040         
19041         
19042         me.removeUIFromElement();
19043         
19044         
19045         me.ui = ui;
19046         
19047         
19048         me.addUIToElement();
19049         
19050         
19051         for (i = 0; i < newUICls.length; i++) {
19052             cls = newUICls[i];
19053             
19054             me.addClsWithUI(cls);
19055         }
19056     },
19057     
19058     
19059     addClsWithUI: function(cls) {
19060         var me = this,
19061             i;
19062         
19063         if (!Ext.isArray(cls)) {
19064             cls = [cls];
19065         }
19066         
19067         for (i = 0; i < cls.length; i++) {
19068             if (cls[i] && !me.hasUICls(cls[i])) {
19069                 me.uiCls = Ext.Array.clone(me.uiCls);
19070                 me.uiCls.push(cls[i]);
19071                 me.addUIClsToElement(cls[i]);
19072             }
19073         }
19074     },
19075     
19076     
19077     removeClsWithUI: function(cls) {
19078         var me = this,
19079             i;
19080         
19081         if (!Ext.isArray(cls)) {
19082             cls = [cls];
19083         }
19084         
19085         for (i = 0; i < cls.length; i++) {
19086             if (cls[i] && me.hasUICls(cls[i])) {
19087                 me.uiCls = Ext.Array.remove(me.uiCls, cls[i]);
19088                 me.removeUIClsFromElement(cls[i]);
19089             }
19090         }
19091     },
19092     
19093     
19094     hasUICls: function(cls) {
19095         var me = this,
19096             uiCls = me.uiCls || [];
19097         
19098         return Ext.Array.contains(uiCls, cls);
19099     },
19100     
19101     
19102     addUIClsToElement: function(cls, force) {
19103         var me = this;
19104         
19105         me.addCls(Ext.baseCSSPrefix + cls);
19106         me.addCls(me.baseCls + '-' + cls);
19107         me.addCls(me.baseCls + '-' + me.ui + '-' + cls);
19108         
19109         if (!force && me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
19110             
19111             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
19112                 i, el;
19113             
19114             
19115             for (i = 0; i < els.length; i++) {
19116                 el = me['frame' + els[i].toUpperCase()];
19117                 
19118                 if (el && el.dom) {
19119                     el.addCls(me.baseCls + '-' + me.ui + '-' + els[i]);
19120                     el.addCls(me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]);
19121                 }
19122             }
19123         }
19124     },
19125     
19126     
19127     removeUIClsFromElement: function(cls, force) {
19128         var me = this;
19129         
19130         me.removeCls(Ext.baseCSSPrefix + cls);
19131         me.removeCls(me.baseCls + '-' + cls);
19132         me.removeCls(me.baseCls + '-' + me.ui + '-' + cls);
19133         
19134         if (!force &&me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
19135             
19136             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
19137                 i, el;
19138             
19139             
19140             for (i = 0; i < els.length; i++) {
19141                 el = me['frame' + els[i].toUpperCase()];
19142                 if (el && el.dom) {
19143                     el.removeCls(me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]);
19144                 }
19145             }
19146         }
19147     },
19148     
19149     
19150     addUIToElement: function(force) {
19151         var me = this;
19152         
19153         me.addCls(me.baseCls + '-' + me.ui);
19154         
19155         if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
19156             
19157             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
19158                 i, el;
19159             
19160             
19161             for (i = 0; i < els.length; i++) {
19162                 el = me['frame' + els[i].toUpperCase()];
19163                 
19164                 if (el) {
19165                     el.addCls(me.baseCls + '-' + me.ui + '-' + els[i]);
19166                 }
19167             }
19168         }
19169     },
19170     
19171     
19172     removeUIFromElement: function() {
19173         var me = this;
19174         
19175         me.removeCls(me.baseCls + '-' + me.ui);
19176         
19177         if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
19178             
19179             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
19180                 i, el;
19181             
19182             
19183             for (i = 0; i < els.length; i++) {
19184                 el = me['frame' + els[i].toUpperCase()];
19185                 if (el) {
19186                     el.removeCls(me.baseCls + '-' + me.ui + '-' + els[i]);
19187                 }
19188             }
19189         }
19190     },
19191     
19192     getElConfig : function() {
19193         var result = this.autoEl || {tag: 'div'};
19194         result.id = this.id;
19195         return result;
19196     },
19197
19198     
19199     getInsertPosition: function(position) {
19200         
19201         if (position !== undefined) {
19202             if (Ext.isNumber(position)) {
19203                 position = this.container.dom.childNodes[position];
19204             }
19205             else {
19206                 position = Ext.getDom(position);
19207             }
19208         }
19209
19210         return position;
19211     },
19212
19213     
19214     initContainer: function(container) {
19215         var me = this;
19216
19217         
19218         
19219         
19220         if (!container && me.el) {
19221             container = me.el.dom.parentNode;
19222             me.allowDomMove = false;
19223         }
19224
19225         me.container = Ext.get(container);
19226
19227         if (me.ctCls) {
19228             me.container.addCls(me.ctCls);
19229         }
19230
19231         return me.container;
19232     },
19233
19234     
19235     initRenderData: function() {
19236         var me = this;
19237
19238         return Ext.applyIf(me.renderData, {
19239             ui: me.ui,
19240             uiCls: me.uiCls,
19241             baseCls: me.baseCls,
19242             componentCls: me.componentCls,
19243             frame: me.frame
19244         });
19245     },
19246
19247     
19248     getTpl: function(name) {
19249         var prototype = this.self.prototype,
19250             ownerPrototype;
19251
19252         if (this.hasOwnProperty(name)) {
19253             if (!(this[name] instanceof Ext.XTemplate)) {
19254                 this[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', this[name]);
19255             }
19256
19257             return this[name];
19258         }
19259
19260         if (!(prototype[name] instanceof Ext.XTemplate)) {
19261             ownerPrototype = prototype;
19262
19263             do {
19264                 if (ownerPrototype.hasOwnProperty(name)) {
19265                     ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', ownerPrototype[name]);
19266                     break;
19267                 }
19268
19269                 ownerPrototype = ownerPrototype.superclass;
19270             } while (ownerPrototype);
19271         }
19272
19273         return prototype[name];
19274     },
19275
19276     
19277     initRenderTpl: function() {
19278         return this.getTpl('renderTpl');
19279     },
19280
19281     
19282     initStyles: function() {
19283         var style = {},
19284             me = this,
19285             Element = Ext.core.Element;
19286
19287         if (Ext.isString(me.style)) {
19288             style = Element.parseStyles(me.style);
19289         } else {
19290             style = Ext.apply({}, me.style);
19291         }
19292
19293         
19294         
19295         if (me.padding !== undefined) {
19296             style.padding = Element.unitizeBox((me.padding === true) ? 5 : me.padding);
19297         }
19298
19299         if (me.margin !== undefined) {
19300             style.margin = Element.unitizeBox((me.margin === true) ? 5 : me.margin);
19301         }
19302
19303         delete me.style;
19304         return style;
19305     },
19306
19307     
19308     initContent: function() {
19309         var me = this,
19310             target = me.getTargetEl(),
19311             contentEl,
19312             pre;
19313
19314         if (me.html) {
19315             target.update(Ext.core.DomHelper.markup(me.html));
19316             delete me.html;
19317         }
19318
19319         if (me.contentEl) {
19320             contentEl = Ext.get(me.contentEl);
19321             pre = Ext.baseCSSPrefix;
19322             contentEl.removeCls([pre + 'hidden', pre + 'hide-display', pre + 'hide-offsets', pre + 'hide-nosize']);
19323             target.appendChild(contentEl.dom);
19324         }
19325
19326         if (me.tpl) {
19327             
19328             if (!me.tpl.isTemplate) {
19329                 me.tpl = Ext.create('Ext.XTemplate', me.tpl);
19330             }
19331
19332             if (me.data) {
19333                 me.tpl[me.tplWriteMode](target, me.data);
19334                 delete me.data;
19335             }
19336         }
19337     },
19338
19339     
19340     initEvents : function() {
19341         var me = this,
19342             afterRenderEvents = me.afterRenderEvents,
19343             property, listeners;
19344         if (afterRenderEvents) {
19345             for (property in afterRenderEvents) {
19346                 if (afterRenderEvents.hasOwnProperty(property)) {
19347                     listeners = afterRenderEvents[property];
19348                     if (me[property] && me[property].on) {
19349                         me.mon(me[property], listeners);
19350                     }
19351                 }
19352             }
19353         }
19354     },
19355
19356     
19357     applyRenderSelectors: function() {
19358         var selectors = this.renderSelectors || {},
19359             el = this.el.dom,
19360             selector;
19361
19362         for (selector in selectors) {
19363             if (selectors.hasOwnProperty(selector) && selectors[selector]) {
19364                 this[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], el));
19365             }
19366         }
19367     },
19368
19369     
19370     is: function(selector) {
19371         return Ext.ComponentQuery.is(this, selector);
19372     },
19373
19374     
19375     up: function(selector) {
19376         var result = this.ownerCt;
19377         if (selector) {
19378             for (; result; result = result.ownerCt) {
19379                 if (Ext.ComponentQuery.is(result, selector)) {
19380                     return result;
19381                 }
19382             }
19383         }
19384         return result;
19385     },
19386
19387     
19388     nextSibling: function(selector) {
19389         var o = this.ownerCt, it, last, idx, c;
19390         if (o) {
19391             it = o.items;
19392             idx = it.indexOf(this) + 1;
19393             if (idx) {
19394                 if (selector) {
19395                     for (last = it.getCount(); idx < last; idx++) {
19396                         if ((c = it.getAt(idx)).is(selector)) {
19397                             return c;
19398                         }
19399                     }
19400                 } else {
19401                     if (idx < it.getCount()) {
19402                         return it.getAt(idx);
19403                     }
19404                 }
19405             }
19406         }
19407         return null;
19408     },
19409
19410     
19411     previousSibling: function(selector) {
19412         var o = this.ownerCt, it, idx, c;
19413         if (o) {
19414             it = o.items;
19415             idx = it.indexOf(this);
19416             if (idx != -1) {
19417                 if (selector) {
19418                     for (--idx; idx >= 0; idx--) {
19419                         if ((c = it.getAt(idx)).is(selector)) {
19420                             return c;
19421                         }
19422                     }
19423                 } else {
19424                     if (idx) {
19425                         return it.getAt(--idx);
19426                     }
19427                 }
19428             }
19429         }
19430         return null;
19431     },
19432
19433     
19434     previousNode: function(selector, includeSelf) {
19435         var node = this,
19436             result,
19437             it, len, i;
19438
19439         
19440         if (includeSelf && node.is(selector)) {
19441             return node;
19442         }
19443
19444         result = this.prev(selector);
19445         if (result) {
19446             return result;
19447         }
19448
19449         if (node.ownerCt) {
19450             for (it = node.ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
19451                 if (it[i].query) {
19452                     result = it[i].query(selector);
19453                     result = result[result.length - 1];
19454                     if (result) {
19455                         return result;
19456                     }
19457                 }
19458             }
19459             return node.ownerCt.previousNode(selector, true);
19460         }
19461     },
19462
19463     
19464     nextNode: function(selector, includeSelf) {
19465         var node = this,
19466             result,
19467             it, len, i;
19468
19469         
19470         if (includeSelf && node.is(selector)) {
19471             return node;
19472         }
19473
19474         result = this.next(selector);
19475         if (result) {
19476             return result;
19477         }
19478
19479         if (node.ownerCt) {
19480             for (it = node.ownerCt.items, i = it.indexOf(node) + 1, it = it.items, len = it.length; i < len; i++) {
19481                 if (it[i].down) {
19482                     result = it[i].down(selector);
19483                     if (result) {
19484                         return result;
19485                     }
19486                 }
19487             }
19488             return node.ownerCt.nextNode(selector);
19489         }
19490     },
19491
19492     
19493     getId : function() {
19494         return this.id || (this.id = 'ext-comp-' + (this.getAutoId()));
19495     },
19496
19497     getItemId : function() {
19498         return this.itemId || this.id;
19499     },
19500
19501     
19502     getEl : function() {
19503         return this.el;
19504     },
19505
19506     
19507     getTargetEl: function() {
19508         return this.frameBody || this.el;
19509     },
19510
19511     
19512     isXType: function(xtype, shallow) {
19513         
19514         if (Ext.isFunction(xtype)) {
19515             xtype = xtype.xtype;
19516             
19517         } else if (Ext.isObject(xtype)) {
19518             xtype = xtype.statics().xtype;
19519             
19520         }
19521
19522         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1: this.self.xtype == xtype;
19523     },
19524
19525     
19526     getXTypes: function() {
19527         var self = this.self,
19528             xtypes      = [],
19529             parentPrototype  = this,
19530             xtype;
19531
19532         if (!self.xtypes) {
19533             while (parentPrototype && Ext.getClass(parentPrototype)) {
19534                 xtype = Ext.getClass(parentPrototype).xtype;
19535
19536                 if (xtype !== undefined) {
19537                     xtypes.unshift(xtype);
19538                 }
19539
19540                 parentPrototype = parentPrototype.superclass;
19541             }
19542
19543             self.xtypeChain = xtypes;
19544             self.xtypes = xtypes.join('/');
19545         }
19546
19547         return self.xtypes;
19548     },
19549
19550     
19551     update : function(htmlOrData, loadScripts, cb) {
19552         var me = this;
19553
19554         if (me.tpl && !Ext.isString(htmlOrData)) {
19555             me.data = htmlOrData;
19556             if (me.rendered) {
19557                 me.tpl[me.tplWriteMode](me.getTargetEl(), htmlOrData || {});
19558             }
19559         } else {
19560             me.html = Ext.isObject(htmlOrData) ? Ext.core.DomHelper.markup(htmlOrData) : htmlOrData;
19561             if (me.rendered) {
19562                 me.getTargetEl().update(me.html, loadScripts, cb);
19563             }
19564         }
19565
19566         if (me.rendered) {
19567             me.doComponentLayout();
19568         }
19569     },
19570
19571     
19572     setVisible : function(visible) {
19573         return this[visible ? 'show': 'hide']();
19574     },
19575
19576     
19577     isVisible: function(deep) {
19578         var me = this,
19579             child = me,
19580             visible = !me.hidden,
19581             ancestor = me.ownerCt;
19582
19583         
19584         me.hiddenAncestor = false;
19585         if (me.destroyed) {
19586             return false;
19587         }
19588
19589         if (deep && visible && me.rendered && ancestor) {
19590             while (ancestor) {
19591                 
19592                 
19593                 
19594                 
19595                 if (ancestor.hidden || (ancestor.collapsed &&
19596                         !(ancestor.getDockedItems && Ext.Array.contains(ancestor.getDockedItems(), child)))) {
19597                     
19598                     me.hiddenAncestor = ancestor;
19599                     visible = false;
19600                     break;
19601                 }
19602                 child = ancestor;
19603                 ancestor = ancestor.ownerCt;
19604             }
19605         }
19606         return visible;
19607     },
19608
19609     
19610     enable: function(silent) {
19611         var me = this;
19612
19613         if (me.rendered) {
19614             me.el.removeCls(me.disabledCls);
19615             me.el.dom.disabled = false;
19616             me.onEnable();
19617         }
19618
19619         me.disabled = false;
19620
19621         if (silent !== true) {
19622             me.fireEvent('enable', me);
19623         }
19624
19625         return me;
19626     },
19627
19628     
19629     disable: function(silent) {
19630         var me = this;
19631
19632         if (me.rendered) {
19633             me.el.addCls(me.disabledCls);
19634             me.el.dom.disabled = true;
19635             me.onDisable();
19636         }
19637
19638         me.disabled = true;
19639
19640         if (silent !== true) {
19641             me.fireEvent('disable', me);
19642         }
19643
19644         return me;
19645     },
19646     
19647     
19648     onEnable: function() {
19649         if (this.maskOnDisable) {
19650             this.el.unmask();
19651         }        
19652     },
19653
19654     
19655     onDisable : function() {
19656         if (this.maskOnDisable) {
19657             this.el.mask();
19658         }
19659     },
19660     
19661     
19662     isDisabled : function() {
19663         return this.disabled;
19664     },
19665
19666     
19667     setDisabled : function(disabled) {
19668         return this[disabled ? 'disable': 'enable']();
19669     },
19670
19671     
19672     isHidden : function() {
19673         return this.hidden;
19674     },
19675
19676     
19677     addCls : function(className) {
19678         var me = this;
19679         if (!className) {
19680             return me;
19681         }
19682         if (!Ext.isArray(className)){
19683             className = className.replace(me.trimRe, '').split(me.spacesRe);
19684         }
19685         if (me.rendered) {
19686             me.el.addCls(className);
19687         }
19688         else {
19689             me.additionalCls = Ext.Array.unique(me.additionalCls.concat(className));
19690         }
19691         return me;
19692     },
19693
19694     
19695     addClass : function() {
19696         return this.addCls.apply(this, arguments);
19697     },
19698
19699     
19700     removeCls : function(className) {
19701         var me = this;
19702
19703         if (!className) {
19704             return me;
19705         }
19706         if (!Ext.isArray(className)){
19707             className = className.replace(me.trimRe, '').split(me.spacesRe);
19708         }
19709         if (me.rendered) {
19710             me.el.removeCls(className);
19711         }
19712         else if (me.additionalCls.length) {
19713             Ext.each(className, function(cls) {
19714                 Ext.Array.remove(me.additionalCls, cls);
19715             });
19716         }
19717         return me;
19718     },
19719
19720     removeClass : function() {
19721         if (Ext.isDefined(Ext.global.console)) {
19722             Ext.global.console.warn('Ext.Component: removeClass has been deprecated. Please use removeCls.');
19723         }
19724         return this.removeCls.apply(this, arguments);
19725     },
19726
19727     addOverCls: function() {
19728         var me = this;
19729         if (!me.disabled) {
19730             me.el.addCls(me.overCls);
19731         }
19732     },
19733
19734     removeOverCls: function() {
19735         this.el.removeCls(this.overCls);
19736     },
19737
19738     addListener : function(element, listeners, scope, options) {
19739         var me = this,
19740             fn,
19741             option;
19742
19743         if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) {
19744             if (options.element) {
19745                 fn = listeners;
19746
19747                 listeners = {};
19748                 listeners[element] = fn;
19749                 element = options.element;
19750                 if (scope) {
19751                     listeners.scope = scope;
19752                 }
19753
19754                 for (option in options) {
19755                     if (options.hasOwnProperty(option)) {
19756                         if (me.eventOptionsRe.test(option)) {
19757                             listeners[option] = options[option];
19758                         }
19759                     }
19760                 }
19761             }
19762
19763             
19764             
19765             if (me[element] && me[element].on) {
19766                 me.mon(me[element], listeners);
19767             } else {
19768                 me.afterRenderEvents = me.afterRenderEvents || {};
19769                 me.afterRenderEvents[element] = listeners;
19770             }
19771         }
19772
19773         return me.mixins.observable.addListener.apply(me, arguments);
19774     },
19775
19776     
19777
19778     
19779     getBubbleTarget : function() {
19780         return this.ownerCt;
19781     },
19782
19783     
19784     isFloating : function() {
19785         return this.floating;
19786     },
19787
19788     
19789     isDraggable : function() {
19790         return !!this.draggable;
19791     },
19792
19793     
19794     isDroppable : function() {
19795         return !!this.droppable;
19796     },
19797
19798     
19799     onAdded : function(container, pos) {
19800         this.ownerCt = container;
19801         this.fireEvent('added', this, container, pos);
19802     },
19803
19804     
19805     onRemoved : function() {
19806         var me = this;
19807
19808         me.fireEvent('removed', me, me.ownerCt);
19809         delete me.ownerCt;
19810     },
19811
19812     
19813     beforeDestroy : Ext.emptyFn,
19814     
19815     
19816     onResize : Ext.emptyFn,
19817
19818     
19819     setSize : function(width, height) {
19820         var me = this,
19821             layoutCollection;
19822
19823         
19824         if (Ext.isObject(width)) {
19825             height = width.height;
19826             width  = width.width;
19827         }
19828
19829         
19830         if (Ext.isNumber(width)) {
19831             width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
19832         }
19833         if (Ext.isNumber(height)) {
19834             height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
19835         }
19836
19837         if (!me.rendered || !me.isVisible()) {
19838             
19839             if (me.hiddenAncestor) {
19840                 layoutCollection = me.hiddenAncestor.layoutOnShow;
19841                 layoutCollection.remove(me);
19842                 layoutCollection.add(me);
19843             }
19844             me.needsLayout = {
19845                 width: width,
19846                 height: height,
19847                 isSetSize: true
19848             };
19849             if (!me.rendered) {
19850                 me.width  = (width !== undefined) ? width : me.width;
19851                 me.height = (height !== undefined) ? height : me.height;
19852             }
19853             return me;
19854         }
19855         me.doComponentLayout(width, height, true);
19856
19857         return me;
19858     },
19859
19860     setCalculatedSize : function(width, height, ownerCt) {
19861         var me = this,
19862             layoutCollection;
19863
19864         
19865         if (Ext.isObject(width)) {
19866             ownerCt = width.ownerCt;
19867             height = width.height;
19868             width  = width.width;
19869         }
19870
19871         
19872         if (Ext.isNumber(width)) {
19873             width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
19874         }
19875         if (Ext.isNumber(height)) {
19876             height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
19877         }
19878
19879         if (!me.rendered || !me.isVisible()) {
19880             
19881             if (me.hiddenAncestor) {
19882                 layoutCollection = me.hiddenAncestor.layoutOnShow;
19883                 layoutCollection.remove(me);
19884                 layoutCollection.add(me);
19885             }
19886             me.needsLayout = {
19887                 width: width,
19888                 height: height,
19889                 isSetSize: false,
19890                 ownerCt: ownerCt
19891             };
19892             return me;
19893         }
19894         me.doComponentLayout(width, height, false, ownerCt);
19895
19896         return me;
19897     },
19898
19899     
19900     doComponentLayout : function(width, height, isSetSize, ownerCt) {
19901         var me = this,
19902             componentLayout = me.getComponentLayout();
19903
19904         
19905         
19906         
19907         if (me.rendered && componentLayout) {
19908             width = (width !== undefined) ? width : me.width;
19909             height = (height !== undefined) ? height : me.height;
19910             if (isSetSize) {
19911                 me.width = width;
19912                 me.height = height;
19913             }
19914
19915             componentLayout.layout(width, height, isSetSize, ownerCt);
19916         }
19917         return me;
19918     },
19919
19920     
19921     setComponentLayout : function(layout) {
19922         var currentLayout = this.componentLayout;
19923         if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
19924             currentLayout.setOwner(null);
19925         }
19926         this.componentLayout = layout;
19927         layout.setOwner(this);
19928     },
19929
19930     getComponentLayout : function() {
19931         var me = this;
19932
19933         if (!me.componentLayout || !me.componentLayout.isLayout) {
19934             me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));
19935         }
19936         return me.componentLayout;
19937     },
19938
19939     
19940     afterComponentLayout: function(width, height, isSetSize, layoutOwner) {
19941         this.fireEvent('resize', this, width, height);
19942     },
19943
19944     
19945     beforeComponentLayout: function(width, height, isSetSize, layoutOwner) {
19946         return true;
19947     },
19948
19949     
19950     setPosition : function(x, y) {
19951         var me = this;
19952
19953         if (Ext.isObject(x)) {
19954             y = x.y;
19955             x = x.x;
19956         }
19957
19958         if (!me.rendered) {
19959             return me;
19960         }
19961
19962         if (x !== undefined || y !== undefined) {
19963             me.el.setBox(x, y);
19964             me.onPosition(x, y);
19965             me.fireEvent('move', me, x, y);
19966         }
19967         return me;
19968     },
19969
19970     
19971     onPosition: Ext.emptyFn,
19972
19973     
19974     setWidth : function(width) {
19975         return this.setSize(width);
19976     },
19977
19978     
19979     setHeight : function(height) {
19980         return this.setSize(undefined, height);
19981     },
19982
19983     
19984     getSize : function() {
19985         return this.el.getSize();
19986     },
19987
19988     
19989     getWidth : function() {
19990         return this.el.getWidth();
19991     },
19992
19993     
19994     getHeight : function() {
19995         return this.el.getHeight();
19996     },
19997
19998     
19999     getLoader: function(){
20000         var me = this,
20001             autoLoad = me.autoLoad ? (Ext.isObject(me.autoLoad) ? me.autoLoad : {url: me.autoLoad}) : null,
20002             loader = me.loader || autoLoad;
20003
20004         if (loader) {
20005             if (!loader.isLoader) {
20006                 me.loader = Ext.create('Ext.ComponentLoader', Ext.apply({
20007                     target: me,
20008                     autoLoad: autoLoad
20009                 }, loader));
20010             } else {
20011                 loader.setTarget(me);
20012             }
20013             return me.loader;
20014
20015         }
20016         return null;
20017     },
20018
20019     
20020     setLoading : function(load, targetEl) {
20021         var me = this,
20022             config;
20023
20024         if (me.rendered) {
20025             if (load !== false && !me.collapsed) {
20026                 if (Ext.isObject(load)) {
20027                     config = load;
20028                 }
20029                 else if (Ext.isString(load)) {
20030                     config = {msg: load};
20031                 }
20032                 else {
20033                     config = {};
20034                 }
20035                 me.loadMask = me.loadMask || Ext.create('Ext.LoadMask', targetEl ? me.getTargetEl() : me.el, config);
20036                 me.loadMask.show();
20037             } else if (me.loadMask) {
20038                 Ext.destroy(me.loadMask);
20039                 me.loadMask = null;
20040             }
20041         }
20042
20043         return me.loadMask;
20044     },
20045
20046     
20047     setDocked : function(dock, layoutParent) {
20048         var me = this;
20049
20050         me.dock = dock;
20051         if (layoutParent && me.ownerCt && me.rendered) {
20052             me.ownerCt.doComponentLayout();
20053         }
20054         return me;
20055     },
20056
20057     onDestroy : function() {
20058         var me = this;
20059
20060         if (me.monitorResize && Ext.EventManager.resizeEvent) {
20061             Ext.EventManager.resizeEvent.removeListener(me.setSize, me);
20062         }
20063         Ext.destroy(me.componentLayout, me.loadMask);
20064     },
20065
20066     
20067     destroy : function() {
20068         var me = this;
20069
20070         if (!me.isDestroyed) {
20071             if (me.fireEvent('beforedestroy', me) !== false) {
20072                 me.destroying = true;
20073                 me.beforeDestroy();
20074
20075                 if (me.floating) {
20076                     delete me.floatParent;
20077                     
20078                     
20079                     if (me.zIndexManager) {
20080                         me.zIndexManager.unregister(me);
20081                     }
20082                 } else if (me.ownerCt && me.ownerCt.remove) {
20083                     me.ownerCt.remove(me, false);
20084                 }
20085
20086                 if (me.rendered) {
20087                     me.el.remove();
20088                 }
20089
20090                 me.onDestroy();
20091
20092                 
20093                 Ext.destroy(me.plugins);
20094
20095                 Ext.ComponentManager.unregister(me);
20096                 me.fireEvent('destroy', me);
20097
20098                 me.mixins.state.destroy.call(me);
20099
20100                 me.clearListeners();
20101                 me.destroying = false;
20102                 me.isDestroyed = true;
20103             }
20104         }
20105     },
20106
20107     
20108     getPlugin: function(pluginId) {
20109         var i = 0,
20110             plugins = this.plugins,
20111             ln = plugins.length;
20112         for (; i < ln; i++) {
20113             if (plugins[i].pluginId === pluginId) {
20114                 return plugins[i];
20115             }
20116         }
20117     },
20118     
20119     
20120     isDescendantOf: function(container) {
20121         return !!this.findParentBy(function(p){
20122             return p === container;
20123         });
20124     }
20125 }, function() {
20126     this.createAlias({
20127         on: 'addListener',
20128         prev: 'previousSibling',
20129         next: 'nextSibling'
20130     });
20131 });
20132
20133
20134 Ext.define('Ext.AbstractPlugin', {
20135     disabled: false,
20136     
20137     constructor: function(config) {
20138         if (!config.cmp && Ext.global.console) {
20139             Ext.global.console.warn("Attempted to attach a plugin ");
20140         }
20141         Ext.apply(this, config);
20142     },
20143     
20144     getCmp: function() {
20145         return this.cmp;
20146     },
20147
20148     
20149     init: Ext.emptyFn,
20150
20151     
20152     destroy: Ext.emptyFn,
20153
20154     
20155     enable: function() {
20156         this.disabled = false;
20157     },
20158
20159     
20160     disable: function() {
20161         this.disabled = true;
20162     }
20163 });
20164
20165
20166 Ext.define('Ext.data.Connection', {
20167     mixins: {
20168         observable: 'Ext.util.Observable'
20169     },
20170
20171     statics: {
20172         requestId: 0
20173     },
20174
20175     url: null,
20176     async: true,
20177     method: null,
20178     username: '',
20179     password: '',
20180
20181     
20182     disableCaching: true,
20183
20184     
20185     disableCachingParam: '_dc',
20186
20187     
20188     timeout : 30000,
20189
20190     
20191
20192     useDefaultHeader : true,
20193     defaultPostHeader : 'application/x-www-form-urlencoded; charset=UTF-8',
20194     useDefaultXhrHeader : true,
20195     defaultXhrHeader : 'XMLHttpRequest',
20196
20197     constructor : function(config) {
20198         config = config || {};
20199         Ext.apply(this, config);
20200
20201         this.addEvents(
20202             
20203             'beforerequest',
20204             
20205             'requestcomplete',
20206             
20207             'requestexception'
20208         );
20209         this.requests = {};
20210         this.mixins.observable.constructor.call(this);
20211     },
20212
20213     
20214     request : function(options) {
20215         options = options || {};
20216         var me = this,
20217             scope = options.scope || window,
20218             username = options.username || me.username,
20219             password = options.password || me.password || '',
20220             async,
20221             requestOptions,
20222             request,
20223             headers,
20224             xhr;
20225
20226         if (me.fireEvent('beforerequest', me, options) !== false) {
20227
20228             requestOptions = me.setOptions(options, scope);
20229
20230             if (this.isFormUpload(options) === true) {
20231                 this.upload(options.form, requestOptions.url, requestOptions.data, options);
20232                 return null;
20233             }
20234
20235             
20236             if (options.autoAbort === true || me.autoAbort) {
20237                 me.abort();
20238             }
20239
20240             
20241             xhr = this.getXhrInstance();
20242
20243             async = options.async !== false ? (options.async || me.async) : false;
20244
20245             
20246             if (username) {
20247                 xhr.open(requestOptions.method, requestOptions.url, async, username, password);
20248             } else {
20249                 xhr.open(requestOptions.method, requestOptions.url, async);
20250             }
20251
20252             headers = me.setupHeaders(xhr, options, requestOptions.data, requestOptions.params);
20253
20254             
20255             request = {
20256                 id: ++Ext.data.Connection.requestId,
20257                 xhr: xhr,
20258                 headers: headers,
20259                 options: options,
20260                 async: async,
20261                 timeout: setTimeout(function() {
20262                     request.timedout = true;
20263                     me.abort(request);
20264                 }, options.timeout || me.timeout)
20265             };
20266             me.requests[request.id] = request;
20267
20268             
20269             if (async) {
20270                 xhr.onreadystatechange = Ext.Function.bind(me.onStateChange, me, [request]);
20271             }
20272
20273             
20274             xhr.send(requestOptions.data);
20275             if (!async) {
20276                 return this.onComplete(request);
20277             }
20278             return request;
20279         } else {
20280             Ext.callback(options.callback, options.scope, [options, undefined, undefined]);
20281             return null;
20282         }
20283     },
20284
20285     
20286     upload: function(form, url, params, options){
20287         form = Ext.getDom(form);
20288         options = options || {};
20289
20290         var id = Ext.id(),
20291                 frame = document.createElement('iframe'),
20292                 hiddens = [],
20293                 encoding = 'multipart/form-data',
20294                 buf = {
20295                     target: form.target,
20296                     method: form.method,
20297                     encoding: form.encoding,
20298                     enctype: form.enctype,
20299                     action: form.action
20300                 }, hiddenItem;
20301
20302         
20303         Ext.fly(frame).set({
20304             id: id,
20305             name: id,
20306             cls: Ext.baseCSSPrefix + 'hide-display',
20307             src: Ext.SSL_SECURE_URL
20308         });
20309
20310         document.body.appendChild(frame);
20311
20312         
20313         if (document.frames) {
20314            document.frames[id].name = id;
20315         }
20316
20317         Ext.fly(form).set({
20318             target: id,
20319             method: 'POST',
20320             enctype: encoding,
20321             encoding: encoding,
20322             action: url || buf.action
20323         });
20324
20325         
20326         if (params) {
20327             Ext.iterate(Ext.Object.fromQueryString(params), function(name, value){
20328                 hiddenItem = document.createElement('input');
20329                 Ext.fly(hiddenItem).set({
20330                     type: 'hidden',
20331                     value: value,
20332                     name: name
20333                 });
20334                 form.appendChild(hiddenItem);
20335                 hiddens.push(hiddenItem);
20336             });
20337         }
20338
20339         Ext.fly(frame).on('load', Ext.Function.bind(this.onUploadComplete, this, [frame, options]), null, {single: true});
20340         form.submit();
20341
20342         Ext.fly(form).set(buf);
20343         Ext.each(hiddens, function(h) {
20344             Ext.removeNode(h);
20345         });
20346     },
20347
20348     onUploadComplete: function(frame, options){
20349         var me = this,
20350             
20351             response = {
20352                 responseText: '',
20353                 responseXML: null
20354             }, doc, firstChild;
20355
20356         try {
20357             doc = frame.contentWindow.document || frame.contentDocument || window.frames[id].document;
20358             if (doc) {
20359                 if (doc.body) {
20360                     if (/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)) { 
20361                         response.responseText = firstChild.value;
20362                     } else {
20363                         response.responseText = doc.body.innerHTML;
20364                     }
20365                 }
20366                 
20367                 response.responseXML = doc.XMLDocument || doc;
20368             }
20369         } catch (e) {
20370         }
20371
20372         me.fireEvent('requestcomplete', me, response, options);
20373
20374         Ext.callback(options.success, options.scope, [response, options]);
20375         Ext.callback(options.callback, options.scope, [options, true, response]);
20376
20377         setTimeout(function(){
20378             Ext.removeNode(frame);
20379         }, 100);
20380     },
20381
20382     
20383     isFormUpload: function(options){
20384         var form = this.getForm(options);
20385         if (form) {
20386             return (options.isUpload || (/multipart\/form-data/i).test(form.getAttribute('enctype')));
20387         }
20388         return false;
20389     },
20390
20391     
20392     getForm: function(options){
20393         return Ext.getDom(options.form) || null;
20394     },
20395
20396     
20397     setOptions: function(options, scope){
20398         var me =  this,
20399             params = options.params || {},
20400             extraParams = me.extraParams,
20401             urlParams = options.urlParams,
20402             url = options.url || me.url,
20403             jsonData = options.jsonData,
20404             method,
20405             disableCache,
20406             data;
20407
20408
20409         
20410         if (Ext.isFunction(params)) {
20411             params = params.call(scope, options);
20412         }
20413
20414         
20415         if (Ext.isFunction(url)) {
20416             url = url.call(scope, options);
20417         }
20418
20419         url = this.setupUrl(options, url);
20420
20421         if (!url) {
20422             Ext.Error.raise({
20423                 options: options,
20424                 msg: 'No URL specified'
20425             });
20426         }
20427
20428         
20429         data = options.rawData || options.xmlData || jsonData || null;
20430         if (jsonData && !Ext.isPrimitive(jsonData)) {
20431             data = Ext.encode(data);
20432         }
20433
20434         
20435         if (Ext.isObject(params)) {
20436             params = Ext.Object.toQueryString(params);
20437         }
20438
20439         if (Ext.isObject(extraParams)) {
20440             extraParams = Ext.Object.toQueryString(extraParams);
20441         }
20442
20443         params = params + ((extraParams) ? ((params) ? '&' : '') + extraParams : '');
20444
20445         urlParams = Ext.isObject(urlParams) ? Ext.Object.toQueryString(urlParams) : urlParams;
20446
20447         params = this.setupParams(options, params);
20448
20449         
20450         method = (options.method || me.method || ((params || data) ? 'POST' : 'GET')).toUpperCase();
20451         this.setupMethod(options, method);
20452
20453
20454         disableCache = options.disableCaching !== false ? (options.disableCaching || me.disableCaching) : false;
20455         
20456         if (method === 'GET' && disableCache) {
20457             url = Ext.urlAppend(url, (options.disableCachingParam || me.disableCachingParam) + '=' + (new Date().getTime()));
20458         }
20459
20460         
20461         if ((method == 'GET' || data) && params) {
20462             url = Ext.urlAppend(url, params);
20463             params = null;
20464         }
20465
20466         
20467         if (urlParams) {
20468             url = Ext.urlAppend(url, urlParams);
20469         }
20470
20471         return {
20472             url: url,
20473             method: method,
20474             data: data || params || null
20475         };
20476     },
20477
20478     
20479     setupUrl: function(options, url){
20480         var form = this.getForm(options);
20481         if (form) {
20482             url = url || form.action;
20483         }
20484         return url;
20485     },
20486
20487
20488     
20489     setupParams: function(options, params) {
20490         var form = this.getForm(options),
20491             serializedForm;
20492         if (form && !this.isFormUpload(options)) {
20493             serializedForm = Ext.core.Element.serializeForm(form);
20494             params = params ? (params + '&' + serializedForm) : serializedForm;
20495         }
20496         return params;
20497     },
20498
20499     
20500     setupMethod: function(options, method){
20501         if (this.isFormUpload(options)) {
20502             return 'POST';
20503         }
20504         return method;
20505     },
20506
20507     
20508     setupHeaders: function(xhr, options, data, params){
20509         var me = this,
20510             headers = Ext.apply({}, options.headers || {}, me.defaultHeaders || {}),
20511             contentType = me.defaultPostHeader,
20512             jsonData = options.jsonData,
20513             xmlData = options.xmlData,
20514             key,
20515             header;
20516
20517         if (!headers['Content-Type'] && (data || params)) {
20518             if (data) {
20519                 if (options.rawData) {
20520                     contentType = 'text/plain';
20521                 } else {
20522                     if (xmlData && Ext.isDefined(xmlData)) {
20523                         contentType = 'text/xml';
20524                     } else if (jsonData && Ext.isDefined(jsonData)) {
20525                         contentType = 'application/json';
20526                     }
20527                 }
20528             }
20529             headers['Content-Type'] = contentType;
20530         }
20531
20532         if (me.useDefaultXhrHeader && !headers['X-Requested-With']) {
20533             headers['X-Requested-With'] = me.defaultXhrHeader;
20534         }
20535         
20536         try{
20537             for (key in headers) {
20538                 if (headers.hasOwnProperty(key)) {
20539                     header = headers[key];
20540                     xhr.setRequestHeader(key, header);
20541                 }
20542
20543             }
20544         } catch(e) {
20545             me.fireEvent('exception', key, header);
20546         }
20547         return headers;
20548     },
20549
20550     
20551     getXhrInstance: (function(){
20552         var options = [function(){
20553             return new XMLHttpRequest();
20554         }, function(){
20555             return new ActiveXObject('MSXML2.XMLHTTP.3.0');
20556         }, function(){
20557             return new ActiveXObject('MSXML2.XMLHTTP');
20558         }, function(){
20559             return new ActiveXObject('Microsoft.XMLHTTP');
20560         }], i = 0,
20561             len = options.length,
20562             xhr;
20563
20564         for(; i < len; ++i) {
20565             try{
20566                 xhr = options[i];
20567                 xhr();
20568                 break;
20569             }catch(e){}
20570         }
20571         return xhr;
20572     })(),
20573
20574     
20575     isLoading : function(request) {
20576         if (!(request && request.xhr)) {
20577             return false;
20578         }
20579         
20580         var state = request.xhr.readyState;
20581         return !(state === 0 || state == 4);
20582     },
20583
20584     
20585     abort : function(request) {
20586         var me = this,
20587             requests = me.requests,
20588             id;
20589
20590         if (request && me.isLoading(request)) {
20591             
20592             request.xhr.onreadystatechange = null;
20593             request.xhr.abort();
20594             me.clearTimeout(request);
20595             if (!request.timedout) {
20596                 request.aborted = true;
20597             }
20598             me.onComplete(request);
20599             me.cleanup(request);
20600         } else if (!request) {
20601             for(id in requests) {
20602                 if (requests.hasOwnProperty(id)) {
20603                     me.abort(requests[id]);
20604                 }
20605             }
20606         }
20607     },
20608
20609     
20610     onStateChange : function(request) {
20611         if (request.xhr.readyState == 4) {
20612             this.clearTimeout(request);
20613             this.onComplete(request);
20614             this.cleanup(request);
20615         }
20616     },
20617
20618     
20619     clearTimeout: function(request){
20620         clearTimeout(request.timeout);
20621         delete request.timeout;
20622     },
20623
20624     
20625     cleanup: function(request){
20626         request.xhr = null;
20627         delete request.xhr;
20628     },
20629
20630     
20631     onComplete : function(request) {
20632         var me = this,
20633             options = request.options,
20634             result = me.parseStatus(request.xhr.status),
20635             success = result.success,
20636             response;
20637
20638         if (success) {
20639             response = me.createResponse(request);
20640             me.fireEvent('requestcomplete', me, response, options);
20641             Ext.callback(options.success, options.scope, [response, options]);
20642         } else {
20643             if (result.isException || request.aborted || request.timedout) {
20644                 response = me.createException(request);
20645             } else {
20646                 response = me.createResponse(request);
20647             }
20648             me.fireEvent('requestexception', me, response, options);
20649             Ext.callback(options.failure, options.scope, [response, options]);
20650         }
20651         Ext.callback(options.callback, options.scope, [options, success, response]);
20652         delete me.requests[request.id];
20653         return response;
20654     },
20655
20656     
20657     parseStatus: function(status) {
20658         
20659         status = status == 1223 ? 204 : status;
20660
20661         var success = (status >= 200 && status < 300) || status == 304,
20662             isException = false;
20663
20664         if (!success) {
20665             switch (status) {
20666                 case 12002:
20667                 case 12029:
20668                 case 12030:
20669                 case 12031:
20670                 case 12152:
20671                 case 13030:
20672                     isException = true;
20673                     break;
20674             }
20675         }
20676         return {
20677             success: success,
20678             isException: isException
20679         };
20680     },
20681
20682     
20683     createResponse : function(request) {
20684         var xhr = request.xhr,
20685             headers = {},
20686             lines = xhr.getAllResponseHeaders().replace(/\r\n/g, '\n').split('\n'),
20687             count = lines.length,
20688             line, index, key, value, response;
20689
20690         while (count--) {
20691             line = lines[count];
20692             index = line.indexOf(':');
20693             if(index >= 0) {
20694                 key = line.substr(0, index).toLowerCase();
20695                 if (line.charAt(index + 1) == ' ') {
20696                     ++index;
20697                 }
20698                 headers[key] = line.substr(index + 1);
20699             }
20700         }
20701
20702         request.xhr = null;
20703         delete request.xhr;
20704
20705         response = {
20706             request: request,
20707             requestId : request.id,
20708             status : xhr.status,
20709             statusText : xhr.statusText,
20710             getResponseHeader : function(header){ return headers[header.toLowerCase()]; },
20711             getAllResponseHeaders : function(){ return headers; },
20712             responseText : xhr.responseText,
20713             responseXML : xhr.responseXML
20714         };
20715
20716         
20717         
20718         xhr = null;
20719         return response;
20720     },
20721
20722     
20723     createException : function(request) {
20724         return {
20725             request : request,
20726             requestId : request.id,
20727             status : request.aborted ? -1 : 0,
20728             statusText : request.aborted ? 'transaction aborted' : 'communication failure',
20729             aborted: request.aborted,
20730             timedout: request.timedout
20731         };
20732     }
20733 });
20734
20735
20736 Ext.define('Ext.Ajax', {
20737     extend: 'Ext.data.Connection',
20738     singleton: true,
20739
20740     
20741     
20742     
20743     
20744     
20745     
20746
20747     
20748
20749     
20750     
20751     
20752     
20753     
20754     
20755
20756     
20757     autoAbort : false
20758 });
20759
20760 Ext.define('Ext.data.Association', {
20761     
20762
20763     
20764
20765     
20766     primaryKey: 'id',
20767
20768     
20769     
20770     
20771
20772     defaultReaderType: 'json',
20773
20774     statics: {
20775         create: function(association){
20776             if (!association.isAssociation) {
20777                 if (Ext.isString(association)) {
20778                     association = {
20779                         type: association
20780                     };
20781                 }
20782
20783                 switch (association.type) {
20784                     case 'belongsTo':
20785                         return Ext.create('Ext.data.BelongsToAssociation', association);
20786                     case 'hasMany':
20787                         return Ext.create('Ext.data.HasManyAssociation', association);
20788                     
20789
20790
20791                     default:
20792                         Ext.Error.raise('Unknown Association type: "' + association.type + '"');
20793                 }
20794             }
20795             return association;
20796         }
20797     },
20798
20799     constructor: function(config) {
20800         Ext.apply(this, config);
20801
20802         var types           = Ext.ModelManager.types,
20803             ownerName       = config.ownerModel,
20804             associatedName  = config.associatedModel,
20805             ownerModel      = types[ownerName],
20806             associatedModel = types[associatedName],
20807             ownerProto;
20808
20809         if (ownerModel === undefined) {
20810             Ext.Error.raise("The configured ownerModel was not valid (you tried " + ownerName + ")");
20811         }
20812         if (associatedModel === undefined) {
20813             Ext.Error.raise("The configured associatedModel was not valid (you tried " + associatedName + ")");
20814         }
20815
20816         this.ownerModel = ownerModel;
20817         this.associatedModel = associatedModel;
20818
20819         
20820
20821         
20822
20823         Ext.applyIf(this, {
20824             ownerName : ownerName,
20825             associatedName: associatedName
20826         });
20827     },
20828
20829     
20830     getReader: function(){
20831         var me = this,
20832             reader = me.reader,
20833             model = me.associatedModel;
20834
20835         if (reader) {
20836             if (Ext.isString(reader)) {
20837                 reader = {
20838                     type: reader
20839                 };
20840             }
20841             if (reader.isReader) {
20842                 reader.setModel(model);
20843             } else {
20844                 Ext.applyIf(reader, {
20845                     model: model,
20846                     type : me.defaultReaderType
20847                 });
20848             }
20849             me.reader = Ext.createByAlias('reader.' + reader.type, reader);
20850         }
20851         return me.reader || null;
20852     }
20853 });
20854
20855
20856 Ext.define('Ext.ModelManager', {
20857     extend: 'Ext.AbstractManager',
20858     alternateClassName: 'Ext.ModelMgr',
20859     requires: ['Ext.data.Association'],
20860     
20861     singleton: true,
20862     
20863     typeName: 'mtype',
20864     
20865     
20866     associationStack: [],
20867     
20868     
20869     registerType: function(name, config) {
20870         var proto = config.prototype,
20871             model;
20872         if (proto && proto.isModel) {
20873             
20874             model = config;
20875         } else {
20876             
20877             if (!config.extend) {
20878                 config.extend = 'Ext.data.Model';
20879             }
20880             model = Ext.define(name, config);
20881         }
20882         this.types[name] = model;
20883         return model;
20884     },
20885     
20886     
20887     onModelDefined: function(model) {
20888         var stack  = this.associationStack,
20889             length = stack.length,
20890             create = [],
20891             association, i, created;
20892         
20893         for (i = 0; i < length; i++) {
20894             association = stack[i];
20895             
20896             if (association.associatedModel == model.modelName) {
20897                 create.push(association);
20898             }
20899         }
20900         
20901         for (i = 0, length = create.length; i < length; i++) {
20902             created = create[i];
20903             this.types[created.ownerModel].prototype.associations.add(Ext.data.Association.create(created));
20904             Ext.Array.remove(stack, created);
20905         }
20906     },
20907     
20908     
20909     registerDeferredAssociation: function(association){
20910         this.associationStack.push(association);
20911     },
20912     
20913     
20914     getModel: function(id) {
20915         var model = id;
20916         if (typeof model == 'string') {
20917             model = this.types[model];
20918         }
20919         return model;
20920     },
20921     
20922     
20923     create: function(config, name, id) {
20924         var con = typeof name == 'function' ? name : this.types[name || config.name];
20925         
20926         return new con(config, id);
20927     }
20928 }, function() {
20929     
20930     
20931     Ext.regModel = function() {
20932         if (Ext.isDefined(Ext.global.console)) {
20933             Ext.global.console.warn('Ext.regModel has been deprecated. Models can now be created by extending Ext.data.Model: Ext.define("MyModel", {extend: "Ext.data.Model", fields: []});.');
20934         }
20935         return this.ModelManager.registerType.apply(this.ModelManager, arguments);
20936     };
20937 });
20938
20939   
20940 Ext.define('Ext.app.Controller', {
20941     
20942
20943     mixins: {
20944         observable: 'Ext.util.Observable'
20945     },
20946
20947     onClassExtended: function(cls, data) {
20948         var className = Ext.getClassName(cls),
20949             match = className.match(/^(.*)\.controller\./);
20950
20951         if (match !== null) {
20952             var namespace = Ext.Loader.getPrefix(className) || match[1],
20953                 onBeforeClassCreated = data.onBeforeClassCreated,
20954                 requires = [],
20955                 modules = ['model', 'view', 'store'],
20956                 prefix;
20957
20958             data.onBeforeClassCreated = function(cls, data) {
20959                 var i, ln, module,
20960                     items, j, subLn, item;
20961
20962                 for (i = 0,ln = modules.length; i < ln; i++) {
20963                     module = modules[i];
20964
20965                     items = Ext.Array.from(data[module + 's']);
20966
20967                     for (j = 0,subLn = items.length; j < subLn; j++) {
20968                         item = items[j];
20969
20970                         prefix = Ext.Loader.getPrefix(item);
20971
20972                         if (prefix === '' || prefix === item) {
20973                             requires.push(namespace + '.' + module + '.' + item);
20974                         }
20975                         else {
20976                             requires.push(item);
20977                         }
20978                     }
20979                 }
20980
20981                 Ext.require(requires, Ext.Function.pass(onBeforeClassCreated, arguments, this));
20982             };
20983         }
20984     },
20985
20986     constructor: function(config) {
20987         this.mixins.observable.constructor.call(this, config);
20988
20989         Ext.apply(this, config || {});
20990
20991         this.createGetters('model', this.models);
20992         this.createGetters('store', this.stores);
20993         this.createGetters('view', this.views);
20994
20995         if (this.refs) {
20996             this.ref(this.refs);
20997         }
20998     },
20999
21000     
21001     init: function(application) {},
21002     
21003     onLaunch: function(application) {},
21004
21005     createGetters: function(type, refs) {
21006         type = Ext.String.capitalize(type);
21007         Ext.Array.each(refs, function(ref) {
21008             var fn = 'get',
21009                 parts = ref.split('.');
21010
21011             
21012             Ext.Array.each(parts, function(part) {
21013                 fn += Ext.String.capitalize(part);
21014             });
21015             fn += type;
21016
21017             if (!this[fn]) {
21018                 this[fn] = Ext.Function.pass(this['get' + type], [ref], this);
21019             }
21020             
21021             this[fn](ref);
21022         },
21023         this);
21024     },
21025
21026     ref: function(refs) {
21027         var me = this;
21028         refs = Ext.Array.from(refs);
21029         Ext.Array.each(refs, function(info) {
21030             var ref = info.ref,
21031                 fn = 'get' + Ext.String.capitalize(ref);
21032             if (!me[fn]) {
21033                 me[fn] = Ext.Function.pass(me.getRef, [ref, info], me);
21034             }
21035         });
21036     },
21037
21038     getRef: function(ref, info, config) {
21039         this.refCache = this.refCache || {};
21040         info = info || {};
21041         config = config || {};
21042
21043         Ext.apply(info, config);
21044
21045         if (info.forceCreate) {
21046             return Ext.ComponentManager.create(info, 'component');
21047         }
21048
21049         var me = this,
21050             selector = info.selector,
21051             cached = me.refCache[ref];
21052
21053         if (!cached) {
21054             me.refCache[ref] = cached = Ext.ComponentQuery.query(info.selector)[0];
21055             if (!cached && info.autoCreate) {
21056                 me.refCache[ref] = cached = Ext.ComponentManager.create(info, 'component');
21057             }
21058             if (cached) {
21059                 cached.on('beforedestroy', function() {
21060                     me.refCache[ref] = null;
21061                 });
21062             }
21063         }
21064
21065         return cached;
21066     },
21067
21068     control: function(selectors, listeners) {
21069         this.application.control(selectors, listeners, this);
21070     },
21071
21072     getController: function(name) {
21073         return this.application.getController(name);
21074     },
21075
21076     getStore: function(name) {
21077         return this.application.getStore(name);
21078     },
21079
21080     getModel: function(model) {
21081         return this.application.getModel(model);
21082     },
21083
21084     getView: function(view) {
21085         return this.application.getView(view);
21086     }
21087 });
21088
21089
21090 Ext.define('Ext.data.SortTypes', {
21091     
21092     singleton: true,
21093     
21094     
21095     none : function(s) {
21096         return s;
21097     },
21098
21099     
21100     stripTagsRE : /<\/?[^>]+>/gi,
21101
21102     
21103     asText : function(s) {
21104         return String(s).replace(this.stripTagsRE, "");
21105     },
21106
21107     
21108     asUCText : function(s) {
21109         return String(s).toUpperCase().replace(this.stripTagsRE, "");
21110     },
21111
21112     
21113     asUCString : function(s) {
21114         return String(s).toUpperCase();
21115     },
21116
21117     
21118     asDate : function(s) {
21119         if(!s){
21120             return 0;
21121         }
21122         if(Ext.isDate(s)){
21123             return s.getTime();
21124         }
21125         return Date.parse(String(s));
21126     },
21127
21128     
21129     asFloat : function(s) {
21130         var val = parseFloat(String(s).replace(/,/g, ""));
21131         return isNaN(val) ? 0 : val;
21132     },
21133
21134     
21135     asInt : function(s) {
21136         var val = parseInt(String(s).replace(/,/g, ""), 10);
21137         return isNaN(val) ? 0 : val;
21138     }
21139 });
21140
21141 Ext.define('Ext.data.Errors', {
21142     extend: 'Ext.util.MixedCollection',
21143     
21144     
21145     isValid: function() {
21146         return this.length === 0;
21147     },
21148     
21149     
21150     getByField: function(fieldName) {
21151         var errors = [],
21152             error, field, i;
21153             
21154         for (i = 0; i < this.length; i++) {
21155             error = this.items[i];
21156             
21157             if (error.field == fieldName) {
21158                 errors.push(error);
21159             }
21160         }
21161         
21162         return errors;
21163     }
21164 });
21165
21166
21167 Ext.define('Ext.data.Operation', {
21168     
21169     synchronous: true,
21170     
21171     
21172     action: undefined,
21173     
21174     
21175     filters: undefined,
21176     
21177     
21178     sorters: undefined,
21179     
21180     
21181     group: undefined,
21182     
21183     
21184     start: undefined,
21185     
21186     
21187     limit: undefined,
21188     
21189     
21190     batch: undefined,
21191         
21192     
21193     started: false,
21194     
21195     
21196     running: false,
21197     
21198     
21199     complete: false,
21200     
21201     
21202     success: undefined,
21203     
21204     
21205     exception: false,
21206     
21207     
21208     error: undefined,
21209     
21210     constructor: function(config) {
21211         Ext.apply(this, config || {});
21212     },
21213     
21214     
21215     setStarted: function() {
21216         this.started = true;
21217         this.running = true;
21218     },
21219     
21220     
21221     setCompleted: function() {
21222         this.complete = true;
21223         this.running  = false;
21224     },
21225     
21226     
21227     setSuccessful: function() {
21228         this.success = true;
21229     },
21230     
21231     
21232     setException: function(error) {
21233         this.exception = true;
21234         this.success = false;
21235         this.running = false;
21236         this.error = error;
21237     },
21238     
21239     
21240     hasException: function() {
21241         return this.exception === true;
21242     },
21243     
21244     
21245     getError: function() {
21246         return this.error;
21247     },
21248     
21249     
21250     getRecords: function() {
21251         var resultSet = this.getResultSet();
21252         
21253         return (resultSet === undefined ? this.records : resultSet.records);
21254     },
21255     
21256     
21257     getResultSet: function() {
21258         return this.resultSet;
21259     },
21260     
21261     
21262     isStarted: function() {
21263         return this.started === true;
21264     },
21265     
21266     
21267     isRunning: function() {
21268         return this.running === true;
21269     },
21270     
21271     
21272     isComplete: function() {
21273         return this.complete === true;
21274     },
21275     
21276     
21277     wasSuccessful: function() {
21278         return this.isComplete() && this.success === true;
21279     },
21280     
21281     
21282     setBatch: function(batch) {
21283         this.batch = batch;
21284     },
21285     
21286     
21287     allowWrite: function() {
21288         return this.action != 'read';
21289     }
21290 });
21291
21292 Ext.define('Ext.data.validations', {
21293     singleton: true,
21294     
21295     
21296     presenceMessage: 'must be present',
21297     
21298     
21299     lengthMessage: 'is the wrong length',
21300     
21301     
21302     formatMessage: 'is the wrong format',
21303     
21304     
21305     inclusionMessage: 'is not included in the list of acceptable values',
21306     
21307     
21308     exclusionMessage: 'is not an acceptable value',
21309     
21310     
21311     presence: function(config, value) {
21312         if (value === undefined) {
21313             value = config;
21314         }
21315         
21316         return !!value;
21317     },
21318     
21319     
21320     length: function(config, value) {
21321         if (value === undefined) {
21322             return false;
21323         }
21324         
21325         var length = value.length,
21326             min    = config.min,
21327             max    = config.max;
21328         
21329         if ((min && length < min) || (max && length > max)) {
21330             return false;
21331         } else {
21332             return true;
21333         }
21334     },
21335     
21336     
21337     format: function(config, value) {
21338         return !!(config.matcher && config.matcher.test(value));
21339     },
21340     
21341     
21342     inclusion: function(config, value) {
21343         return config.list && Ext.Array.indexOf(config.list,value) != -1;
21344     },
21345     
21346     
21347     exclusion: function(config, value) {
21348         return config.list && Ext.Array.indexOf(config.list,value) == -1;
21349     }
21350 });
21351
21352 Ext.define('Ext.data.ResultSet', {
21353     
21354     loaded: true,
21355     
21356     
21357     count: 0,
21358     
21359     
21360     total: 0,
21361     
21362     
21363     success: false,
21364     
21365     
21366
21367     constructor: function(config) {
21368         Ext.apply(this, config);
21369         
21370         
21371         this.totalRecords = this.total;
21372         
21373         if (config.count === undefined) {
21374             this.count = this.records.length;
21375         }
21376     }
21377 });
21378
21379 Ext.define('Ext.data.writer.Writer', {
21380     alias: 'writer.base',
21381     alternateClassName: ['Ext.data.DataWriter', 'Ext.data.Writer'],
21382     
21383     
21384     writeAllFields: true,
21385     
21386     
21387     nameProperty: 'name',
21388
21389     constructor: function(config) {
21390         Ext.apply(this, config);
21391     },
21392
21393     
21394     write: function(request) {
21395         var operation = request.operation,
21396             records   = operation.records || [],
21397             len       = records.length,
21398             i         = 0,
21399             data      = [];
21400
21401         for (; i < len; i++) {
21402             data.push(this.getRecordData(records[i]));
21403         }
21404         return this.writeRecords(request, data);
21405     },
21406
21407     
21408     getRecordData: function(record) {
21409         var isPhantom = record.phantom === true,
21410             writeAll = this.writeAllFields || isPhantom,
21411             nameProperty = this.nameProperty,
21412             fields = record.fields,
21413             data = {},
21414             changes,
21415             name,
21416             field,
21417             key;
21418         
21419         if (writeAll) {
21420             fields.each(function(field){
21421                 if (field.persist) {
21422                     name = field[nameProperty] || field.name;
21423                     data[name] = record.get(field.name);
21424                 }
21425             });
21426         } else {
21427             
21428             changes = record.getChanges();
21429             for (key in changes) {
21430                 if (changes.hasOwnProperty(key)) {
21431                     field = fields.get(key);
21432                     name = field[nameProperty] || field.name;
21433                     data[name] = changes[key];
21434                 }
21435             }
21436             if (!isPhantom) {
21437                 
21438                 data[record.idProperty] = record.getId();
21439             }
21440         }
21441         return data;
21442     }
21443 });
21444
21445
21446 Ext.define('Ext.util.Floating', {
21447
21448     uses: ['Ext.Layer', 'Ext.window.Window'],
21449
21450     
21451     focusOnToFront: true,
21452
21453     
21454     shadow: 'sides',
21455
21456     constructor: function(config) {
21457         this.floating = true;
21458         this.el = Ext.create('Ext.Layer', Ext.apply({}, config, {
21459             hideMode: this.hideMode,
21460             hidden: this.hidden,
21461             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
21462             shadowOffset: this.shadowOffset,
21463             constrain: false,
21464             shim: this.shim === false ? false : undefined
21465         }), this.el);
21466     },
21467
21468     onFloatRender: function() {
21469         var me = this;
21470         me.zIndexParent = me.getZIndexParent();
21471         me.setFloatParent(me.ownerCt);
21472         delete me.ownerCt;
21473
21474         if (me.zIndexParent) {
21475             me.zIndexParent.registerFloatingItem(me);
21476         } else {
21477             Ext.WindowManager.register(me);
21478         }
21479     },
21480
21481     setFloatParent: function(floatParent) {
21482         var me = this;
21483
21484         
21485         if (me.floatParent) {
21486             me.mun(me.floatParent, {
21487                 hide: me.onFloatParentHide,
21488                 show: me.onFloatParentShow,
21489                 scope: me
21490             });
21491         }
21492
21493         me.floatParent = floatParent;
21494
21495         
21496         if (floatParent) {
21497             me.mon(me.floatParent, {
21498                 hide: me.onFloatParentHide,
21499                 show: me.onFloatParentShow,
21500                 scope: me
21501             });
21502         }
21503
21504         
21505         
21506         if ((me.constrain || me.constrainHeader) && !me.constrainTo) {
21507             me.constrainTo = floatParent ? floatParent.getTargetEl() : me.container;
21508         }
21509     },
21510
21511     onFloatParentHide: function() {
21512         this.showOnParentShow = this.isVisible();
21513         this.hide();
21514     },
21515
21516     onFloatParentShow: function() {
21517         if (this.showOnParentShow) {
21518             delete this.showOnParentShow;
21519             this.show();
21520         }
21521     },
21522
21523     
21524     getZIndexParent: function() {
21525         var p = this.ownerCt,
21526             c;
21527
21528         if (p) {
21529             while (p) {
21530                 c = p;
21531                 p = p.ownerCt;
21532             }
21533             if (c.floating) {
21534                 return c;
21535             }
21536         }
21537     },
21538
21539     
21540     
21541     
21542     
21543     
21544     setZIndex: function(index) {
21545         var me = this;
21546         this.el.setZIndex(index);
21547
21548         
21549         index += 10;
21550
21551         
21552         
21553         if (me.floatingItems) {
21554             index = Math.floor(me.floatingItems.setBase(index) / 100) * 100 + 10000;
21555         }
21556         return index;
21557     },
21558
21559     
21560     doConstrain: function(constrainTo) {
21561         var me = this,
21562             constrainEl,
21563             vector,
21564             xy;
21565
21566         if (me.constrain || me.constrainHeader) {
21567             if (me.constrainHeader) {
21568                 constrainEl = me.header.el;
21569             } else {
21570                 constrainEl = me.el;
21571             }
21572             vector = constrainEl.getConstrainVector(constrainTo || (me.floatParent && me.floatParent.getTargetEl()) || me.container);
21573             if (vector) {
21574                 xy = me.getPosition();
21575                 xy[0] += vector[0];
21576                 xy[1] += vector[1];
21577                 me.setPosition(xy);
21578             }
21579         }
21580     },
21581
21582     
21583     alignTo: function(element, position, offsets) {
21584         if (element.isComponent) {
21585             element = element.getEl();
21586         }
21587         var xy = this.el.getAlignToXY(element, position, offsets);
21588         this.setPagePosition(xy);
21589         return this;
21590     },
21591
21592     
21593     toFront: function(preventFocus) {
21594         var me = this;
21595
21596         
21597         
21598         if (me.zIndexParent) {
21599             me.zIndexParent.toFront(true);
21600         }
21601         if (me.zIndexManager.bringToFront(me)) {
21602             if (!Ext.isDefined(preventFocus)) {
21603                 preventFocus = !me.focusOnToFront;
21604             }
21605             if (!preventFocus) {
21606                 
21607                 
21608                 
21609                 me.focus(false, true);
21610             }
21611         }
21612         return me;
21613     },
21614
21615     
21616     setActive: function(active, newActive) {
21617         if (active) {
21618             if ((this instanceof Ext.window.Window) && !this.maximized) {
21619                 this.el.enableShadow(true);
21620             }
21621             this.fireEvent('activate', this);
21622         } else {
21623             
21624             
21625             if ((this instanceof Ext.window.Window) && (newActive instanceof Ext.window.Window)) {
21626                 this.el.disableShadow();
21627             }
21628             this.fireEvent('deactivate', this);
21629         }
21630     },
21631
21632     
21633     toBack: function() {
21634         this.zIndexManager.sendToBack(this);
21635         return this;
21636     },
21637
21638     
21639     center: function() {
21640         var xy = this.el.getAlignToXY(this.container, 'c-c');
21641         this.setPagePosition(xy);
21642         return this;
21643     },
21644
21645     
21646     syncShadow : function(){
21647         if (this.floating) {
21648             this.el.sync(true);
21649         }
21650     },
21651
21652     
21653     fitContainer: function() {
21654         var parent = this.floatParent,
21655             container = parent ? parent.getTargetEl() : this.container,
21656             size = container.getViewSize(false);
21657
21658         this.setSize(size);
21659     }
21660 });
21661
21662
21663 Ext.define('Ext.layout.container.AbstractContainer', {
21664
21665     
21666
21667     extend: 'Ext.layout.Layout',
21668
21669     
21670
21671     type: 'container',
21672
21673     fixedLayout: true,
21674
21675     
21676     managedHeight: true,
21677     
21678     managedWidth: true,
21679
21680     
21681     bindToOwnerCtComponent: false,
21682
21683     
21684     bindToOwnerCtContainer: false,
21685
21686     
21687
21688     isManaged: function(dimension) {
21689         dimension = Ext.String.capitalize(dimension);
21690         var me = this,
21691             child = me,
21692             managed = me['managed' + dimension],
21693             ancestor = me.owner.ownerCt;
21694
21695         if (ancestor && ancestor.layout) {
21696             while (ancestor && ancestor.layout) {
21697                 if (managed === false || ancestor.layout['managed' + dimension] === false) {
21698                     managed = false;
21699                     break;
21700                 }
21701                 ancestor = ancestor.ownerCt;
21702             }
21703         }
21704         return managed;
21705     },
21706
21707     layout: function() {
21708         var me = this,
21709             owner = me.owner;
21710         if (Ext.isNumber(owner.height) || owner.isViewport) {
21711             me.managedHeight = false;
21712         }
21713         if (Ext.isNumber(owner.width) || owner.isViewport) {
21714             me.managedWidth = false;
21715         }
21716         me.callParent(arguments);
21717     },
21718
21719     
21720     setItemSize: function(item, width, height) {
21721         if (Ext.isObject(width)) {
21722             height = width.height;
21723             width = width.width;
21724         }
21725         item.setCalculatedSize(width, height, this.owner);
21726     },
21727
21728     
21729     getLayoutItems: function() {
21730         return this.owner && this.owner.items && this.owner.items.items || [];
21731     },
21732
21733     afterLayout: function() {
21734         this.owner.afterLayout(this);
21735     },
21736     
21737      getTarget: function() {
21738          return this.owner.getTargetEl();
21739      },
21740     
21741      getRenderTarget: function() {
21742          return this.owner.getTargetEl();
21743      }
21744 });
21745
21746
21747 Ext.define('Ext.ZIndexManager', {
21748
21749     alternateClassName: 'Ext.WindowGroup',
21750
21751     statics: {
21752         zBase : 9000
21753     },
21754
21755     constructor: function(container) {
21756         var me = this;
21757
21758         me.list = {};
21759         me.zIndexStack = [];
21760         me.front = null;
21761
21762         if (container) {
21763
21764             
21765             if (container.isContainer) {
21766                 container.on('resize', me._onContainerResize, me);
21767                 me.zseed = Ext.Number.from(container.getEl().getStyle('zIndex'), me.getNextZSeed());
21768                 
21769                 me.targetEl = container.getTargetEl();
21770                 me.container = container;
21771             }
21772             
21773             else {
21774                 Ext.EventManager.onWindowResize(me._onContainerResize, me);
21775                 me.zseed = me.getNextZSeed();
21776                 me.targetEl = Ext.get(container);
21777             }
21778         }
21779         
21780         
21781         else {
21782             Ext.EventManager.onWindowResize(me._onContainerResize, me);
21783             me.zseed = me.getNextZSeed();
21784             Ext.onDocumentReady(function() {
21785                 me.targetEl = Ext.getBody();
21786             });
21787         }
21788     },
21789
21790     getNextZSeed: function() {
21791         return (Ext.ZIndexManager.zBase += 10000);
21792     },
21793
21794     setBase: function(baseZIndex) {
21795         this.zseed = baseZIndex;
21796         return this.assignZIndices();
21797     },
21798
21799     
21800     assignZIndices: function() {
21801         var a = this.zIndexStack,
21802             len = a.length,
21803             i = 0,
21804             zIndex = this.zseed,
21805             comp;
21806
21807         for (; i < len; i++) {
21808             comp = a[i];
21809             if (comp && !comp.hidden) {
21810
21811                 
21812                 
21813                 
21814                 
21815                 
21816                 
21817                 
21818                 zIndex = comp.setZIndex(zIndex);
21819             }
21820         }
21821         this._activateLast();
21822         return zIndex;
21823     },
21824
21825     
21826     _setActiveChild: function(comp) {
21827         if (comp != this.front) {
21828
21829             if (this.front) {
21830                 this.front.setActive(false, comp);
21831             }
21832             this.front = comp;
21833             if (comp) {
21834                 comp.setActive(true);
21835                 if (comp.modal) {
21836                     this._showModalMask(comp.el.getStyle('zIndex') - 4);
21837                 }
21838             }
21839         }
21840     },
21841
21842     
21843     _activateLast: function(justHidden) {
21844         var comp,
21845             lastActivated = false,
21846             i;
21847
21848         
21849         
21850         
21851         for (i = this.zIndexStack.length-1; i >= 0; --i) {
21852             comp = this.zIndexStack[i];
21853             if (!comp.hidden) {
21854                 if (!lastActivated) {
21855                     this._setActiveChild(comp);
21856                     lastActivated = true;
21857                 }
21858
21859                 
21860                 if (comp.modal) {
21861                     this._showModalMask(comp.el.getStyle('zIndex') - 4);
21862                     return;
21863                 }
21864             }
21865         }
21866
21867         
21868         
21869         this._hideModalMask();
21870         if (!lastActivated) {
21871             this._setActiveChild(null);
21872         }
21873     },
21874
21875     _showModalMask: function(zIndex) {
21876         if (!this.mask) {
21877             this.mask = this.targetEl.createChild({
21878                 cls: Ext.baseCSSPrefix + 'mask'
21879             });
21880             this.mask.setVisibilityMode(Ext.core.Element.DISPLAY);
21881             this.mask.on('click', this._onMaskClick, this);
21882         }
21883         Ext.getBody().addCls(Ext.baseCSSPrefix + 'body-masked');
21884         this.mask.setSize(this.targetEl.getViewSize(true));
21885         this.mask.setStyle('zIndex', zIndex);
21886         this.mask.show();
21887     },
21888
21889     _hideModalMask: function() {
21890         if (this.mask) {
21891             Ext.getBody().removeCls(Ext.baseCSSPrefix + 'body-masked');
21892             this.mask.hide();
21893         }
21894     },
21895
21896     _onMaskClick: function() {
21897         if (this.front) {
21898             this.front.focus();
21899         }
21900     },
21901
21902     _onContainerResize: function() {
21903         if (this.mask && this.mask.isVisible()) {
21904             this.mask.setSize(this.targetEl.getViewSize(true));
21905         }
21906     },
21907
21908     
21909     register : function(comp) {
21910         if (comp.zIndexManager) {
21911             comp.zIndexManager.unregister(comp);
21912         }
21913         comp.zIndexManager = this;
21914
21915         this.list[comp.id] = comp;
21916         this.zIndexStack.push(comp);
21917         comp.on('hide', this._activateLast, this);
21918     },
21919
21920     
21921     unregister : function(comp) {
21922         delete comp.zIndexManager;
21923         if (this.list && this.list[comp.id]) {
21924             delete this.list[comp.id];
21925             comp.un('hide', this._activateLast);
21926             Ext.Array.remove(this.zIndexStack, comp);
21927
21928             
21929             this._activateLast(comp);
21930         }
21931     },
21932
21933     
21934     get : function(id) {
21935         return typeof id == "object" ? id : this.list[id];
21936     },
21937
21938    
21939     bringToFront : function(comp) {
21940         comp = this.get(comp);
21941         if (comp != this.front) {
21942             Ext.Array.remove(this.zIndexStack, comp);
21943             this.zIndexStack.push(comp);
21944             this.assignZIndices();
21945             return true;
21946         }
21947         if (comp.modal) {
21948             Ext.getBody().addCls(Ext.baseCSSPrefix + 'body-masked');
21949             this.mask.setSize(Ext.core.Element.getViewWidth(true), Ext.core.Element.getViewHeight(true));
21950             this.mask.show();
21951         }
21952         return false;
21953     },
21954
21955     
21956     sendToBack : function(comp) {
21957         comp = this.get(comp);
21958         Ext.Array.remove(this.zIndexStack, comp);
21959         this.zIndexStack.unshift(comp);
21960         this.assignZIndices();
21961         return comp;
21962     },
21963
21964     
21965     hideAll : function() {
21966         for (var id in this.list) {
21967             if (this.list[id].isComponent && this.list[id].isVisible()) {
21968                 this.list[id].hide();
21969             }
21970         }
21971     },
21972
21973     
21974     hide: function() {
21975         var i = 0,
21976             ln = this.zIndexStack.length,
21977             comp;
21978
21979         this.tempHidden = [];
21980         for (; i < ln; i++) {
21981             comp = this.zIndexStack[i];
21982             if (comp.isVisible()) {
21983                 this.tempHidden.push(comp);
21984                 comp.hide();
21985             }
21986         }
21987     },
21988
21989     
21990     show: function() {
21991         var i = 0,
21992             ln = this.tempHidden.length,
21993             comp,
21994             x,
21995             y;
21996
21997         for (; i < ln; i++) {
21998             comp = this.tempHidden[i];
21999             x = comp.x;
22000             y = comp.y;
22001             comp.show();
22002             comp.setPosition(x, y);
22003         }
22004         delete this.tempHidden;
22005     },
22006
22007     
22008     getActive : function() {
22009         return this.front;
22010     },
22011
22012     
22013     getBy : function(fn, scope) {
22014         var r = [],
22015             i = 0,
22016             len = this.zIndexStack.length,
22017             comp;
22018
22019         for (; i < len; i++) {
22020             comp = this.zIndexStack[i];
22021             if (fn.call(scope||comp, comp) !== false) {
22022                 r.push(comp);
22023             }
22024         }
22025         return r;
22026     },
22027
22028     
22029     each : function(fn, scope) {
22030         var comp;
22031         for (var id in this.list) {
22032             comp = this.list[id];
22033             if (comp.isComponent && fn.call(scope || comp, comp) === false) {
22034                 return;
22035             }
22036         }
22037     },
22038
22039     
22040     eachBottomUp: function (fn, scope) {
22041         var comp,
22042             stack = this.zIndexStack,
22043             i, n;
22044
22045         for (i = 0, n = stack.length ; i < n; i++) {
22046             comp = stack[i];
22047             if (comp.isComponent && fn.call(scope || comp, comp) === false) {
22048                 return;
22049             }
22050         }
22051     },
22052
22053     
22054     eachTopDown: function (fn, scope) {
22055         var comp,
22056             stack = this.zIndexStack,
22057             i;
22058
22059         for (i = stack.length ; i-- > 0; ) {
22060             comp = stack[i];
22061             if (comp.isComponent && fn.call(scope || comp, comp) === false) {
22062                 return;
22063             }
22064         }
22065     },
22066
22067     destroy: function() {
22068         delete this.zIndexStack;
22069         delete this.list;
22070         delete this.container;
22071         delete this.targetEl;
22072     }
22073 }, function() {
22074     
22075     Ext.WindowManager = Ext.WindowMgr = new this();
22076 });
22077
22078
22079 Ext.define('Ext.layout.container.boxOverflow.None', {
22080     
22081     alternateClassName: 'Ext.layout.boxOverflow.None',
22082     
22083     constructor: function(layout, config) {
22084         this.layout = layout;
22085         Ext.apply(this, config || {});
22086     },
22087
22088     handleOverflow: Ext.emptyFn,
22089
22090     clearOverflow: Ext.emptyFn,
22091
22092     
22093     getItem: function(item) {
22094         return this.layout.owner.getComponent(item);
22095     }
22096 });
22097
22098 Ext.define('Ext.util.KeyMap', {
22099     alternateClassName: 'Ext.KeyMap',
22100     
22101     constructor: function(el, binding, eventName){
22102         var me = this;
22103         
22104         Ext.apply(me, {
22105             el: Ext.get(el),
22106             eventName: eventName || me.eventName,
22107             bindings: []
22108         });
22109         if (binding) {
22110             me.addBinding(binding);
22111         }
22112         me.enable();
22113     },
22114     
22115     eventName: 'keydown',
22116
22117     
22118     addBinding : function(binding){
22119         if (Ext.isArray(binding)) {
22120             Ext.each(binding, this.addBinding, this);
22121             return;
22122         }
22123         
22124         var keyCode = binding.key,
22125             processed = false,
22126             key,
22127             keys,
22128             keyString,
22129             i,
22130             len;
22131
22132         if (Ext.isString(keyCode)) {
22133             keys = [];
22134             keyString = keyCode.toLowerCase();
22135             
22136             for (i = 0, len = keyString.length; i < len; ++i){
22137                 keys.push(keyString.charCodeAt(i));
22138             }
22139             keyCode = keys;
22140             processed = true;
22141         }
22142         
22143         if (!Ext.isArray(keyCode)) {
22144             keyCode = [keyCode];
22145         }
22146         
22147         if (!processed) {
22148             for (i = 0, len = keyCode.length; i < len; ++i) {
22149                 key = keyCode[i];
22150                 if (Ext.isString(key)) {
22151                     keyCode[i] = key.toLowerCase().charCodeAt(0);
22152                 }
22153             }
22154         }
22155         
22156         this.bindings.push(Ext.apply({
22157             keyCode: keyCode
22158         }, binding));
22159     },
22160     
22161     
22162     handleKeyDown: function(event) {
22163         if (this.enabled) { 
22164             var bindings = this.bindings,
22165                 i = 0,
22166                 len = bindings.length;
22167                 
22168             event = this.processEvent(event);
22169             for(; i < len; ++i){
22170                 this.processBinding(bindings[i], event);
22171             }
22172         }
22173     },
22174     
22175     
22176     processEvent: function(event){
22177         return event;
22178     },
22179     
22180     
22181     processBinding: function(binding, event){
22182         if (this.checkModifiers(binding, event)) {
22183             var key = event.getKey(),
22184                 handler = binding.fn || binding.handler,
22185                 scope = binding.scope || this,
22186                 keyCode = binding.keyCode,
22187                 defaultEventAction = binding.defaultEventAction,
22188                 i,
22189                 len,
22190                 keydownEvent = new Ext.EventObjectImpl(event);
22191                 
22192             
22193             for (i = 0, len = keyCode.length; i < len; ++i) {
22194                 if (key === keyCode[i]) {
22195                     if (handler.call(scope, key, event) !== true && defaultEventAction) {
22196                         keydownEvent[defaultEventAction]();
22197                     }
22198                     break;
22199                 }
22200             }
22201         }
22202     },
22203     
22204     
22205     checkModifiers: function(binding, e){
22206         var keys = ['shift', 'ctrl', 'alt'],
22207             i = 0,
22208             len = keys.length,
22209             val, key;
22210             
22211         for (; i < len; ++i){
22212             key = keys[i];
22213             val = binding[key];
22214             if (!(val === undefined || (val === e[key + 'Key']))) {
22215                 return false;
22216             }
22217         }
22218         return true;
22219     },
22220
22221     
22222     on: function(key, fn, scope) {
22223         var keyCode, shift, ctrl, alt;
22224         if (Ext.isObject(key) && !Ext.isArray(key)) {
22225             keyCode = key.key;
22226             shift = key.shift;
22227             ctrl = key.ctrl;
22228             alt = key.alt;
22229         } else {
22230             keyCode = key;
22231         }
22232         this.addBinding({
22233             key: keyCode,
22234             shift: shift,
22235             ctrl: ctrl,
22236             alt: alt,
22237             fn: fn,
22238             scope: scope
22239         });
22240     },
22241
22242     
22243     isEnabled : function(){
22244         return this.enabled;
22245     },
22246
22247     
22248     enable: function(){
22249         if(!this.enabled){
22250             this.el.on(this.eventName, this.handleKeyDown, this);
22251             this.enabled = true;
22252         }
22253     },
22254
22255     
22256     disable: function(){
22257         if(this.enabled){
22258             this.el.removeListener(this.eventName, this.handleKeyDown, this);
22259             this.enabled = false;
22260         }
22261     },
22262
22263     
22264     setDisabled : function(disabled){
22265         if (disabled) {
22266             this.disable();
22267         } else {
22268             this.enable();
22269         }
22270     },
22271     
22272     
22273     destroy: function(removeEl){
22274         var me = this;
22275         
22276         me.bindings = [];
22277         me.disable();
22278         if (removeEl === true) {
22279             me.el.remove();
22280         }
22281         delete me.el;
22282     }
22283 });
22284
22285
22286 Ext.define('Ext.util.ClickRepeater', {
22287     extend: 'Ext.util.Observable',
22288
22289     constructor : function(el, config){
22290         this.el = Ext.get(el);
22291         this.el.unselectable();
22292
22293         Ext.apply(this, config);
22294
22295         this.addEvents(
22296         
22297         "mousedown",
22298         
22299         "click",
22300         
22301         "mouseup"
22302         );
22303
22304         if(!this.disabled){
22305             this.disabled = true;
22306             this.enable();
22307         }
22308
22309         
22310         if(this.handler){
22311             this.on("click", this.handler,  this.scope || this);
22312         }
22313
22314         this.callParent();
22315     },
22316
22317     
22318
22319     
22320
22321     
22322
22323     
22324     interval : 20,
22325
22326     
22327     delay: 250,
22328
22329     
22330     preventDefault : true,
22331     
22332     stopDefault : false,
22333
22334     timer : 0,
22335
22336     
22337     enable: function(){
22338         if(this.disabled){
22339             this.el.on('mousedown', this.handleMouseDown, this);
22340             if (Ext.isIE){
22341                 this.el.on('dblclick', this.handleDblClick, this);
22342             }
22343             if(this.preventDefault || this.stopDefault){
22344                 this.el.on('click', this.eventOptions, this);
22345             }
22346         }
22347         this.disabled = false;
22348     },
22349
22350     
22351     disable: function( force){
22352         if(force || !this.disabled){
22353             clearTimeout(this.timer);
22354             if(this.pressedCls){
22355                 this.el.removeCls(this.pressedCls);
22356             }
22357             Ext.getDoc().un('mouseup', this.handleMouseUp, this);
22358             this.el.removeAllListeners();
22359         }
22360         this.disabled = true;
22361     },
22362
22363     
22364     setDisabled: function(disabled){
22365         this[disabled ? 'disable' : 'enable']();
22366     },
22367
22368     eventOptions: function(e){
22369         if(this.preventDefault){
22370             e.preventDefault();
22371         }
22372         if(this.stopDefault){
22373             e.stopEvent();
22374         }
22375     },
22376
22377     
22378     destroy : function() {
22379         this.disable(true);
22380         Ext.destroy(this.el);
22381         this.clearListeners();
22382     },
22383
22384     handleDblClick : function(e){
22385         clearTimeout(this.timer);
22386         this.el.blur();
22387
22388         this.fireEvent("mousedown", this, e);
22389         this.fireEvent("click", this, e);
22390     },
22391
22392     
22393     handleMouseDown : function(e){
22394         clearTimeout(this.timer);
22395         this.el.blur();
22396         if(this.pressedCls){
22397             this.el.addCls(this.pressedCls);
22398         }
22399         this.mousedownTime = new Date();
22400
22401         Ext.getDoc().on("mouseup", this.handleMouseUp, this);
22402         this.el.on("mouseout", this.handleMouseOut, this);
22403
22404         this.fireEvent("mousedown", this, e);
22405         this.fireEvent("click", this, e);
22406
22407         
22408         if (this.accelerate) {
22409             this.delay = 400;
22410         }
22411
22412         
22413         
22414         e = new Ext.EventObjectImpl(e);
22415
22416         this.timer =  Ext.defer(this.click, this.delay || this.interval, this, [e]);
22417     },
22418
22419     
22420     click : function(e){
22421         this.fireEvent("click", this, e);
22422         this.timer =  Ext.defer(this.click, this.accelerate ?
22423             this.easeOutExpo(Ext.Date.getElapsed(this.mousedownTime),
22424                 400,
22425                 -390,
22426                 12000) :
22427             this.interval, this, [e]);
22428     },
22429
22430     easeOutExpo : function (t, b, c, d) {
22431         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
22432     },
22433
22434     
22435     handleMouseOut : function(){
22436         clearTimeout(this.timer);
22437         if(this.pressedCls){
22438             this.el.removeCls(this.pressedCls);
22439         }
22440         this.el.on("mouseover", this.handleMouseReturn, this);
22441     },
22442
22443     
22444     handleMouseReturn : function(){
22445         this.el.un("mouseover", this.handleMouseReturn, this);
22446         if(this.pressedCls){
22447             this.el.addCls(this.pressedCls);
22448         }
22449         this.click();
22450     },
22451
22452     
22453     handleMouseUp : function(e){
22454         clearTimeout(this.timer);
22455         this.el.un("mouseover", this.handleMouseReturn, this);
22456         this.el.un("mouseout", this.handleMouseOut, this);
22457         Ext.getDoc().un("mouseup", this.handleMouseUp, this);
22458         if(this.pressedCls){
22459             this.el.removeCls(this.pressedCls);
22460         }
22461         this.fireEvent("mouseup", this, e);
22462     }
22463 });
22464
22465
22466 Ext.define('Ext.layout.component.Button', {
22467
22468     
22469
22470     alias: ['layout.button'],
22471
22472     extend: 'Ext.layout.component.Component',
22473
22474     
22475
22476     type: 'button',
22477
22478     cellClsRE: /-btn-(tl|br)\b/,
22479     htmlRE: /<.*>/,
22480
22481     beforeLayout: function() {
22482         return this.callParent(arguments) || this.lastText !== this.owner.text;
22483     },
22484
22485     
22486     onLayout: function(width, height) {
22487         var me = this,
22488             isNum = Ext.isNumber,
22489             owner = me.owner,
22490             ownerEl = owner.el,
22491             btnEl = owner.btnEl,
22492             btnInnerEl = owner.btnInnerEl,
22493             minWidth = owner.minWidth,
22494             maxWidth = owner.maxWidth,
22495             ownerWidth, btnFrameWidth, metrics;
22496
22497         me.getTargetInfo();
22498         me.callParent(arguments);
22499
22500         btnInnerEl.unclip();
22501         me.setTargetSize(width, height);
22502
22503         if (!isNum(width)) {
22504             
22505             
22506             
22507             if (owner.text && Ext.isIE7 && Ext.isStrict && btnEl && btnEl.getWidth() > 20) {
22508                 btnFrameWidth = me.btnFrameWidth;
22509                 metrics = Ext.util.TextMetrics.measure(btnInnerEl, owner.text);
22510                 ownerEl.setWidth(metrics.width + btnFrameWidth + me.adjWidth);
22511                 btnEl.setWidth(metrics.width + btnFrameWidth);
22512                 btnInnerEl.setWidth(metrics.width + btnFrameWidth);
22513             } else {
22514                 
22515                 ownerEl.setWidth(null);
22516                 btnEl.setWidth(null);
22517                 btnInnerEl.setWidth(null);
22518             }
22519
22520             
22521             if (minWidth || maxWidth) {
22522                 ownerWidth = ownerEl.getWidth();
22523                 if (minWidth && (ownerWidth < minWidth)) {
22524                     me.setTargetSize(minWidth, height);
22525                 }
22526                 else if (maxWidth && (ownerWidth > maxWidth)) {
22527                     btnInnerEl.clip();
22528                     me.setTargetSize(maxWidth, height);
22529                 }
22530             }
22531         }
22532
22533         this.lastText = owner.text;
22534     },
22535
22536     setTargetSize: function(width, height) {
22537         var me = this,
22538             owner = me.owner,
22539             isNum = Ext.isNumber,
22540             btnInnerEl = owner.btnInnerEl,
22541             btnWidth = (isNum(width) ? width - me.adjWidth : width),
22542             btnHeight = (isNum(height) ? height - me.adjHeight : height),
22543             btnFrameHeight = me.btnFrameHeight,
22544             text = owner.getText(),
22545             textHeight;
22546
22547         me.callParent(arguments);
22548         me.setElementSize(owner.btnEl, btnWidth, btnHeight);
22549         me.setElementSize(btnInnerEl, btnWidth, btnHeight);
22550         if (isNum(btnHeight)) {
22551             btnInnerEl.setStyle('line-height', btnHeight - btnFrameHeight + 'px');
22552         }
22553
22554         
22555         
22556         
22557         
22558         
22559         if (text && this.htmlRE.test(text)) {
22560             btnInnerEl.setStyle('line-height', 'normal');
22561             textHeight = Ext.util.TextMetrics.measure(btnInnerEl, text).height;
22562             btnInnerEl.setStyle('padding-top', me.btnFrameTop + Math.max(btnInnerEl.getHeight() - btnFrameHeight - textHeight, 0) / 2 + 'px');
22563             me.setElementSize(btnInnerEl, btnWidth, btnHeight);
22564         }
22565     },
22566
22567     getTargetInfo: function() {
22568         var me = this,
22569             owner = me.owner,
22570             ownerEl = owner.el,
22571             frameSize = me.frameSize,
22572             frameBody = owner.frameBody,
22573             btnWrap = owner.btnWrap,
22574             innerEl = owner.btnInnerEl;
22575
22576         if (!('adjWidth' in me)) {
22577             Ext.apply(me, {
22578                 
22579                 adjWidth: frameSize.left + frameSize.right + ownerEl.getBorderWidth('lr') + ownerEl.getPadding('lr') +
22580                           btnWrap.getPadding('lr') + (frameBody ? frameBody.getFrameWidth('lr') : 0),
22581                 adjHeight: frameSize.top + frameSize.bottom + ownerEl.getBorderWidth('tb') + ownerEl.getPadding('tb') +
22582                            btnWrap.getPadding('tb') + (frameBody ? frameBody.getFrameWidth('tb') : 0),
22583                 btnFrameWidth: innerEl.getFrameWidth('lr'),
22584                 btnFrameHeight: innerEl.getFrameWidth('tb'),
22585                 btnFrameTop: innerEl.getFrameWidth('t')
22586             });
22587         }
22588
22589         return me.callParent();
22590     }
22591 });
22592
22593 Ext.define('Ext.util.TextMetrics', {
22594     statics: {
22595         shared: null,
22596         
22597         measure: function(el, text, fixedWidth){
22598             var me = this,
22599                 shared = me.shared;
22600             
22601             if(!shared){
22602                 shared = me.shared = new me(el, fixedWidth);
22603             }
22604             shared.bind(el);
22605             shared.setFixedWidth(fixedWidth || 'auto');
22606             return shared.getSize(text);
22607         },
22608         
22609         
22610          destroy: function(){
22611              var me = this;
22612              Ext.destroy(me.shared);
22613              me.shared = null;
22614          }
22615     },
22616     
22617     
22618     constructor: function(bindTo, fixedWidth){
22619         var measure = this.measure = Ext.getBody().createChild({
22620             cls: 'x-textmetrics'
22621         });
22622         this.el = Ext.get(bindTo);
22623         
22624         measure.position('absolute');
22625         measure.setLeftTop(-1000, -1000);
22626         measure.hide();
22627
22628         if (fixedWidth) {
22629            measure.setWidth(fixedWidth);
22630         }
22631     },
22632     
22633     
22634     getSize: function(text){
22635         var measure = this.measure,
22636             size;
22637         
22638         measure.update(text);
22639         size = measure.getSize();
22640         measure.update('');
22641         return size;
22642     },
22643     
22644     
22645     bind: function(el){
22646         var me = this;
22647         
22648         me.el = Ext.get(el);
22649         me.measure.setStyle(
22650             me.el.getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
22651         );
22652     },
22653     
22654     
22655      setFixedWidth : function(width){
22656          this.measure.setWidth(width);
22657      },
22658      
22659      
22660      getWidth : function(text){
22661          this.measure.dom.style.width = 'auto';
22662          return this.getSize(text).width;
22663      },
22664      
22665      
22666      getHeight : function(text){
22667          return this.getSize(text).height;
22668      },
22669      
22670      
22671      destroy: function(){
22672          var me = this;
22673          me.measure.remove();
22674          delete me.el;
22675          delete me.measure;
22676      }
22677 }, function(){
22678     Ext.core.Element.addMethods({
22679         
22680         getTextWidth : function(text, min, max){
22681             return Ext.Number.constrain(Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width, min || 0, max || 1000000);
22682         }
22683     });
22684 });
22685
22686
22687 Ext.define('Ext.layout.container.boxOverflow.Scroller', {
22688
22689     
22690
22691     extend: 'Ext.layout.container.boxOverflow.None',
22692     requires: ['Ext.util.ClickRepeater', 'Ext.core.Element'],
22693     alternateClassName: 'Ext.layout.boxOverflow.Scroller',
22694     mixins: {
22695         observable: 'Ext.util.Observable'
22696     },
22697     
22698     
22699
22700     
22701     animateScroll: false,
22702
22703     
22704     scrollIncrement: 20,
22705
22706     
22707     wheelIncrement: 10,
22708
22709     
22710     scrollRepeatInterval: 60,
22711
22712     
22713     scrollDuration: 400,
22714
22715     
22716
22717     
22718
22719     
22720     scrollerCls: Ext.baseCSSPrefix + 'box-scroller',
22721
22722     
22723
22724     
22725     
22726     constructor: function(layout, config) {
22727         this.layout = layout;
22728         Ext.apply(this, config || {});
22729         
22730         this.addEvents(
22731             
22732             'scroll'
22733         );
22734     },
22735     
22736     initCSSClasses: function() {
22737         var me = this,
22738         layout = me.layout;
22739
22740         if (!me.CSSinitialized) {
22741             me.beforeCtCls = me.beforeCtCls || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelBefore;
22742             me.afterCtCls  = me.afterCtCls  || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelAfter;
22743             me.beforeScrollerCls = me.beforeScrollerCls || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelBefore;
22744             me.afterScrollerCls  = me.afterScrollerCls  || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelAfter;
22745             me.CSSinitializes = true;
22746         }
22747     },
22748
22749     handleOverflow: function(calculations, targetSize) {
22750         var me = this,
22751             layout = me.layout,
22752             methodName = 'get' + layout.parallelPrefixCap,
22753             newSize = {};
22754
22755         me.initCSSClasses();
22756         me.callParent(arguments);
22757         this.createInnerElements();
22758         this.showScrollers();
22759         newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
22760         newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - (me.beforeCt[methodName]() + me.afterCt[methodName]());
22761         return { targetSize: newSize };
22762     },
22763
22764     
22765     createInnerElements: function() {
22766         var me = this,
22767             target = me.layout.getRenderTarget();
22768
22769         
22770         
22771         if (!me.beforeCt) {
22772             target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
22773             me.beforeCt = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.beforeCtCls}, 'before');
22774             me.afterCt  = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.afterCtCls},  'after');
22775             me.createWheelListener();
22776         }
22777     },
22778
22779     
22780     createWheelListener: function() {
22781         this.layout.innerCt.on({
22782             scope     : this,
22783             mousewheel: function(e) {
22784                 e.stopEvent();
22785
22786                 this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
22787             }
22788         });
22789     },
22790
22791     
22792     clearOverflow: function() {
22793         this.hideScrollers();
22794     },
22795
22796     
22797     showScrollers: function() {
22798         this.createScrollers();
22799         this.beforeScroller.show();
22800         this.afterScroller.show();
22801         this.updateScrollButtons();
22802         
22803         this.layout.owner.addClsWithUI('scroller');
22804     },
22805
22806     
22807     hideScrollers: function() {
22808         if (this.beforeScroller != undefined) {
22809             this.beforeScroller.hide();
22810             this.afterScroller.hide();
22811             
22812             this.layout.owner.removeClsWithUI('scroller');
22813         }
22814     },
22815
22816     
22817     createScrollers: function() {
22818         if (!this.beforeScroller && !this.afterScroller) {
22819             var before = this.beforeCt.createChild({
22820                 cls: Ext.String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
22821             });
22822
22823             var after = this.afterCt.createChild({
22824                 cls: Ext.String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
22825             });
22826
22827             before.addClsOnOver(this.beforeScrollerCls + '-hover');
22828             after.addClsOnOver(this.afterScrollerCls + '-hover');
22829
22830             before.setVisibilityMode(Ext.core.Element.DISPLAY);
22831             after.setVisibilityMode(Ext.core.Element.DISPLAY);
22832
22833             this.beforeRepeater = Ext.create('Ext.util.ClickRepeater', before, {
22834                 interval: this.scrollRepeatInterval,
22835                 handler : this.scrollLeft,
22836                 scope   : this
22837             });
22838
22839             this.afterRepeater = Ext.create('Ext.util.ClickRepeater', after, {
22840                 interval: this.scrollRepeatInterval,
22841                 handler : this.scrollRight,
22842                 scope   : this
22843             });
22844
22845             
22846             this.beforeScroller = before;
22847
22848             
22849             this.afterScroller = after;
22850         }
22851     },
22852
22853     
22854     destroy: function() {
22855         Ext.destroy(this.beforeRepeater, this.afterRepeater, this.beforeScroller, this.afterScroller, this.beforeCt, this.afterCt);
22856     },
22857
22858     
22859     scrollBy: function(delta, animate) {
22860         this.scrollTo(this.getScrollPosition() + delta, animate);
22861     },
22862
22863     
22864     getScrollAnim: function() {
22865         return {
22866             duration: this.scrollDuration, 
22867             callback: this.updateScrollButtons, 
22868             scope   : this
22869         };
22870     },
22871
22872     
22873     updateScrollButtons: function() {
22874         if (this.beforeScroller == undefined || this.afterScroller == undefined) {
22875             return;
22876         }
22877
22878         var beforeMeth = this.atExtremeBefore()  ? 'addCls' : 'removeCls',
22879             afterMeth  = this.atExtremeAfter() ? 'addCls' : 'removeCls',
22880             beforeCls  = this.beforeScrollerCls + '-disabled',
22881             afterCls   = this.afterScrollerCls  + '-disabled';
22882         
22883         this.beforeScroller[beforeMeth](beforeCls);
22884         this.afterScroller[afterMeth](afterCls);
22885         this.scrolling = false;
22886     },
22887
22888     
22889     atExtremeBefore: function() {
22890         return this.getScrollPosition() === 0;
22891     },
22892
22893     
22894     scrollLeft: function() {
22895         this.scrollBy(-this.scrollIncrement, false);
22896     },
22897
22898     
22899     scrollRight: function() {
22900         this.scrollBy(this.scrollIncrement, false);
22901     },
22902
22903     
22904     getScrollPosition: function(){
22905         var layout = this.layout;
22906         return parseInt(layout.innerCt.dom['scroll' + layout.parallelBeforeCap], 10) || 0;
22907     },
22908
22909     
22910     getMaxScrollPosition: function() {
22911         var layout = this.layout;
22912         return layout.innerCt.dom['scroll' + layout.parallelPrefixCap] - this.layout.innerCt['get' + layout.parallelPrefixCap]();
22913     },
22914
22915     
22916     atExtremeAfter: function() {
22917         return this.getScrollPosition() >= this.getMaxScrollPosition();
22918     },
22919
22920     
22921     scrollTo: function(position, animate) {
22922         var me = this,
22923             layout = me.layout,
22924             oldPosition = me.getScrollPosition(),
22925             newPosition = Ext.Number.constrain(position, 0, me.getMaxScrollPosition());
22926
22927         if (newPosition != oldPosition && !me.scrolling) {
22928             if (animate == undefined) {
22929                 animate = me.animateScroll;
22930             }
22931
22932             layout.innerCt.scrollTo(layout.parallelBefore, newPosition, animate ? me.getScrollAnim() : false);
22933             if (animate) {
22934                 me.scrolling = true;
22935             } else {
22936                 me.scrolling = false;
22937                 me.updateScrollButtons();
22938             }
22939             
22940             me.fireEvent('scroll', me, newPosition, animate ? me.getScrollAnim() : false);
22941         }
22942     },
22943
22944     
22945     scrollToItem: function(item, animate) {
22946         var me = this,
22947             layout = me.layout,
22948             visibility,
22949             box,
22950             newPos;
22951
22952         item = me.getItem(item);
22953         if (item != undefined) {
22954             visibility = this.getItemVisibility(item);
22955             if (!visibility.fullyVisible) {
22956                 box  = item.getBox(true, true);
22957                 newPos = box[layout.parallelPosition];
22958                 if (visibility.hiddenEnd) {
22959                     newPos -= (this.layout.innerCt['get' + layout.parallelPrefixCap]() - box[layout.parallelPrefix]);
22960                 }
22961                 this.scrollTo(newPos, animate);
22962             }
22963         }
22964     },
22965
22966     
22967     getItemVisibility: function(item) {
22968         var me          = this,
22969             box         = me.getItem(item).getBox(true, true),
22970             layout      = me.layout,
22971             itemStart   = box[layout.parallelPosition],
22972             itemEnd     = itemStart + box[layout.parallelPrefix],
22973             scrollStart = me.getScrollPosition(),
22974             scrollEnd   = scrollStart + layout.innerCt['get' + layout.parallelPrefixCap]();
22975
22976         return {
22977             hiddenStart : itemStart < scrollStart,
22978             hiddenEnd   : itemEnd > scrollEnd,
22979             fullyVisible: itemStart > scrollStart && itemEnd < scrollEnd
22980         };
22981     }
22982 });
22983
22984 Ext.define('Ext.util.Offset', {
22985
22986     
22987
22988     statics: {
22989         fromObject: function(obj) {
22990             return new this(obj.x, obj.y);
22991         }
22992     },
22993
22994     
22995
22996     constructor: function(x, y) {
22997         this.x = (x != null && !isNaN(x)) ? x : 0;
22998         this.y = (y != null && !isNaN(y)) ? y : 0;
22999
23000         return this;
23001     },
23002
23003     copy: function() {
23004         return new Ext.util.Offset(this.x, this.y);
23005     },
23006
23007     copyFrom: function(p) {
23008         this.x = p.x;
23009         this.y = p.y;
23010     },
23011
23012     toString: function() {
23013         return "Offset[" + this.x + "," + this.y + "]";
23014     },
23015
23016     equals: function(offset) {
23017         if(!(offset instanceof this.statics())) {
23018             Ext.Error.raise('Offset must be an instance of Ext.util.Offset');
23019         }
23020
23021         return (this.x == offset.x && this.y == offset.y);
23022     },
23023
23024     round: function(to) {
23025         if (!isNaN(to)) {
23026             var factor = Math.pow(10, to);
23027             this.x = Math.round(this.x * factor) / factor;
23028             this.y = Math.round(this.y * factor) / factor;
23029         } else {
23030             this.x = Math.round(this.x);
23031             this.y = Math.round(this.y);
23032         }
23033     },
23034
23035     isZero: function() {
23036         return this.x == 0 && this.y == 0;
23037     }
23038 });
23039
23040
23041 Ext.define('Ext.util.KeyNav', {
23042     
23043     alternateClassName: 'Ext.KeyNav',
23044     
23045     requires: ['Ext.util.KeyMap'],
23046     
23047     statics: {
23048         keyOptions: {
23049             left: 37,
23050             right: 39,
23051             up: 38,
23052             down: 40,
23053             space: 32,
23054             pageUp: 33,
23055             pageDown: 34,
23056             del: 46,
23057             backspace: 8,
23058             home: 36,
23059             end: 35,
23060             enter: 13,
23061             esc: 27,
23062             tab: 9
23063         }
23064     },
23065     
23066     constructor: function(el, config){
23067         this.setConfig(el, config || {});
23068     },
23069     
23070     
23071     setConfig: function(el, config) {
23072         if (this.map) {
23073             this.map.destroy();
23074         }
23075         
23076         var map = Ext.create('Ext.util.KeyMap', el, null, this.getKeyEvent('forceKeyDown' in config ? config.forceKeyDown : this.forceKeyDown)),
23077             keys = Ext.util.KeyNav.keyOptions,
23078             scope = config.scope || this,
23079             key;
23080         
23081         this.map = map;
23082         for (key in keys) {
23083             if (keys.hasOwnProperty(key)) {
23084                 if (config[key]) {
23085                     map.addBinding({
23086                         scope: scope,
23087                         key: keys[key],
23088                         handler: Ext.Function.bind(this.handleEvent, scope, [config[key]], true),
23089                         defaultEventAction: config.defaultEventAction || this.defaultEventAction
23090                     });
23091                 }
23092             }
23093         }
23094         
23095         map.disable();
23096         if (!config.disabled) {
23097             map.enable();
23098         }
23099     },
23100     
23101     
23102     handleEvent: function(map, event, handler){
23103         return handler.call(this, event);
23104     },
23105     
23106     
23107     disabled: false,
23108     
23109     
23110     defaultEventAction: "stopEvent",
23111     
23112     
23113     forceKeyDown: false,
23114     
23115     
23116     destroy: function(removeEl){
23117         this.map.destroy(removeEl);
23118         delete this.map;
23119     },
23120
23121     
23122     enable: function() {
23123         this.map.enable();
23124         this.disabled = false;
23125     },
23126
23127     
23128     disable: function() {
23129         this.map.disable();
23130         this.disabled = true;
23131     },
23132     
23133     
23134     setDisabled : function(disabled){
23135         this.map.setDisabled(disabled);
23136         this.disabled = disabled;
23137     },
23138     
23139     
23140     getKeyEvent: function(forceKeyDown){
23141         return (forceKeyDown || Ext.EventManager.useKeyDown) ? 'keydown' : 'keypress';
23142     }
23143 });
23144
23145
23146
23147 Ext.define('Ext.fx.Queue', {
23148
23149     requires: ['Ext.util.HashMap'],
23150
23151     constructor: function() {
23152         this.targets = Ext.create('Ext.util.HashMap');
23153         this.fxQueue = {};
23154     },
23155
23156     
23157     getFxDefaults: function(targetId) {
23158         var target = this.targets.get(targetId);
23159         if (target) {
23160             return target.fxDefaults;
23161         }
23162         return {};
23163     },
23164
23165     
23166     setFxDefaults: function(targetId, obj) {
23167         var target = this.targets.get(targetId);
23168         if (target) {
23169             target.fxDefaults = Ext.apply(target.fxDefaults || {}, obj);
23170         }
23171     },
23172
23173     
23174     stopAnimation: function(targetId) {
23175         var me = this,
23176             queue = me.getFxQueue(targetId),
23177             ln = queue.length;
23178         while (ln) {
23179             queue[ln - 1].end();
23180             ln--;
23181         }
23182     },
23183
23184     
23185     getActiveAnimation: function(targetId) {
23186         var queue = this.getFxQueue(targetId);
23187         return (queue && !!queue.length) ? queue[0] : false;
23188     },
23189
23190     
23191     hasFxBlock: function(targetId) {
23192         var queue = this.getFxQueue(targetId);
23193         return queue && queue[0] && queue[0].block;
23194     },
23195
23196     
23197     getFxQueue: function(targetId) {
23198         if (!targetId) {
23199             return false;
23200         }
23201         var me = this,
23202             queue = me.fxQueue[targetId],
23203             target = me.targets.get(targetId);
23204
23205         if (!target) {
23206             return false;
23207         }
23208
23209         if (!queue) {
23210             me.fxQueue[targetId] = [];
23211             
23212             if (target.type != 'element') {
23213                 target.target.on('destroy', function() {
23214                     me.fxQueue[targetId] = [];
23215                 });
23216             }
23217         }
23218         return me.fxQueue[targetId];
23219     },
23220
23221     
23222     queueFx: function(anim) {
23223         var me = this,
23224             target = anim.target,
23225             queue, ln;
23226
23227         if (!target) {
23228             return;
23229         }
23230
23231         queue = me.getFxQueue(target.getId());
23232         ln = queue.length;
23233
23234         if (ln) {
23235             if (anim.concurrent) {
23236                 anim.paused = false;
23237             }
23238             else {
23239                 queue[ln - 1].on('afteranimate', function() {
23240                     anim.paused = false;
23241                 });
23242             }
23243         }
23244         else {
23245             anim.paused = false;
23246         }
23247         anim.on('afteranimate', function() {
23248             Ext.Array.remove(queue, anim);
23249             if (anim.remove) {
23250                 if (target.type == 'element') {
23251                     var el = Ext.get(target.id);
23252                     if (el) {
23253                         el.remove();
23254                     }
23255                 }
23256             }
23257         }, this);
23258         queue.push(anim);
23259     }
23260 });
23261
23262
23263 Ext.define('Ext.fx.target.Target', {
23264
23265     isAnimTarget: true,
23266
23267     constructor: function(target) {
23268         this.target = target;
23269         this.id = this.getId();
23270     },
23271     
23272     getId: function() {
23273         return this.target.id;
23274     }
23275 });
23276
23277
23278
23279 Ext.define('Ext.fx.target.Sprite', {
23280
23281     
23282
23283     extend: 'Ext.fx.target.Target',
23284
23285     
23286
23287     type: 'draw',
23288
23289     getFromPrim: function(sprite, attr) {
23290         var o;
23291         if (attr == 'translate') {
23292             o = {
23293                 x: sprite.attr.translation.x || 0,
23294                 y: sprite.attr.translation.y || 0
23295             };
23296         }
23297         else if (attr == 'rotate') {
23298             o = {
23299                 degrees: sprite.attr.rotation.degrees || 0,
23300                 x: sprite.attr.rotation.x,
23301                 y: sprite.attr.rotation.y
23302             };
23303         }
23304         else {
23305             o = sprite.attr[attr];
23306         }
23307         return o;
23308     },
23309
23310     getAttr: function(attr, val) {
23311         return [[this.target, val != undefined ? val : this.getFromPrim(this.target, attr)]];
23312     },
23313
23314     setAttr: function(targetData) {
23315         var ln = targetData.length,
23316             spriteArr = [],
23317             attrs, attr, attrArr, attPtr, spritePtr, idx, value, i, j, x, y, ln2;
23318         for (i = 0; i < ln; i++) {
23319             attrs = targetData[i].attrs;
23320             for (attr in attrs) {
23321                 attrArr = attrs[attr];
23322                 ln2 = attrArr.length;
23323                 for (j = 0; j < ln2; j++) {
23324                     spritePtr = attrArr[j][0];
23325                     attPtr = attrArr[j][1];
23326                     if (attr === 'translate') {
23327                         value = {
23328                             x: attPtr.x,
23329                             y: attPtr.y
23330                         };
23331                     }
23332                     else if (attr === 'rotate') {
23333                         x = attPtr.x;
23334                         if (isNaN(x)) {
23335                             x = null;
23336                         }
23337                         y = attPtr.y;
23338                         if (isNaN(y)) {
23339                             y = null;
23340                         }
23341                         value = {
23342                             degrees: attPtr.degrees,
23343                             x: x,
23344                             y: y
23345                         };
23346                     }
23347                     else if (attr === 'width' || attr === 'height' || attr === 'x' || attr === 'y') {
23348                         value = parseFloat(attPtr);
23349                     }
23350                     else {
23351                         value = attPtr;
23352                     }
23353                     idx = Ext.Array.indexOf(spriteArr, spritePtr);
23354                     if (idx == -1) {
23355                         spriteArr.push([spritePtr, {}]);
23356                         idx = spriteArr.length - 1;
23357                     }
23358                     spriteArr[idx][1][attr] = value;
23359                 }
23360             }
23361         }
23362         ln = spriteArr.length;
23363         for (i = 0; i < ln; i++) {
23364             spritePtr = spriteArr[i];
23365             spritePtr[0].setAttributes(spritePtr[1]);
23366         }
23367         this.target.redraw();
23368     }
23369 });
23370
23371
23372
23373 Ext.define('Ext.fx.target.CompositeSprite', {
23374
23375     
23376
23377     extend: 'Ext.fx.target.Sprite',
23378
23379     
23380
23381     getAttr: function(attr, val) {
23382         var out = [],
23383             target = this.target;
23384         target.each(function(sprite) {
23385             out.push([sprite, val != undefined ? val : this.getFromPrim(sprite, attr)]);
23386         }, this);
23387         return out;
23388     }
23389 });
23390
23391
23392 Ext.define('Ext.fx.target.Component', {
23393
23394     
23395    
23396     extend: 'Ext.fx.target.Target',
23397     
23398     
23399
23400     type: 'component',
23401
23402     
23403     getPropMethod: {
23404         top: function() {
23405             return this.getPosition(true)[1];
23406         },
23407         left: function() {
23408             return this.getPosition(true)[0];
23409         },
23410         x: function() {
23411             return this.getPosition()[0];
23412         },
23413         y: function() {
23414             return this.getPosition()[1];
23415         },
23416         height: function() {
23417             return this.getHeight();
23418         },
23419         width: function() {
23420             return this.getWidth();
23421         },
23422         opacity: function() {
23423             return this.el.getStyle('opacity');
23424         }
23425     },
23426
23427     compMethod: {
23428         top: 'setPosition',
23429         left: 'setPosition',
23430         x: 'setPagePosition',
23431         y: 'setPagePosition',
23432         height: 'setSize',
23433         width: 'setSize',
23434         opacity: 'setOpacity'
23435     },
23436
23437     
23438     getAttr: function(attr, val) {
23439         return [[this.target, val !== undefined ? val : this.getPropMethod[attr].call(this.target)]];
23440     },
23441
23442     setAttr: function(targetData, isFirstFrame, isLastFrame) {
23443         var me = this,
23444             target = me.target,
23445             ln = targetData.length,
23446             attrs, attr, o, i, j, meth, targets, left, top, w, h;
23447         for (i = 0; i < ln; i++) {
23448             attrs = targetData[i].attrs;
23449             for (attr in attrs) {
23450                 targets = attrs[attr].length;
23451                 meth = {
23452                     setPosition: {},
23453                     setPagePosition: {},
23454                     setSize: {},
23455                     setOpacity: {}
23456                 };
23457                 for (j = 0; j < targets; j++) {
23458                     o = attrs[attr][j];
23459                     
23460                     
23461                     
23462                     
23463                     meth[me.compMethod[attr]].target = o[0];
23464                     meth[me.compMethod[attr]][attr] = o[1];
23465                 }
23466                 if (meth.setPosition.target) {
23467                     o = meth.setPosition;
23468                     left = (o.left === undefined) ? undefined : parseInt(o.left, 10);
23469                     top = (o.top === undefined) ? undefined : parseInt(o.top, 10);
23470                     o.target.setPosition(left, top);
23471                 }
23472                 if (meth.setPagePosition.target) {
23473                     o = meth.setPagePosition;
23474                     o.target.setPagePosition(o.x, o.y);
23475                 }
23476                 if (meth.setSize.target) {
23477                     o = meth.setSize;
23478                     
23479                     w = (o.width === undefined) ? o.target.getWidth() : parseInt(o.width, 10);
23480                     h = (o.height === undefined) ? o.target.getHeight() : parseInt(o.height, 10);
23481
23482                     
23483                     
23484                     
23485                     
23486                     
23487                     
23488                     
23489                     if (isLastFrame || me.dynamic) {
23490                         o.target.componentLayout.childrenChanged = true;
23491
23492                         
23493                         if (me.layoutAnimation) {
23494                             o.target.setCalculatedSize(w, h);
23495                         } else {
23496                             o.target.setSize(w, h);
23497                         }
23498                     }
23499                     else {
23500                         o.target.el.setSize(w, h);
23501                     }
23502                 }
23503                 if (meth.setOpacity.target) {
23504                     o = meth.setOpacity;
23505                     o.target.el.setStyle('opacity', o.opacity);
23506                 }
23507             }
23508         }
23509     }
23510 });
23511
23512
23513 Ext.define('Ext.fx.CubicBezier', {
23514
23515     
23516
23517     singleton: true,
23518
23519     
23520
23521     cubicBezierAtTime: function(t, p1x, p1y, p2x, p2y, duration) {
23522         var cx = 3 * p1x,
23523             bx = 3 * (p2x - p1x) - cx,
23524             ax = 1 - cx - bx,
23525             cy = 3 * p1y,
23526             by = 3 * (p2y - p1y) - cy,
23527             ay = 1 - cy - by;
23528         function sampleCurveX(t) {
23529             return ((ax * t + bx) * t + cx) * t;
23530         }
23531         function solve(x, epsilon) {
23532             var t = solveCurveX(x, epsilon);
23533             return ((ay * t + by) * t + cy) * t;
23534         }
23535         function solveCurveX(x, epsilon) {
23536             var t0, t1, t2, x2, d2, i;
23537             for (t2 = x, i = 0; i < 8; i++) {
23538                 x2 = sampleCurveX(t2) - x;
23539                 if (Math.abs(x2) < epsilon) {
23540                     return t2;
23541                 }
23542                 d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
23543                 if (Math.abs(d2) < 1e-6) {
23544                     break;
23545                 }
23546                 t2 = t2 - x2 / d2;
23547             }
23548             t0 = 0;
23549             t1 = 1;
23550             t2 = x;
23551             if (t2 < t0) {
23552                 return t0;
23553             }
23554             if (t2 > t1) {
23555                 return t1;
23556             }
23557             while (t0 < t1) {
23558                 x2 = sampleCurveX(t2);
23559                 if (Math.abs(x2 - x) < epsilon) {
23560                     return t2;
23561                 }
23562                 if (x > x2) {
23563                     t0 = t2;
23564                 } else {
23565                     t1 = t2;
23566                 }
23567                 t2 = (t1 - t0) / 2 + t0;
23568             }
23569             return t2;
23570         }
23571         return solve(t, 1 / (200 * duration));
23572     },
23573
23574     cubicBezier: function(x1, y1, x2, y2) {
23575         var fn = function(pos) {
23576             return Ext.fx.CubicBezier.cubicBezierAtTime(pos, x1, y1, x2, y2, 1);
23577         };
23578         fn.toCSS3 = function() {
23579             return 'cubic-bezier(' + [x1, y1, x2, y2].join(',') + ')';
23580         };
23581         fn.reverse = function() {
23582             return Ext.fx.CubicBezier.cubicBezier(1 - x2, 1 - y2, 1 - x1, 1 - y1);
23583         };
23584         return fn;
23585     }
23586 });
23587
23588 Ext.define('Ext.draw.Color', {
23589
23590     
23591
23592     
23593
23594     colorToHexRe: /(.*?)rgb\((\d+),\s*(\d+),\s*(\d+)\)/,
23595     rgbRe: /\s*rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)\s*/,
23596     hexRe: /\s*#([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)\s*/,
23597
23598     
23599     lightnessFactor: 0.2,
23600
23601     
23602     constructor : function(red, green, blue) {
23603         var me = this,
23604             clamp = Ext.Number.constrain;
23605         me.r = clamp(red, 0, 255);
23606         me.g = clamp(green, 0, 255);
23607         me.b = clamp(blue, 0, 255);
23608     },
23609
23610     
23611     getRed: function() {
23612         return this.r;
23613     },
23614
23615     
23616     getGreen: function() {
23617         return this.g;
23618     },
23619
23620     
23621     getBlue: function() {
23622         return this.b;
23623     },
23624
23625     
23626     getRGB: function() {
23627         var me = this;
23628         return [me.r, me.g, me.b];
23629     },
23630
23631     
23632     getHSL: function() {
23633         var me = this,
23634             r = me.r / 255,
23635             g = me.g / 255,
23636             b = me.b / 255,
23637             max = Math.max(r, g, b),
23638             min = Math.min(r, g, b),
23639             delta = max - min,
23640             h,
23641             s = 0,
23642             l = 0.5 * (max + min);
23643
23644         
23645         if (min != max) {
23646             s = (l < 0.5) ? delta / (max + min) : delta / (2 - max - min);
23647             if (r == max) {
23648                 h = 60 * (g - b) / delta;
23649             } else if (g == max) {
23650                 h = 120 + 60 * (b - r) / delta;
23651             } else {
23652                 h = 240 + 60 * (r - g) / delta;
23653             }
23654             if (h < 0) {
23655                 h += 360;
23656             }
23657             if (h >= 360) {
23658                 h -= 360;
23659             }
23660         }
23661         return [h, s, l];
23662     },
23663
23664     
23665     getLighter: function(factor) {
23666         var hsl = this.getHSL();
23667         factor = factor || this.lightnessFactor;
23668         hsl[2] = Ext.Number.constrain(hsl[2] + factor, 0, 1);
23669         return this.fromHSL(hsl[0], hsl[1], hsl[2]);
23670     },
23671
23672     
23673     getDarker: function(factor) {
23674         factor = factor || this.lightnessFactor;
23675         return this.getLighter(-factor);
23676     },
23677
23678     
23679     toString: function() {
23680         var me = this,
23681             round = Math.round,
23682             r = round(me.r).toString(16),
23683             g = round(me.g).toString(16),
23684             b = round(me.b).toString(16);
23685         r = (r.length == 1) ? '0' + r : r;
23686         g = (g.length == 1) ? '0' + g : g;
23687         b = (b.length == 1) ? '0' + b : b;
23688         return ['#', r, g, b].join('');
23689     },
23690
23691     
23692     toHex: function(color) {
23693         if (Ext.isArray(color)) {
23694             color = color[0];
23695         }
23696         if (!Ext.isString(color)) {
23697             return '';
23698         }
23699         if (color.substr(0, 1) === '#') {
23700             return color;
23701         }
23702         var digits = this.colorToHexRe.exec(color);
23703
23704         if (Ext.isArray(digits)) {
23705             var red = parseInt(digits[2], 10),
23706                 green = parseInt(digits[3], 10),
23707                 blue = parseInt(digits[4], 10),
23708                 rgb = blue | (green << 8) | (red << 16);
23709             return digits[1] + '#' + ("000000" + rgb.toString(16)).slice(-6);
23710         }
23711         else {
23712             return '';
23713         }
23714     },
23715
23716     
23717     fromString: function(str) {
23718         var values, r, g, b,
23719             parse = parseInt;
23720
23721         if ((str.length == 4 || str.length == 7) && str.substr(0, 1) === '#') {
23722             values = str.match(this.hexRe);
23723             if (values) {
23724                 r = parse(values[1], 16) >> 0;
23725                 g = parse(values[2], 16) >> 0;
23726                 b = parse(values[3], 16) >> 0;
23727                 if (str.length == 4) {
23728                     r += (r * 16);
23729                     g += (g * 16);
23730                     b += (b * 16);
23731                 }
23732             }
23733         }
23734         else {
23735             values = str.match(this.rgbRe);
23736             if (values) {
23737                 r = values[1];
23738                 g = values[2];
23739                 b = values[3];
23740             }
23741         }
23742
23743         return (typeof r == 'undefined') ? undefined : Ext.create('Ext.draw.Color', r, g, b);
23744     },
23745
23746     
23747     getGrayscale: function() {
23748         
23749         return this.r * 0.3 + this.g * 0.59 + this.b * 0.11;
23750     },
23751
23752     
23753     fromHSL: function(h, s, l) {
23754         var C, X, m, i, rgb = [],
23755             abs = Math.abs,
23756             floor = Math.floor;
23757
23758         if (s == 0 || h == null) {
23759             
23760             rgb = [l, l, l];
23761         }
23762         else {
23763             
23764             
23765             
23766             
23767             h /= 60;
23768             C = s * (1 - abs(2 * l - 1));
23769             X = C * (1 - abs(h - 2 * floor(h / 2) - 1));
23770             m = l - C / 2;
23771             switch (floor(h)) {
23772                 case 0:
23773                     rgb = [C, X, 0];
23774                     break;
23775                 case 1:
23776                     rgb = [X, C, 0];
23777                     break;
23778                 case 2:
23779                     rgb = [0, C, X];
23780                     break;
23781                 case 3:
23782                     rgb = [0, X, C];
23783                     break;
23784                 case 4:
23785                     rgb = [X, 0, C];
23786                     break;
23787                 case 5:
23788                     rgb = [C, 0, X];
23789                     break;
23790             }
23791             rgb = [rgb[0] + m, rgb[1] + m, rgb[2] + m];
23792         }
23793         return Ext.create('Ext.draw.Color', rgb[0] * 255, rgb[1] * 255, rgb[2] * 255);
23794     }
23795 }, function() {
23796     var prototype = this.prototype;
23797
23798     
23799     this.addStatics({
23800         fromHSL: function() {
23801             return prototype.fromHSL.apply(prototype, arguments);
23802         },
23803         fromString: function() {
23804             return prototype.fromString.apply(prototype, arguments);
23805         },
23806         toHex: function() {
23807             return prototype.toHex.apply(prototype, arguments);
23808         }
23809     });
23810 });
23811
23812
23813 Ext.define('Ext.dd.StatusProxy', {
23814     animRepair: false,
23815
23816     constructor: function(config){
23817         Ext.apply(this, config);
23818         this.id = this.id || Ext.id();
23819         this.proxy = Ext.createWidget('component', {
23820             floating: true,
23821             id: this.id,
23822             html: '<div class="' + Ext.baseCSSPrefix + 'dd-drop-icon"></div>' +
23823                   '<div class="' + Ext.baseCSSPrefix + 'dd-drag-ghost"></div>',
23824             cls: Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed,
23825             shadow: !config || config.shadow !== false,
23826             renderTo: document.body
23827         });
23828
23829         this.el = this.proxy.el;
23830         this.el.show();
23831         this.el.setVisibilityMode(Ext.core.Element.VISIBILITY);
23832         this.el.hide();
23833
23834         this.ghost = Ext.get(this.el.dom.childNodes[1]);
23835         this.dropStatus = this.dropNotAllowed;
23836     },
23837     
23838     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
23839     
23840     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
23841
23842     
23843     setStatus : function(cssClass){
23844         cssClass = cssClass || this.dropNotAllowed;
23845         if(this.dropStatus != cssClass){
23846             this.el.replaceCls(this.dropStatus, cssClass);
23847             this.dropStatus = cssClass;
23848         }
23849     },
23850
23851     
23852     reset : function(clearGhost){
23853         this.el.dom.className = Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed;
23854         this.dropStatus = this.dropNotAllowed;
23855         if(clearGhost){
23856             this.ghost.update("");
23857         }
23858     },
23859
23860     
23861     update : function(html){
23862         if(typeof html == "string"){
23863             this.ghost.update(html);
23864         }else{
23865             this.ghost.update("");
23866             html.style.margin = "0";
23867             this.ghost.dom.appendChild(html);
23868         }
23869         var el = this.ghost.dom.firstChild; 
23870         if(el){
23871             Ext.fly(el).setStyle('float', 'none');
23872         }
23873     },
23874
23875     
23876     getEl : function(){
23877         return this.el;
23878     },
23879
23880     
23881     getGhost : function(){
23882         return this.ghost;
23883     },
23884
23885     
23886     hide : function(clear) {
23887         this.proxy.hide();
23888         if (clear) {
23889             this.reset(true);
23890         }
23891     },
23892
23893     
23894     stop : function(){
23895         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
23896             this.anim.stop();
23897         }
23898     },
23899
23900     
23901     show : function() {
23902         this.proxy.show();
23903         this.proxy.toFront();
23904     },
23905
23906     
23907     sync : function(){
23908         this.proxy.el.sync();
23909     },
23910
23911     
23912     repair : function(xy, callback, scope){
23913         this.callback = callback;
23914         this.scope = scope;
23915         if (xy && this.animRepair !== false) {
23916             this.el.addCls(Ext.baseCSSPrefix + 'dd-drag-repair');
23917             this.el.hideUnders(true);
23918             this.anim = this.el.animate({
23919                 duration: this.repairDuration || 500,
23920                 easing: 'ease-out',
23921                 to: {
23922                     x: xy[0],
23923                     y: xy[1]
23924                 },
23925                 stopAnimation: true,
23926                 callback: this.afterRepair,
23927                 scope: this
23928             });
23929         } else {
23930             this.afterRepair();
23931         }
23932     },
23933
23934     
23935     afterRepair : function(){
23936         this.hide(true);
23937         if(typeof this.callback == "function"){
23938             this.callback.call(this.scope || this);
23939         }
23940         this.callback = null;
23941         this.scope = null;
23942     },
23943
23944     destroy: function(){
23945         Ext.destroy(this.ghost, this.proxy, this.el);
23946     }
23947 });
23948
23949 Ext.define('Ext.panel.Proxy', {
23950     
23951     alternateClassName: 'Ext.dd.PanelProxy',
23952     
23953     constructor: function(panel, config){
23954         
23955         this.panel = panel;
23956         this.id = this.panel.id +'-ddproxy';
23957         Ext.apply(this, config);
23958     },
23959
23960     
23961     insertProxy: true,
23962
23963     
23964     setStatus: Ext.emptyFn,
23965     reset: Ext.emptyFn,
23966     update: Ext.emptyFn,
23967     stop: Ext.emptyFn,
23968     sync: Ext.emptyFn,
23969
23970     
23971     getEl: function(){
23972         return this.ghost.el;
23973     },
23974
23975     
23976     getGhost: function(){
23977         return this.ghost;
23978     },
23979
23980     
23981     getProxy: function(){
23982         return this.proxy;
23983     },
23984
23985     
23986     hide : function(){
23987         if (this.ghost) {
23988             if (this.proxy) {
23989                 this.proxy.remove();
23990                 delete this.proxy;
23991             }
23992
23993             
23994             this.panel.unghost(null, false);
23995             delete this.ghost;
23996         }
23997     },
23998
23999     
24000     show: function(){
24001         if (!this.ghost) {
24002             var panelSize = this.panel.getSize();
24003             this.panel.el.setVisibilityMode(Ext.core.Element.DISPLAY);
24004             this.ghost = this.panel.ghost();
24005             if (this.insertProxy) {
24006                 
24007                 
24008                 this.proxy = this.panel.el.insertSibling({cls: Ext.baseCSSPrefix + 'panel-dd-spacer'});
24009                 this.proxy.setSize(panelSize);
24010             }
24011         }
24012     },
24013
24014     
24015     repair: function(xy, callback, scope) {
24016         this.hide();
24017         if (typeof callback == "function") {
24018             callback.call(scope || this);
24019         }
24020     },
24021
24022     
24023     moveProxy : function(parentNode, before){
24024         if (this.proxy) {
24025             parentNode.insertBefore(this.proxy.dom, before);
24026         }
24027     }
24028 });
24029
24030
24031 Ext.define('Ext.layout.component.AbstractDock', {
24032
24033     
24034
24035     extend: 'Ext.layout.component.Component',
24036
24037     
24038
24039     type: 'dock',
24040
24041     
24042     autoSizing: true,
24043
24044     beforeLayout: function() {
24045         var returnValue = this.callParent(arguments);
24046         if (returnValue !== false && (!this.initializedBorders || this.childrenChanged) && (!this.owner.border || this.owner.manageBodyBorders)) {
24047             this.handleItemBorders();
24048             this.initializedBorders = true;
24049         }
24050         return returnValue;
24051     },
24052     
24053     handleItemBorders: function() {
24054         var owner = this.owner,
24055             body = owner.body,
24056             docked = this.getLayoutItems(),
24057             borders = {
24058                 top: [],
24059                 right: [],
24060                 bottom: [],
24061                 left: []
24062             },
24063             oldBorders = this.borders,
24064             opposites = {
24065                 top: 'bottom',
24066                 right: 'left',
24067                 bottom: 'top',
24068                 left: 'right'
24069             },
24070             i, ln, item, dock, side;
24071
24072         for (i = 0, ln = docked.length; i < ln; i++) {
24073             item = docked[i];
24074             dock = item.dock;
24075             
24076             if (item.ignoreBorderManagement) {
24077                 continue;
24078             }
24079             
24080             if (!borders[dock].satisfied) {
24081                 borders[dock].push(item);
24082                 borders[dock].satisfied = true;
24083             }
24084             
24085             if (!borders.top.satisfied && opposites[dock] !== 'top') {
24086                 borders.top.push(item);
24087             }
24088             if (!borders.right.satisfied && opposites[dock] !== 'right') {
24089                 borders.right.push(item);
24090             }            
24091             if (!borders.bottom.satisfied && opposites[dock] !== 'bottom') {
24092                 borders.bottom.push(item);
24093             }            
24094             if (!borders.left.satisfied && opposites[dock] !== 'left') {
24095                 borders.left.push(item);
24096             }
24097         }
24098
24099         if (oldBorders) {
24100             for (side in oldBorders) {
24101                 if (oldBorders.hasOwnProperty(side)) {
24102                     ln = oldBorders[side].length;
24103                     if (!owner.manageBodyBorders) {
24104                         for (i = 0; i < ln; i++) {
24105                             oldBorders[side][i].removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
24106                         }
24107                         if (!oldBorders[side].satisfied && !owner.bodyBorder) {
24108                             body.removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);                   
24109                         }                    
24110                     }
24111                     else if (oldBorders[side].satisfied) {
24112                         body.setStyle('border-' + side + '-width', '');
24113                     }
24114                 }
24115             }
24116         }
24117                 
24118         for (side in borders) {
24119             if (borders.hasOwnProperty(side)) {
24120                 ln = borders[side].length;
24121                 if (!owner.manageBodyBorders) {
24122                     for (i = 0; i < ln; i++) {
24123                         borders[side][i].addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
24124                     }
24125                     if ((!borders[side].satisfied && !owner.bodyBorder) || owner.bodyBorder === false) {
24126                         body.addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);                   
24127                     }                    
24128                 }
24129                 else if (borders[side].satisfied) {
24130                     body.setStyle('border-' + side + '-width', '1px');
24131                 }
24132             }
24133         }
24134         
24135         this.borders = borders;
24136     },
24137     
24138     
24139     onLayout: function(width, height) {
24140         var me = this,
24141             owner = me.owner,
24142             body = owner.body,
24143             layout = owner.layout,
24144             target = me.getTarget(),
24145             autoWidth = false,
24146             autoHeight = false,
24147             padding, border, frameSize;
24148
24149         
24150         var info = me.info = {
24151             boxes: [],
24152             size: {
24153                 width: width,
24154                 height: height
24155             },
24156             bodyBox: {}
24157         };
24158
24159         Ext.applyIf(info, me.getTargetInfo());
24160
24161         
24162         if (owner && owner.ownerCt && owner.ownerCt.layout && owner.ownerCt.layout.isLayout) {
24163             if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
24164                 owner.ownerCt.layout.bindToOwnerCtComponent = true;
24165             }
24166             else {
24167                 owner.ownerCt.layout.bindToOwnerCtComponent = false;
24168             }
24169         }
24170
24171         
24172         if (height === undefined || height === null || width === undefined || width === null) {
24173             padding = info.padding;
24174             border = info.border;
24175             frameSize = me.frameSize;
24176
24177             
24178             if ((height === undefined || height === null) && (width === undefined || width === null)) {
24179                 autoHeight = true;
24180                 autoWidth = true;
24181                 me.setTargetSize(null);
24182                 me.setBodyBox({width: null, height: null});
24183             }
24184             
24185             else if (height === undefined || height === null) {
24186                 autoHeight = true;
24187                 
24188                 me.setTargetSize(width);
24189                 me.setBodyBox({width: width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right, height: null});
24190             
24191             }
24192             else {
24193                 autoWidth = true;
24194                 
24195                 me.setTargetSize(null, height);
24196                 me.setBodyBox({width: null, height: height - padding.top - padding.bottom - border.top - border.bottom - frameSize.top - frameSize.bottom});
24197             }
24198
24199             
24200             if (layout && layout.isLayout) {
24201                 
24202                 layout.bindToOwnerCtComponent = true;
24203                 layout.layout();
24204
24205                 
24206                 
24207                 
24208                 
24209                 
24210                 
24211                 
24212                 
24213                 
24214                 
24215                 
24216                 
24217                 info.autoSizedCtLayout = layout.autoSize === true;
24218             }
24219
24220             
24221             
24222             
24223             
24224             
24225             me.dockItems(autoWidth, autoHeight);
24226             me.setTargetSize(info.size.width, info.size.height);
24227         }
24228         else {
24229             me.setTargetSize(width, height);
24230             me.dockItems();
24231         }
24232         me.callParent(arguments);
24233     },
24234
24235     
24236     dockItems : function(autoWidth, autoHeight) {
24237         this.calculateDockBoxes(autoWidth, autoHeight);
24238
24239         
24240         
24241         
24242         var info = this.info,
24243             boxes = info.boxes,
24244             ln = boxes.length,
24245             dock, i;
24246
24247         
24248         
24249         for (i = 0; i < ln; i++) {
24250             dock = boxes[i];
24251             dock.item.setPosition(dock.x, dock.y);
24252             if ((autoWidth || autoHeight) && dock.layout && dock.layout.isLayout) {
24253                 
24254                 dock.layout.bindToOwnerCtComponent = true;
24255             }
24256         }
24257
24258         
24259         
24260         if (!info.autoSizedCtLayout) {
24261             if (autoWidth) {
24262                 info.bodyBox.width = null;
24263             }
24264             if (autoHeight) {
24265                 info.bodyBox.height = null;
24266             }
24267         }
24268
24269         
24270         
24271         this.setBodyBox(info.bodyBox);
24272     },
24273
24274     
24275     calculateDockBoxes : function(autoWidth, autoHeight) {
24276         
24277         
24278         
24279         var me = this,
24280             target = me.getTarget(),
24281             items = me.getLayoutItems(),
24282             owner = me.owner,
24283             bodyEl = owner.body,
24284             info = me.info,
24285             size = info.size,
24286             ln = items.length,
24287             padding = info.padding,
24288             border = info.border,
24289             frameSize = me.frameSize,
24290             item, i, box, rect;
24291
24292         
24293         
24294         if (autoHeight) {
24295             size.height = bodyEl.getHeight() + padding.top + border.top + padding.bottom + border.bottom + frameSize.top + frameSize.bottom;
24296         }
24297         else {
24298             size.height = target.getHeight();
24299         }
24300         if (autoWidth) {
24301             size.width = bodyEl.getWidth() + padding.left + border.left + padding.right + border.right + frameSize.left + frameSize.right;
24302         }
24303         else {
24304             size.width = target.getWidth();
24305         }
24306
24307         info.bodyBox = {
24308             x: padding.left + frameSize.left,
24309             y: padding.top + frameSize.top,
24310             width: size.width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right,
24311             height: size.height - border.top - padding.top - border.bottom - padding.bottom - frameSize.top - frameSize.bottom
24312         };
24313
24314         
24315         for (i = 0; i < ln; i++) {
24316             item = items[i];
24317             
24318             
24319             
24320             box = me.initBox(item);
24321
24322             if (autoHeight === true) {
24323                 box = me.adjustAutoBox(box, i);
24324             }
24325             else {
24326                 box = me.adjustSizedBox(box, i);
24327             }
24328
24329             
24330             
24331             
24332             info.boxes.push(box);
24333         }
24334     },
24335
24336     
24337     adjustSizedBox : function(box, index) {
24338         var bodyBox = this.info.bodyBox,
24339             frameSize = this.frameSize,
24340             info = this.info,
24341             padding = info.padding,
24342             pos = box.type,
24343             border = info.border;
24344
24345         switch (pos) {
24346             case 'top':
24347                 box.y = bodyBox.y;
24348                 break;
24349
24350             case 'left':
24351                 box.x = bodyBox.x;
24352                 break;
24353
24354             case 'bottom':
24355                 box.y = (bodyBox.y + bodyBox.height) - box.height;
24356                 break;
24357
24358             case 'right':
24359                 box.x = (bodyBox.x + bodyBox.width) - box.width;
24360                 break;
24361         }
24362
24363         if (box.ignoreFrame) {
24364             if (pos == 'bottom') {
24365                 box.y += (frameSize.bottom + padding.bottom + border.bottom);
24366             }
24367             else {
24368                 box.y -= (frameSize.top + padding.top + border.top);
24369             }
24370             if (pos == 'right') {
24371                 box.x += (frameSize.right + padding.right + border.right);
24372             }
24373             else {
24374                 box.x -= (frameSize.left + padding.left + border.left);
24375             }
24376         }
24377
24378         
24379         if (!box.overlay) {
24380             switch (pos) {
24381                 case 'top':
24382                     bodyBox.y += box.height;
24383                     bodyBox.height -= box.height;
24384                     break;
24385
24386                 case 'left':
24387                     bodyBox.x += box.width;
24388                     bodyBox.width -= box.width;
24389                     break;
24390
24391                 case 'bottom':
24392                     bodyBox.height -= box.height;
24393                     break;
24394
24395                 case 'right':
24396                     bodyBox.width -= box.width;
24397                     break;
24398             }
24399         }
24400         return box;
24401     },
24402
24403     
24404     adjustAutoBox : function (box, index) {
24405         var info = this.info,
24406             bodyBox = info.bodyBox,
24407             size = info.size,
24408             boxes = info.boxes,
24409             boxesLn = boxes.length,
24410             pos = box.type,
24411             frameSize = this.frameSize,
24412             padding = info.padding,
24413             border = info.border,
24414             autoSizedCtLayout = info.autoSizedCtLayout,
24415             ln = (boxesLn < index) ? boxesLn : index,
24416             i, adjustBox;
24417
24418         if (pos == 'top' || pos == 'bottom') {
24419             
24420             for (i = 0; i < ln; i++) {
24421                 adjustBox = boxes[i];
24422                 if (adjustBox.stretched && adjustBox.type == 'left' || adjustBox.type == 'right') {
24423                     adjustBox.height += box.height;
24424                 }
24425                 else if (adjustBox.type == 'bottom') {
24426                     adjustBox.y += box.height;
24427                 }
24428             }
24429         }
24430
24431         switch (pos) {
24432             case 'top':
24433                 box.y = bodyBox.y;
24434                 if (!box.overlay) {
24435                     bodyBox.y += box.height;
24436                 }
24437                 size.height += box.height;
24438                 break;
24439
24440             case 'bottom':
24441                 box.y = (bodyBox.y + bodyBox.height);
24442                 size.height += box.height;
24443                 break;
24444
24445             case 'left':
24446                 box.x = bodyBox.x;
24447                 if (!box.overlay) {
24448                     bodyBox.x += box.width;
24449                     if (autoSizedCtLayout) {
24450                         size.width += box.width;
24451                     } else {
24452                         bodyBox.width -= box.width;
24453                     }
24454                 }
24455                 break;
24456
24457             case 'right':
24458                 if (!box.overlay) {
24459                     if (autoSizedCtLayout) {
24460                         size.width += box.width;
24461                     } else {
24462                         bodyBox.width -= box.width;
24463                     }
24464                 }
24465                 box.x = (bodyBox.x + bodyBox.width);
24466                 break;
24467         }
24468
24469         if (box.ignoreFrame) {
24470             if (pos == 'bottom') {
24471                 box.y += (frameSize.bottom + padding.bottom + border.bottom);
24472             }
24473             else {
24474                 box.y -= (frameSize.top + padding.top + border.top);
24475             }
24476             if (pos == 'right') {
24477                 box.x += (frameSize.right + padding.right + border.right);
24478             }
24479             else {
24480                 box.x -= (frameSize.left + padding.left + border.left);
24481             }
24482         }
24483         return box;
24484     },
24485
24486     
24487     initBox : function(item) {
24488         var me = this,
24489             bodyBox = me.info.bodyBox,
24490             horizontal = (item.dock == 'top' || item.dock == 'bottom'),
24491             owner = me.owner,
24492             frameSize = me.frameSize,
24493             info = me.info,
24494             padding = info.padding,
24495             border = info.border,
24496             box = {
24497                 item: item,
24498                 overlay: item.overlay,
24499                 type: item.dock,
24500                 offsets: Ext.core.Element.parseBox(item.offsets || {}),
24501                 ignoreFrame: item.ignoreParentFrame
24502             };
24503         
24504         if (item.stretch !== false) {
24505             box.stretched = true;
24506             if (horizontal) {
24507                 box.x = bodyBox.x + box.offsets.left;
24508                 box.width = bodyBox.width - (box.offsets.left + box.offsets.right);
24509                 if (box.ignoreFrame) {
24510                     box.width += (frameSize.left + frameSize.right + border.left + border.right + padding.left + padding.right);
24511                 }
24512                 item.setCalculatedSize(box.width - item.el.getMargin('lr'), undefined, owner);
24513             }
24514             else {
24515                 box.y = bodyBox.y + box.offsets.top;
24516                 box.height = bodyBox.height - (box.offsets.bottom + box.offsets.top);
24517                 if (box.ignoreFrame) {
24518                     box.height += (frameSize.top + frameSize.bottom + border.top + border.bottom + padding.top + padding.bottom);
24519                 }
24520                 item.setCalculatedSize(undefined, box.height - item.el.getMargin('tb'), owner);
24521
24522                 
24523                 
24524                 if (!Ext.supports.ComputedStyle) {
24525                     item.el.repaint();
24526                 }
24527             }
24528         }
24529         else {
24530             item.doComponentLayout();
24531             box.width = item.getWidth() - (box.offsets.left + box.offsets.right);
24532             box.height = item.getHeight() - (box.offsets.bottom + box.offsets.top);
24533             box.y += box.offsets.top;
24534             if (horizontal) {
24535                 box.x = (item.align == 'right') ? bodyBox.width - box.width : bodyBox.x;
24536                 box.x += box.offsets.left;
24537             }
24538         }
24539
24540         
24541         
24542         if (box.width == undefined) {
24543             box.width = item.getWidth() + item.el.getMargin('lr');
24544         }
24545         if (box.height == undefined) {
24546             box.height = item.getHeight() + item.el.getMargin('tb');
24547         }
24548
24549         return box;
24550     },
24551
24552     
24553     getLayoutItems : function() {
24554         var it = this.owner.getDockedItems(),
24555             ln = it.length,
24556             i = 0,
24557             result = [];
24558         for (; i < ln; i++) {
24559             if (it[i].isVisible(true)) {
24560                 result.push(it[i]);
24561             }
24562         }
24563         return result;
24564     },
24565
24566     
24567     renderItems: function(items, target) {
24568         var cns = target.dom.childNodes,
24569             cnsLn = cns.length,
24570             ln = items.length,
24571             domLn = 0,
24572             i, j, cn, item;
24573
24574         
24575         for (i = 0; i < cnsLn; i++) {
24576             cn = Ext.get(cns[i]);
24577             for (j = 0; j < ln; j++) {
24578                 item = items[j];
24579                 if (item.rendered && (cn.id == item.el.id || cn.down('#' + item.el.id))) {
24580                     break;
24581                 }
24582             }
24583
24584             if (j === ln) {
24585                 domLn++;
24586             }
24587         }
24588
24589         
24590         for (i = 0, j = 0; i < ln; i++, j++) {
24591             item = items[i];
24592
24593             
24594             
24595             
24596             
24597             
24598             
24599             
24600             
24601             if (i === j && (item.dock === 'right' || item.dock === 'bottom')) {
24602                 j += domLn;
24603             }
24604
24605             
24606             if (item && !item.rendered) {
24607                 this.renderItem(item, target, j);
24608             }
24609             else if (!this.isValidParent(item, target, j)) {
24610                 this.moveItem(item, target, j);
24611             }
24612         }
24613     },
24614
24615     
24616     setBodyBox : function(box) {
24617         var me = this,
24618             owner = me.owner,
24619             body = owner.body,
24620             info = me.info,
24621             bodyMargin = info.bodyMargin,
24622             padding = info.padding,
24623             border = info.border,
24624             frameSize = me.frameSize;
24625         
24626         
24627         if (owner.collapsed) {
24628             return;
24629         }
24630         
24631         if (Ext.isNumber(box.width)) {
24632             box.width -= bodyMargin.left + bodyMargin.right;
24633         }
24634         
24635         if (Ext.isNumber(box.height)) {
24636             box.height -= bodyMargin.top + bodyMargin.bottom;
24637         }
24638         
24639         me.setElementSize(body, box.width, box.height);
24640         if (Ext.isNumber(box.x)) {
24641             body.setLeft(box.x - padding.left - frameSize.left);
24642         }
24643         if (Ext.isNumber(box.y)) {
24644             body.setTop(box.y - padding.top - frameSize.top);
24645         }
24646     },
24647
24648     
24649     configureItem : function(item, pos) {
24650         this.callParent(arguments);
24651         
24652         item.addCls(Ext.baseCSSPrefix + 'docked');
24653         item.addClsWithUI('docked-' + item.dock);
24654     },
24655
24656     afterRemove : function(item) {
24657         this.callParent(arguments);
24658         if (this.itemCls) {
24659             item.el.removeCls(this.itemCls + '-' + item.dock);
24660         }
24661         var dom = item.el.dom;
24662
24663         if (!item.destroying && dom) {
24664             dom.parentNode.removeChild(dom);
24665         }
24666         this.childrenChanged = true;
24667     }
24668 });
24669
24670 Ext.define('Ext.app.EventBus', {
24671     requires: [
24672         'Ext.util.Event'
24673     ],
24674     mixins: {
24675         observable: 'Ext.util.Observable'
24676     },
24677     
24678     constructor: function() {
24679         this.mixins.observable.constructor.call(this);
24680         
24681         this.bus = {};
24682         
24683         var me = this;
24684         Ext.override(Ext.Component, {
24685             fireEvent: function(ev) {
24686                 if (Ext.util.Observable.prototype.fireEvent.apply(this, arguments) !== false) {
24687                     return me.dispatch.call(me, ev, this, arguments);
24688                 }
24689                 return false;
24690             }
24691         });
24692     },
24693
24694     dispatch: function(ev, target, args) {
24695         var bus = this.bus,
24696             selectors = bus[ev],
24697             selector, controllers, id, events, event, i, ln;
24698         
24699         if (selectors) {
24700             
24701             for (selector in selectors) {
24702                 
24703                 if (target.is(selector)) {
24704                     
24705                     controllers = selectors[selector];
24706                     for (id in controllers) {
24707                         
24708                         events = controllers[id];
24709                         for (i = 0, ln = events.length; i < ln; i++) {
24710                             event = events[i];
24711                             
24712                             return event.fire.apply(event, Array.prototype.slice.call(args, 1));
24713                         }
24714                     }
24715                 }
24716             }
24717         }
24718     },
24719     
24720     control: function(selectors, listeners, controller) {
24721         var bus = this.bus,
24722             selector, fn;
24723         
24724         if (Ext.isString(selectors)) {
24725             selector = selectors;
24726             selectors = {};
24727             selectors[selector] = listeners;
24728             this.control(selectors, null, controller);
24729             return;
24730         }
24731     
24732         Ext.Object.each(selectors, function(selector, listeners) {
24733             Ext.Object.each(listeners, function(ev, listener) {
24734                 var options = {},   
24735                     scope = controller,
24736                     event = Ext.create('Ext.util.Event', controller, ev);
24737                 
24738                 
24739                 if (Ext.isObject(listener)) {
24740                     options = listener;
24741                     listener = options.fn;
24742                     scope = options.scope || controller;
24743                     delete options.fn;
24744                     delete options.scope;
24745                 }
24746                 
24747                 event.addListener(listener, scope, options);
24748
24749                 
24750                 bus[ev] = bus[ev] || {};
24751                 bus[ev][selector] = bus[ev][selector] || {};
24752                 bus[ev][selector][controller.id] = bus[ev][selector][controller.id] || [];            
24753                 
24754                 
24755                 bus[ev][selector][controller.id].push(event);
24756             });
24757         });
24758     }
24759 });
24760
24761 Ext.define('Ext.data.Types', {
24762     singleton: true,
24763     requires: ['Ext.data.SortTypes']
24764 }, function() {
24765     var st = Ext.data.SortTypes;
24766     
24767     Ext.apply(Ext.data.Types, {
24768         
24769         stripRe: /[\$,%]/g,
24770         
24771         
24772         AUTO: {
24773             convert: function(v) {
24774                 return v;
24775             },
24776             sortType: st.none,
24777             type: 'auto'
24778         },
24779
24780         
24781         STRING: {
24782             convert: function(v) {
24783                 var defaultValue = this.useNull ? null : '';
24784                 return (v === undefined || v === null) ? defaultValue : String(v);
24785             },
24786             sortType: st.asUCString,
24787             type: 'string'
24788         },
24789
24790         
24791         INT: {
24792             convert: function(v) {
24793                 return v !== undefined && v !== null && v !== '' ?
24794                     parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
24795             },
24796             sortType: st.none,
24797             type: 'int'
24798         },
24799         
24800         
24801         FLOAT: {
24802             convert: function(v) {
24803                 return v !== undefined && v !== null && v !== '' ?
24804                     parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
24805             },
24806             sortType: st.none,
24807             type: 'float'
24808         },
24809         
24810         
24811         BOOL: {
24812             convert: function(v) {
24813                 if (this.useNull && v === undefined || v === null || v === '') {
24814                     return null;
24815                 }
24816                 return v === true || v === 'true' || v == 1;
24817             },
24818             sortType: st.none,
24819             type: 'bool'
24820         },
24821         
24822         
24823         DATE: {
24824             convert: function(v) {
24825                 var df = this.dateFormat;
24826                 if (!v) {
24827                     return null;
24828                 }
24829                 if (Ext.isDate(v)) {
24830                     return v;
24831                 }
24832                 if (df) {
24833                     if (df == 'timestamp') {
24834                         return new Date(v*1000);
24835                     }
24836                     if (df == 'time') {
24837                         return new Date(parseInt(v, 10));
24838                     }
24839                     return Ext.Date.parse(v, df);
24840                 }
24841                 
24842                 var parsed = Date.parse(v);
24843                 return parsed ? new Date(parsed) : null;
24844             },
24845             sortType: st.asDate,
24846             type: 'date'
24847         }
24848     });
24849     
24850     Ext.apply(Ext.data.Types, {
24851         
24852         BOOLEAN: this.BOOL,
24853         
24854         
24855         INTEGER: this.INT,
24856         
24857         
24858         NUMBER: this.FLOAT    
24859     });
24860 });
24861
24862
24863 Ext.define('Ext.data.Field', {
24864     requires: ['Ext.data.Types', 'Ext.data.SortTypes'],
24865     alias: 'data.field',
24866     
24867     constructor : function(config) {
24868         if (Ext.isString(config)) {
24869             config = {name: config};
24870         }
24871         Ext.apply(this, config);
24872         
24873         var types = Ext.data.Types,
24874             st = this.sortType,
24875             t;
24876
24877         if (this.type) {
24878             if (Ext.isString(this.type)) {
24879                 this.type = types[this.type.toUpperCase()] || types.AUTO;
24880             }
24881         } else {
24882             this.type = types.AUTO;
24883         }
24884
24885         
24886         if (Ext.isString(st)) {
24887             this.sortType = Ext.data.SortTypes[st];
24888         } else if(Ext.isEmpty(st)) {
24889             this.sortType = this.type.sortType;
24890         }
24891
24892         if (!this.convert) {
24893             this.convert = this.type.convert;
24894         }
24895     },
24896     
24897     
24898     
24899     
24900     
24901     
24902     
24903     dateFormat: null,
24904     
24905     
24906     useNull: false,
24907     
24908     
24909     defaultValue: "",
24910     
24911     mapping: null,
24912     
24913     sortType : null,
24914     
24915     sortDir : "ASC",
24916     
24917     allowBlank : true,
24918     
24919     
24920     persist: true
24921 });
24922
24923
24924 Ext.define('Ext.data.reader.Reader', {
24925     requires: ['Ext.data.ResultSet'],
24926     alternateClassName: ['Ext.data.Reader', 'Ext.data.DataReader'],
24927     
24928     
24929
24930     
24931     totalProperty: 'total',
24932
24933     
24934     successProperty: 'success',
24935
24936     
24937     root: '',
24938     
24939     
24940     
24941     
24942     implicitIncludes: true,
24943     
24944     isReader: true,
24945     
24946     constructor: function(config) {
24947         var me = this;
24948         
24949         Ext.apply(me, config || {});
24950         me.fieldCount = 0;
24951         me.model = Ext.ModelManager.getModel(config.model);
24952         if (me.model) {
24953             me.buildExtractors();
24954         }
24955     },
24956
24957     
24958     setModel: function(model, setOnProxy) {
24959         var me = this;
24960         
24961         me.model = Ext.ModelManager.getModel(model);
24962         me.buildExtractors(true);
24963         
24964         if (setOnProxy && me.proxy) {
24965             me.proxy.setModel(me.model, true);
24966         }
24967     },
24968
24969     
24970     read: function(response) {
24971         var data = response;
24972         
24973         if (response && response.responseText) {
24974             data = this.getResponseData(response);
24975         }
24976         
24977         if (data) {
24978             return this.readRecords(data);
24979         } else {
24980             return this.nullResultSet;
24981         }
24982     },
24983
24984     
24985     readRecords: function(data) {
24986         var me  = this;
24987         
24988         
24989         if (me.fieldCount !== me.getFields().length) {
24990             me.buildExtractors(true);
24991         }
24992         
24993         
24994         me.rawData = data;
24995
24996         data = me.getData(data);
24997
24998         
24999         
25000         var root    = Ext.isArray(data) ? data : me.getRoot(data),
25001             success = true,
25002             recordCount = 0,
25003             total, value, records, message;
25004             
25005         if (root) {
25006             total = root.length;
25007         }
25008
25009         if (me.totalProperty) {
25010             value = parseInt(me.getTotal(data), 10);
25011             if (!isNaN(value)) {
25012                 total = value;
25013             }
25014         }
25015
25016         if (me.successProperty) {
25017             value = me.getSuccess(data);
25018             if (value === false || value === 'false') {
25019                 success = false;
25020             }
25021         }
25022         
25023         if (me.messageProperty) {
25024             message = me.getMessage(data);
25025         }
25026         
25027         if (root) {
25028             records = me.extractData(root);
25029             recordCount = records.length;
25030         } else {
25031             recordCount = 0;
25032             records = [];
25033         }
25034
25035         return Ext.create('Ext.data.ResultSet', {
25036             total  : total || recordCount,
25037             count  : recordCount,
25038             records: records,
25039             success: success,
25040             message: message
25041         });
25042     },
25043
25044     
25045     extractData : function(root) {
25046         var me = this,
25047             values  = [],
25048             records = [],
25049             Model   = me.model,
25050             i       = 0,
25051             length  = root.length,
25052             idProp  = me.getIdProperty(),
25053             node, id, record;
25054             
25055         if (!root.length && Ext.isObject(root)) {
25056             root = [root];
25057             length = 1;
25058         }
25059
25060         for (; i < length; i++) {
25061             node   = root[i];
25062             values = me.extractValues(node);
25063             id     = me.getId(node);
25064
25065             
25066             record = new Model(values, id);
25067             record.raw = node;
25068             records.push(record);
25069                 
25070             if (me.implicitIncludes) {
25071                 me.readAssociated(record, node);
25072             }
25073         }
25074
25075         return records;
25076     },
25077     
25078     
25079     readAssociated: function(record, data) {
25080         var associations = record.associations.items,
25081             i            = 0,
25082             length       = associations.length,
25083             association, associationData, proxy, reader;
25084         
25085         for (; i < length; i++) {
25086             association     = associations[i];
25087             associationData = this.getAssociatedDataRoot(data, association.associationKey || association.name);
25088             
25089             if (associationData) {
25090                 reader = association.getReader();
25091                 if (!reader) {
25092                     proxy = association.associatedModel.proxy;
25093                     
25094                     if (proxy) {
25095                         reader = proxy.getReader();
25096                     } else {
25097                         reader = new this.constructor({
25098                             model: association.associatedName
25099                         });
25100                     }
25101                 }
25102                 association.read(record, reader, associationData);
25103             }  
25104         }
25105     },
25106     
25107     
25108     getAssociatedDataRoot: function(data, associationName) {
25109         return data[associationName];
25110     },
25111     
25112     getFields: function() {
25113         return this.model.prototype.fields.items;
25114     },
25115
25116     
25117     extractValues: function(data) {
25118         var fields = this.getFields(),
25119             i      = 0,
25120             length = fields.length,
25121             output = {},
25122             field, value;
25123
25124         for (; i < length; i++) {
25125             field = fields[i];
25126             value = this.extractorFunctions[i](data);
25127
25128             output[field.name] = value;
25129         }
25130
25131         return output;
25132     },
25133
25134     
25135     getData: function(data) {
25136         return data;
25137     },
25138
25139     
25140     getRoot: function(data) {
25141         return data;
25142     },
25143
25144     
25145     getResponseData: function(response) {
25146         Ext.Error.raise("getResponseData must be implemented in the Ext.data.reader.Reader subclass");
25147     },
25148
25149     
25150     onMetaChange : function(meta) {
25151         var fields = meta.fields,
25152             newModel;
25153         
25154         Ext.apply(this, meta);
25155         
25156         if (fields) {
25157             newModel = Ext.define("Ext.data.reader.Json-Model" + Ext.id(), {
25158                 extend: 'Ext.data.Model',
25159                 fields: fields
25160             });
25161             this.setModel(newModel, true);
25162         } else {
25163             this.buildExtractors(true);
25164         }
25165     },
25166     
25167     
25168     getIdProperty: function(){
25169         var prop = this.idProperty;
25170         if (Ext.isEmpty(prop)) {
25171             prop = this.model.prototype.idProperty;
25172         }
25173         return prop;
25174     },
25175
25176     
25177     buildExtractors: function(force) {
25178         var me          = this,
25179             idProp      = me.getIdProperty(),
25180             totalProp   = me.totalProperty,
25181             successProp = me.successProperty,
25182             messageProp = me.messageProperty,
25183             accessor;
25184             
25185         if (force === true) {
25186             delete me.extractorFunctions;
25187         }
25188         
25189         if (me.extractorFunctions) {
25190             return;
25191         }   
25192
25193         
25194         if (totalProp) {
25195             me.getTotal = me.createAccessor(totalProp);
25196         }
25197
25198         if (successProp) {
25199             me.getSuccess = me.createAccessor(successProp);
25200         }
25201
25202         if (messageProp) {
25203             me.getMessage = me.createAccessor(messageProp);
25204         }
25205
25206         if (idProp) {
25207             accessor = me.createAccessor(idProp);
25208
25209             me.getId = function(record) {
25210                 var id = accessor.call(me, record);
25211                 return (id === undefined || id === '') ? null : id;
25212             };
25213         } else {
25214             me.getId = function() {
25215                 return null;
25216             };
25217         }
25218         me.buildFieldExtractors();
25219     },
25220
25221     
25222     buildFieldExtractors: function() {
25223         
25224         var me = this,
25225             fields = me.getFields(),
25226             ln = fields.length,
25227             i  = 0,
25228             extractorFunctions = [],
25229             field, map;
25230
25231         for (; i < ln; i++) {
25232             field = fields[i];
25233             map   = (field.mapping !== undefined && field.mapping !== null) ? field.mapping : field.name;
25234
25235             extractorFunctions.push(me.createAccessor(map));
25236         }
25237         me.fieldCount = ln;
25238
25239         me.extractorFunctions = extractorFunctions;
25240     }
25241 }, function() {
25242     Ext.apply(this, {
25243         
25244         nullResultSet: Ext.create('Ext.data.ResultSet', {
25245             total  : 0,
25246             count  : 0,
25247             records: [],
25248             success: true
25249         })
25250     });
25251 });
25252
25253 Ext.define('Ext.data.reader.Json', {
25254     extend: 'Ext.data.reader.Reader',
25255     alternateClassName: 'Ext.data.JsonReader',
25256     alias : 'reader.json',
25257     
25258     root: '',
25259     
25260     
25261     
25262     
25263     useSimpleAccessors: false,
25264     
25265     
25266     readRecords: function(data) {
25267         
25268         if (data.metaData) {
25269             this.onMetaChange(data.metaData);
25270         }
25271
25272         
25273         this.jsonData = data;
25274         return this.callParent([data]);
25275     },
25276
25277     
25278     getResponseData: function(response) {
25279         try {
25280             var data = Ext.decode(response.responseText);
25281         }
25282         catch (ex) {
25283             Ext.Error.raise({
25284                 response: response,
25285                 json: response.responseText,
25286                 parseError: ex,
25287                 msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
25288             });
25289         }
25290         if (!data) {
25291             Ext.Error.raise('JSON object not found');
25292         }
25293
25294         return data;
25295     },
25296
25297     
25298     buildExtractors : function() {
25299         var me = this;
25300         
25301         me.callParent(arguments);
25302
25303         if (me.root) {
25304             me.getRoot = me.createAccessor(me.root);
25305         } else {
25306             me.getRoot = function(root) {
25307                 return root;
25308             };
25309         }
25310     },
25311     
25312     
25313     extractData: function(root) {
25314         var recordName = this.record,
25315             data = [],
25316             length, i;
25317         
25318         if (recordName) {
25319             length = root.length;
25320             
25321             for (i = 0; i < length; i++) {
25322                 data[i] = root[i][recordName];
25323             }
25324         } else {
25325             data = root;
25326         }
25327         return this.callParent([data]);
25328     },
25329
25330     
25331     createAccessor: function() {
25332         var re = /[\[\.]/;
25333         
25334         return function(expr) {
25335             if (Ext.isEmpty(expr)) {
25336                 return Ext.emptyFn;
25337             }
25338             if (Ext.isFunction(expr)) {
25339                 return expr;
25340             }
25341             if (this.useSimpleAccessors !== true) {
25342                 var i = String(expr).search(re);
25343                 if (i >= 0) {
25344                     return Ext.functionFactory('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
25345                 }
25346             }
25347             return function(obj) {
25348                 return obj[expr];
25349             };
25350         };
25351     }()
25352 });
25353
25354 Ext.define('Ext.data.writer.Json', {
25355     extend: 'Ext.data.writer.Writer',
25356     alternateClassName: 'Ext.data.JsonWriter',
25357     alias: 'writer.json',
25358     
25359     
25360     root: undefined,
25361     
25362     
25363     encode: false,
25364     
25365     
25366     allowSingle: true,
25367     
25368     
25369     writeRecords: function(request, data) {
25370         var root = this.root;
25371         
25372         if (this.allowSingle && data.length == 1) {
25373             
25374             data = data[0];
25375         }
25376         
25377         if (this.encode) {
25378             if (root) {
25379                 
25380                 request.params[root] = Ext.encode(data);
25381             } else {
25382                 Ext.Error.raise('Must specify a root when using encode');
25383             }
25384         } else {
25385             
25386             request.jsonData = request.jsonData || {};
25387             if (root) {
25388                 request.jsonData[root] = data;
25389             } else {
25390                 request.jsonData = data;
25391             }
25392         }
25393         return request;
25394     }
25395 });
25396
25397
25398 Ext.define('Ext.data.proxy.Proxy', {
25399     alias: 'proxy.proxy',
25400     alternateClassName: ['Ext.data.DataProxy', 'Ext.data.Proxy'],
25401     requires: [
25402         'Ext.data.reader.Json',
25403         'Ext.data.writer.Json'
25404     ],
25405     uses: [
25406         'Ext.data.Batch', 
25407         'Ext.data.Operation', 
25408         'Ext.data.Model'
25409     ],
25410     mixins: {
25411         observable: 'Ext.util.Observable'
25412     },
25413     
25414     
25415     batchOrder: 'create,update,destroy',
25416     
25417     
25418     batchActions: true,
25419     
25420     
25421     defaultReaderType: 'json',
25422     
25423     
25424     defaultWriterType: 'json',
25425     
25426     
25427     
25428     isProxy: true,
25429     
25430     constructor: function(config) {
25431         config = config || {};
25432         
25433         if (config.model === undefined) {
25434             delete config.model;
25435         }
25436
25437         this.mixins.observable.constructor.call(this, config);
25438         
25439         if (this.model !== undefined && !(this.model instanceof Ext.data.Model)) {
25440             this.setModel(this.model);
25441         }
25442     },
25443     
25444     
25445     setModel: function(model, setOnStore) {
25446         this.model = Ext.ModelManager.getModel(model);
25447         
25448         var reader = this.reader,
25449             writer = this.writer;
25450         
25451         this.setReader(reader);
25452         this.setWriter(writer);
25453         
25454         if (setOnStore && this.store) {
25455             this.store.setModel(this.model);
25456         }
25457     },
25458     
25459     
25460     getModel: function() {
25461         return this.model;
25462     },
25463     
25464     
25465     setReader: function(reader) {
25466         var me = this;
25467         
25468         if (reader === undefined || typeof reader == 'string') {
25469             reader = {
25470                 type: reader
25471             };
25472         }
25473
25474         if (reader.isReader) {
25475             reader.setModel(me.model);
25476         } else {
25477             Ext.applyIf(reader, {
25478                 proxy: me,
25479                 model: me.model,
25480                 type : me.defaultReaderType
25481             });
25482
25483             reader = Ext.createByAlias('reader.' + reader.type, reader);
25484         }
25485         
25486         me.reader = reader;
25487         return me.reader;
25488     },
25489     
25490     
25491     getReader: function() {
25492         return this.reader;
25493     },
25494     
25495     
25496     setWriter: function(writer) {
25497         if (writer === undefined || typeof writer == 'string') {
25498             writer = {
25499                 type: writer
25500             };
25501         }
25502
25503         if (!(writer instanceof Ext.data.writer.Writer)) {
25504             Ext.applyIf(writer, {
25505                 model: this.model,
25506                 type : this.defaultWriterType
25507             });
25508
25509             writer = Ext.createByAlias('writer.' + writer.type, writer);
25510         }
25511         
25512         this.writer = writer;
25513         
25514         return this.writer;
25515     },
25516     
25517     
25518     getWriter: function() {
25519         return this.writer;
25520     },
25521     
25522     
25523     create: Ext.emptyFn,
25524     
25525     
25526     read: Ext.emptyFn,
25527     
25528     
25529     update: Ext.emptyFn,
25530     
25531     
25532     destroy: Ext.emptyFn,
25533     
25534     
25535     batch: function(operations, listeners) {
25536         var me = this,
25537             batch = Ext.create('Ext.data.Batch', {
25538                 proxy: me,
25539                 listeners: listeners || {}
25540             }),
25541             useBatch = me.batchActions, 
25542             records;
25543         
25544         Ext.each(me.batchOrder.split(','), function(action) {
25545             records = operations[action];
25546             if (records) {
25547                 if (useBatch) {
25548                     batch.add(Ext.create('Ext.data.Operation', {
25549                         action: action,
25550                         records: records
25551                     }));
25552                 } else {
25553                     Ext.each(records, function(record){
25554                         batch.add(Ext.create('Ext.data.Operation', {
25555                             action : action, 
25556                             records: [record]
25557                         }));
25558                     });
25559                 }
25560             }
25561         }, me);
25562         
25563         batch.start();
25564         return batch;
25565     }
25566 }, function() {
25567     
25568     
25569     
25570     Ext.data.DataProxy = this;
25571     
25572     
25573     
25574 });
25575
25576
25577 Ext.define('Ext.data.proxy.Server', {
25578     extend: 'Ext.data.proxy.Proxy',
25579     alias : 'proxy.server',
25580     alternateClassName: 'Ext.data.ServerProxy',
25581     uses  : ['Ext.data.Request'],
25582     
25583     
25584     
25585     
25586     
25587     
25588     
25589     
25590     pageParam: 'page',
25591     
25592     
25593     startParam: 'start',
25594
25595     
25596     limitParam: 'limit',
25597     
25598     
25599     groupParam: 'group',
25600     
25601     
25602     sortParam: 'sort',
25603     
25604     
25605     filterParam: 'filter',
25606     
25607     
25608     directionParam: 'dir',
25609     
25610     
25611     simpleSortMode: false,
25612     
25613     
25614     noCache : true,
25615     
25616     
25617     cacheString: "_dc",
25618     
25619     
25620     timeout : 30000,
25621     
25622     
25623     
25624     
25625     constructor: function(config) {
25626         var me = this;
25627         
25628         config = config || {};
25629         this.addEvents(
25630             
25631             'exception'
25632         );
25633         me.callParent([config]);
25634         
25635         
25636         me.extraParams = config.extraParams || {};
25637         
25638         me.api = config.api || {};
25639         
25640         
25641         me.nocache = me.noCache;
25642     },
25643     
25644     
25645     create: function() {
25646         return this.doRequest.apply(this, arguments);
25647     },
25648     
25649     read: function() {
25650         return this.doRequest.apply(this, arguments);
25651     },
25652     
25653     update: function() {
25654         return this.doRequest.apply(this, arguments);
25655     },
25656     
25657     destroy: function() {
25658         return this.doRequest.apply(this, arguments);
25659     },
25660     
25661     
25662     buildRequest: function(operation) {
25663         var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
25664             request;
25665         
25666         
25667         params = Ext.applyIf(params, this.getParams(params, operation));
25668         
25669         if (operation.id && !params.id) {
25670             params.id = operation.id;
25671         }
25672         
25673         request = Ext.create('Ext.data.Request', {
25674             params   : params,
25675             action   : operation.action,
25676             records  : operation.records,
25677             operation: operation,
25678             url      : operation.url
25679         });
25680         
25681         request.url = this.buildUrl(request);
25682         
25683         
25684         operation.request = request;
25685         
25686         return request;
25687     },
25688     
25689     
25690     processResponse: function(success, operation, request, response, callback, scope){
25691         var me = this,
25692             reader,
25693             result,
25694             records,
25695             length,
25696             mc,
25697             record,
25698             i;
25699             
25700         if (success === true) {
25701             reader = me.getReader();
25702             result = reader.read(me.extractResponseData(response));
25703             records = result.records;
25704             length = records.length;
25705             
25706             if (result.success !== false) {
25707                 mc = Ext.create('Ext.util.MixedCollection', true, function(r) {return r.getId();});
25708                 mc.addAll(operation.records);
25709                 for (i = 0; i < length; i++) {
25710                     record = mc.get(records[i].getId());
25711                     
25712                     if (record) {
25713                         record.beginEdit();
25714                         record.set(record.data);
25715                         record.endEdit(true);
25716                     }
25717                 }
25718                 
25719                 
25720                 Ext.apply(operation, {
25721                     response: response,
25722                     resultSet: result
25723                 });
25724                 
25725                 operation.setCompleted();
25726                 operation.setSuccessful();
25727             } else {
25728                 operation.setException(result.message);
25729                 me.fireEvent('exception', this, response, operation);
25730             }
25731         } else {
25732             me.setException(operation, response);
25733             me.fireEvent('exception', this, response, operation);              
25734         }
25735             
25736         
25737         if (typeof callback == 'function') {
25738             callback.call(scope || me, operation);
25739         }
25740             
25741         me.afterRequest(request, success);
25742     },
25743     
25744     
25745     setException: function(operation, response){
25746         operation.setException({
25747             status: response.status,
25748             statusText: response.statusText
25749         });     
25750     },
25751     
25752     
25753     extractResponseData: function(response){
25754         return response; 
25755     },
25756     
25757     
25758     applyEncoding: function(value){
25759         return Ext.encode(value);
25760     },
25761     
25762     
25763     encodeSorters: function(sorters) {
25764         var min = [],
25765             length = sorters.length,
25766             i = 0;
25767         
25768         for (; i < length; i++) {
25769             min[i] = {
25770                 property : sorters[i].property,
25771                 direction: sorters[i].direction
25772             };
25773         }
25774         return this.applyEncoding(min);
25775         
25776     },
25777     
25778     
25779     encodeFilters: function(filters) {
25780         var min = [],
25781             length = filters.length,
25782             i = 0;
25783         
25784         for (; i < length; i++) {
25785             min[i] = {
25786                 property: filters[i].property,
25787                 value   : filters[i].value
25788             };
25789         }
25790         return this.applyEncoding(min);
25791     },
25792     
25793     
25794     getParams: function(params, operation) {
25795         params = params || {};
25796         
25797         var me             = this,
25798             isDef          = Ext.isDefined,
25799             groupers       = operation.groupers,
25800             sorters        = operation.sorters,
25801             filters        = operation.filters,
25802             page           = operation.page,
25803             start          = operation.start,
25804             limit          = operation.limit,
25805             
25806             simpleSortMode = me.simpleSortMode,
25807             
25808             pageParam      = me.pageParam,
25809             startParam     = me.startParam,
25810             limitParam     = me.limitParam,
25811             groupParam     = me.groupParam,
25812             sortParam      = me.sortParam,
25813             filterParam    = me.filterParam,
25814             directionParam       = me.directionParam;
25815         
25816         if (pageParam && isDef(page)) {
25817             params[pageParam] = page;
25818         }
25819         
25820         if (startParam && isDef(start)) {
25821             params[startParam] = start;
25822         }
25823         
25824         if (limitParam && isDef(limit)) {
25825             params[limitParam] = limit;
25826         }
25827         
25828         if (groupParam && groupers && groupers.length > 0) {
25829             
25830             params[groupParam] = me.encodeSorters(groupers);
25831         }
25832         
25833         if (sortParam && sorters && sorters.length > 0) {
25834             if (simpleSortMode) {
25835                 params[sortParam] = sorters[0].property;
25836                 params[directionParam] = sorters[0].direction;
25837             } else {
25838                 params[sortParam] = me.encodeSorters(sorters);
25839             }
25840             
25841         }
25842         
25843         if (filterParam && filters && filters.length > 0) {
25844             params[filterParam] = me.encodeFilters(filters);
25845         }
25846         
25847         return params;
25848     },
25849     
25850     
25851     buildUrl: function(request) {
25852         var me = this,
25853             url = me.getUrl(request);
25854         
25855         if (!url) {
25856             Ext.Error.raise("You are using a ServerProxy but have not supplied it with a url.");
25857         }
25858         
25859         if (me.noCache) {
25860             url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.cacheString, Ext.Date.now()));
25861         }
25862         
25863         return url;
25864     },
25865     
25866     
25867     getUrl: function(request){
25868         return request.url || this.api[request.action] || this.url;
25869     },
25870     
25871     
25872     doRequest: function(operation, callback, scope) {
25873         Ext.Error.raise("The doRequest function has not been implemented on your Ext.data.proxy.Server subclass. See src/data/ServerProxy.js for details");
25874     },
25875     
25876     
25877     afterRequest: Ext.emptyFn,
25878     
25879     onDestroy: function() {
25880         Ext.destroy(this.reader, this.writer);
25881     }
25882 });
25883
25884
25885 Ext.define('Ext.data.proxy.Ajax', {
25886     requires: ['Ext.util.MixedCollection', 'Ext.Ajax'],
25887     extend: 'Ext.data.proxy.Server',
25888     alias: 'proxy.ajax',
25889     alternateClassName: ['Ext.data.HttpProxy', 'Ext.data.AjaxProxy'],
25890     
25891     
25892     actionMethods: {
25893         create : 'POST',
25894         read   : 'GET',
25895         update : 'POST',
25896         destroy: 'POST'
25897     },
25898     
25899     
25900     
25901     
25902     doRequest: function(operation, callback, scope) {
25903         var writer  = this.getWriter(),
25904             request = this.buildRequest(operation, callback, scope);
25905             
25906         if (operation.allowWrite()) {
25907             request = writer.write(request);
25908         }
25909         
25910         Ext.apply(request, {
25911             headers       : this.headers,
25912             timeout       : this.timeout,
25913             scope         : this,
25914             callback      : this.createRequestCallback(request, operation, callback, scope),
25915             method        : this.getMethod(request),
25916             disableCaching: false 
25917         });
25918         
25919         Ext.Ajax.request(request);
25920         
25921         return request;
25922     },
25923     
25924     
25925     getMethod: function(request) {
25926         return this.actionMethods[request.action];
25927     },
25928     
25929     
25930     createRequestCallback: function(request, operation, callback, scope) {
25931         var me = this;
25932         
25933         return function(options, success, response) {
25934             me.processResponse(success, operation, request, response, callback, scope);
25935         };
25936     }
25937 }, function() {
25938     
25939     Ext.data.HttpProxy = this;
25940 });
25941
25942
25943 Ext.define('Ext.data.Model', {
25944     alternateClassName: 'Ext.data.Record',
25945     
25946     mixins: {
25947         observable: 'Ext.util.Observable'
25948     },
25949
25950     requires: [
25951         'Ext.ModelManager',
25952         'Ext.data.Field',
25953         'Ext.data.Errors',
25954         'Ext.data.Operation',
25955         'Ext.data.validations',
25956         'Ext.data.proxy.Ajax',
25957         'Ext.util.MixedCollection'
25958     ],
25959
25960     onClassExtended: function(cls, data) {
25961         var onBeforeClassCreated = data.onBeforeClassCreated;
25962
25963         data.onBeforeClassCreated = function(cls, data) {
25964             var me = this,
25965                 name = Ext.getClassName(cls),
25966                 prototype = cls.prototype,
25967                 superCls = cls.prototype.superclass,
25968
25969                 validations = data.validations || [],
25970                 fields = data.fields || [],
25971                 associations = data.associations || [],
25972                 belongsTo = data.belongsTo,
25973                 hasMany = data.hasMany,
25974
25975                 fieldsMixedCollection = new Ext.util.MixedCollection(false, function(field) {
25976                     return field.name;
25977                 }),
25978
25979                 associationsMixedCollection = new Ext.util.MixedCollection(false, function(association) {
25980                     return association.name;
25981                 }),
25982
25983                 superValidations = superCls.validations,
25984                 superFields = superCls.fields,
25985                 superAssociations = superCls.associations,
25986
25987                 association, i, ln,
25988                 dependencies = [];
25989
25990             
25991             cls.modelName = name;
25992             prototype.modelName = name;
25993
25994             
25995             if (superValidations) {
25996                 validations = superValidations.concat(validations);
25997             }
25998
25999             data.validations = validations;
26000
26001             
26002             if (superFields) {
26003                 fields = superFields.items.concat(fields);
26004             }
26005
26006             for (i = 0, ln = fields.length; i < ln; ++i) {
26007                 fieldsMixedCollection.add(new Ext.data.Field(fields[i]));
26008             }
26009
26010             data.fields = fieldsMixedCollection;
26011
26012             
26013             
26014             if (belongsTo) {
26015                 belongsTo = Ext.Array.from(belongsTo);
26016
26017                 for (i = 0, ln = belongsTo.length; i < ln; ++i) {
26018                     association = belongsTo[i];
26019
26020                     if (!Ext.isObject(association)) {
26021                         association = {model: association};
26022                     }
26023
26024                     association.type = 'belongsTo';
26025                     associations.push(association);
26026                 }
26027
26028                 delete data.belongsTo;
26029             }
26030
26031             if (hasMany) {
26032                 hasMany = Ext.Array.from(hasMany);
26033                 for (i = 0, ln = hasMany.length; i < ln; ++i) {
26034                     association = hasMany[i];
26035
26036                     if (!Ext.isObject(association)) {
26037                         association = {model: association};
26038                     }
26039
26040                     association.type = 'hasMany';
26041                     associations.push(association);
26042                 }
26043
26044                 delete data.hasMany;
26045             }
26046
26047             if (superAssociations) {
26048                 associations = superAssociations.items.concat(associations);
26049             }
26050
26051             for (i = 0, ln = associations.length; i < ln; ++i) {
26052                 dependencies.push('association.' + associations[i].type.toLowerCase());
26053             }
26054
26055             if (data.proxy) {
26056                 if (typeof data.proxy === 'string') {
26057                     dependencies.push('proxy.' + data.proxy);
26058                 }
26059                 else if (typeof data.proxy.type === 'string') {
26060                     dependencies.push('proxy.' + data.proxy.type);
26061                 }
26062             }
26063
26064             Ext.require(dependencies, function() {
26065                 Ext.ModelManager.registerType(name, cls);
26066
26067                 for (i = 0, ln = associations.length; i < ln; ++i) {
26068                     association = associations[i];
26069
26070                     Ext.apply(association, {
26071                         ownerModel: name,
26072                         associatedModel: association.model
26073                     });
26074
26075                     if (Ext.ModelManager.getModel(association.model) === undefined) {
26076                         Ext.ModelManager.registerDeferredAssociation(association);
26077                     } else {
26078                         associationsMixedCollection.add(Ext.data.Association.create(association));
26079                     }
26080                 }
26081
26082                 data.associations = associationsMixedCollection;
26083
26084                 onBeforeClassCreated.call(me, cls, data);
26085
26086                 cls.setProxy(cls.prototype.proxy || cls.prototype.defaultProxyType);
26087
26088                 
26089                 Ext.ModelManager.onModelDefined(cls);
26090             });
26091         }
26092     },
26093
26094     inheritableStatics: {
26095         
26096         setProxy: function(proxy) {
26097             
26098             if (!proxy.isProxy) {
26099                 if (typeof proxy == "string") {
26100                     proxy = {
26101                         type: proxy
26102                     };
26103                 }
26104                 proxy = Ext.createByAlias("proxy." + proxy.type, proxy);
26105             }
26106             proxy.setModel(this);
26107             this.proxy = this.prototype.proxy = proxy;
26108
26109             return proxy;
26110         },
26111
26112         
26113         getProxy: function() {
26114             return this.proxy;
26115         },
26116
26117         
26118         load: function(id, config) {
26119             config = Ext.apply({}, config);
26120             config = Ext.applyIf(config, {
26121                 action: 'read',
26122                 id    : id
26123             });
26124
26125             var operation  = Ext.create('Ext.data.Operation', config),
26126                 scope      = config.scope || this,
26127                 record     = null,
26128                 callback;
26129
26130             callback = function(operation) {
26131                 if (operation.wasSuccessful()) {
26132                     record = operation.getRecords()[0];
26133                     Ext.callback(config.success, scope, [record, operation]);
26134                 } else {
26135                     Ext.callback(config.failure, scope, [record, operation]);
26136                 }
26137                 Ext.callback(config.callback, scope, [record, operation]);
26138             };
26139
26140             this.proxy.read(operation, callback, this);
26141         }
26142     },
26143
26144     statics: {
26145         PREFIX : 'ext-record',
26146         AUTO_ID: 1,
26147         EDIT   : 'edit',
26148         REJECT : 'reject',
26149         COMMIT : 'commit',
26150
26151         
26152         id: function(rec) {
26153             var id = [this.PREFIX, '-', this.AUTO_ID++].join('');
26154             rec.phantom = true;
26155             rec.internalId = id;
26156             return id;
26157         }
26158     },
26159     
26160     
26161     editing : false,
26162
26163     
26164     dirty : false,
26165
26166     
26167     persistanceProperty: 'data',
26168
26169     evented: false,
26170     isModel: true,
26171
26172     
26173     phantom : false,
26174
26175     
26176     idProperty: 'id',
26177
26178     
26179     defaultProxyType: 'ajax',
26180
26181     
26182
26183     constructor: function(data, id) {
26184         data = data || {};
26185         
26186         var me = this,
26187             fields,
26188             length,
26189             field,
26190             name,
26191             i,
26192             isArray = Ext.isArray(data),
26193             newData = isArray ? {} : null; 
26194
26195         
26196         me.internalId = (id || id === 0) ? id : Ext.data.Model.id(me);
26197
26198         Ext.applyIf(me, {
26199             data: {}    
26200         });
26201         
26202         
26203         me.modified = {};
26204
26205         me[me.persistanceProperty] = {};
26206
26207         me.mixins.observable.constructor.call(me);
26208
26209         
26210         fields = me.fields.items;
26211         length = fields.length;
26212
26213         for (i = 0; i < length; i++) {
26214             field = fields[i];
26215             name  = field.name;
26216
26217             if (isArray){ 
26218                 
26219                 
26220                 newData[name] = data[i];
26221             }
26222             else if (data[name] === undefined) {
26223                 data[name] = field.defaultValue;
26224             }
26225         }
26226
26227         me.set(newData || data);
26228         
26229         me.dirty = false;
26230         me.modified = {};
26231
26232         if (me.getId()) {
26233             me.phantom = false;
26234         }
26235
26236         if (typeof me.init == 'function') {
26237             me.init();
26238         }
26239
26240         me.id = me.modelName + '-' + me.internalId;
26241
26242         Ext.ModelManager.register(me);
26243     },
26244     
26245     
26246     get: function(field) {
26247         return this[this.persistanceProperty][field];
26248     },
26249     
26250     
26251     set: function(fieldName, value) {
26252         var me = this,
26253             fields = me.fields,
26254             modified = me.modified,
26255             convertFields = [],
26256             field, key, i, currentValue;
26257
26258         
26259         if (arguments.length == 1 && Ext.isObject(fieldName)) {
26260             for (key in fieldName) {
26261                 if (fieldName.hasOwnProperty(key)) {
26262                 
26263                     
26264                     
26265                     field = fields.get(key);
26266                     if (field && field.convert !== field.type.convert) {
26267                         convertFields.push(key);
26268                         continue;
26269                     }
26270                     
26271                     me.set(key, fieldName[key]);
26272                 }
26273             }
26274
26275             for (i = 0; i < convertFields.length; i++) {
26276                 field = convertFields[i];
26277                 me.set(field, fieldName[field]);
26278             }
26279
26280         } else {
26281             if (fields) {
26282                 field = fields.get(fieldName);
26283
26284                 if (field && field.convert) {
26285                     value = field.convert(value, me);
26286                 }
26287             }
26288             currentValue = me.get(fieldName);
26289             me[me.persistanceProperty][fieldName] = value;
26290             
26291             if (field && field.persist && !me.isEqual(currentValue, value)) {
26292                 me.dirty = true;
26293                 me.modified[fieldName] = currentValue;
26294             }
26295
26296             if (!me.editing) {
26297                 me.afterEdit();
26298             }
26299         }
26300     },
26301     
26302     
26303     isEqual: function(a, b){
26304         if (Ext.isDate(a) && Ext.isDate(b)) {
26305             return a.getTime() === b.getTime();
26306         }
26307         return a === b;
26308     },
26309     
26310     
26311     beginEdit : function(){
26312         var me = this;
26313         if (!me.editing) {
26314             me.editing = true;
26315             me.dirtySave = me.dirty;
26316             me.dataSave = Ext.apply({}, me[me.persistanceProperty]);
26317             me.modifiedSave = Ext.apply({}, me.modified);
26318         }
26319     },
26320     
26321     
26322     cancelEdit : function(){
26323         var me = this;
26324         if (me.editing) {
26325             me.editing = false;
26326             
26327             me.modified = me.modifiedSave;
26328             me[me.persistanceProperty] = me.dataSave;
26329             me.dirty = me.dirtySave;
26330             delete me.modifiedSave;
26331             delete me.dataSave;
26332             delete me.dirtySave;
26333         }
26334     },
26335     
26336     
26337     endEdit : function(silent){
26338         var me = this;
26339         if (me.editing) {
26340             me.editing = false;
26341             delete me.modifiedSave;
26342             delete me.dataSave;
26343             delete me.dirtySave;
26344             if (silent !== true && me.dirty) {
26345                 me.afterEdit();
26346             }
26347         }
26348     },
26349     
26350     
26351     getChanges : function(){
26352         var modified = this.modified,
26353             changes  = {},
26354             field;
26355
26356         for (field in modified) {
26357             if (modified.hasOwnProperty(field)){
26358                 changes[field] = this.get(field);
26359             }
26360         }
26361
26362         return changes;
26363     },
26364     
26365     
26366     isModified : function(fieldName) {
26367         return this.modified.hasOwnProperty(fieldName);
26368     },
26369     
26370     
26371     setDirty : function() {
26372         var me = this,
26373             name;
26374         
26375         me.dirty = true;
26376
26377         me.fields.each(function(field) {
26378             if (field.persist) {
26379                 name = field.name;
26380                 me.modified[name] = me.get(name);
26381             }
26382         }, me);
26383     },
26384
26385     markDirty : function() {
26386         if (Ext.isDefined(Ext.global.console)) {
26387             Ext.global.console.warn('Ext.data.Model: markDirty has been deprecated. Use setDirty instead.');
26388         }
26389         return this.setDirty.apply(this, arguments);
26390     },
26391     
26392     
26393     reject : function(silent) {
26394         var me = this,
26395             modified = me.modified,
26396             field;
26397
26398         for (field in modified) {
26399             if (modified.hasOwnProperty(field)) {
26400                 if (typeof modified[field] != "function") {
26401                     me[me.persistanceProperty][field] = modified[field];
26402                 }
26403             }
26404         }
26405
26406         me.dirty = false;
26407         me.editing = false;
26408         me.modified = {};
26409
26410         if (silent !== true) {
26411             me.afterReject();
26412         }
26413     },
26414
26415     
26416     commit : function(silent) {
26417         var me = this;
26418         
26419         me.dirty = false;
26420         me.editing = false;
26421
26422         me.modified = {};
26423
26424         if (silent !== true) {
26425             me.afterCommit();
26426         }
26427     },
26428
26429     
26430     copy : function(newId) {
26431         var me = this;
26432         
26433         return new me.self(Ext.apply({}, me[me.persistanceProperty]), newId || me.internalId);
26434     },
26435
26436     
26437     setProxy: function(proxy) {
26438         
26439         if (!proxy.isProxy) {
26440             if (typeof proxy === "string") {
26441                 proxy = {
26442                     type: proxy
26443                 };
26444             }
26445             proxy = Ext.createByAlias("proxy." + proxy.type, proxy);
26446         }
26447         proxy.setModel(this.self);
26448         this.proxy = proxy;
26449
26450         return proxy;
26451     },
26452
26453     
26454     getProxy: function() {
26455         return this.proxy;
26456     },
26457
26458     
26459     validate: function() {
26460         var errors      = Ext.create('Ext.data.Errors'),
26461             validations = this.validations,
26462             validators  = Ext.data.validations,
26463             length, validation, field, valid, type, i;
26464
26465         if (validations) {
26466             length = validations.length;
26467
26468             for (i = 0; i < length; i++) {
26469                 validation = validations[i];
26470                 field = validation.field || validation.name;
26471                 type  = validation.type;
26472                 valid = validators[type](validation, this.get(field));
26473
26474                 if (!valid) {
26475                     errors.add({
26476                         field  : field,
26477                         message: validation.message || validators[type + 'Message']
26478                     });
26479                 }
26480             }
26481         }
26482
26483         return errors;
26484     },
26485
26486     
26487     isValid: function(){
26488         return this.validate().isValid();
26489     },
26490
26491     
26492     save: function(options) {
26493         options = Ext.apply({}, options);
26494
26495         var me     = this,
26496             action = me.phantom ? 'create' : 'update',
26497             record = null,
26498             scope  = options.scope || me,
26499             operation,
26500             callback;
26501
26502         Ext.apply(options, {
26503             records: [me],
26504             action : action
26505         });
26506
26507         operation = Ext.create('Ext.data.Operation', options);
26508
26509         callback = function(operation) {
26510             if (operation.wasSuccessful()) {
26511                 record = operation.getRecords()[0];
26512                 
26513                 
26514                 me.set(record.data);
26515                 record.dirty = false;
26516
26517                 Ext.callback(options.success, scope, [record, operation]);
26518             } else {
26519                 Ext.callback(options.failure, scope, [record, operation]);
26520             }
26521
26522             Ext.callback(options.callback, scope, [record, operation]);
26523         };
26524
26525         me.getProxy()[action](operation, callback, me);
26526
26527         return me;
26528     },
26529
26530     
26531     destroy: function(options){
26532         options = Ext.apply({}, options);
26533
26534         var me     = this,
26535             record = null,
26536             scope  = options.scope || me,
26537             operation,
26538             callback;
26539
26540         Ext.apply(options, {
26541             records: [me],
26542             action : 'destroy'
26543         });
26544
26545         operation = Ext.create('Ext.data.Operation', options);
26546         callback = function(operation) {
26547             if (operation.wasSuccessful()) {
26548                 Ext.callback(options.success, scope, [record, operation]);
26549             } else {
26550                 Ext.callback(options.failure, scope, [record, operation]);
26551             }
26552             Ext.callback(options.callback, scope, [record, operation]);
26553         };
26554
26555         me.getProxy().destroy(operation, callback, me);
26556         return me;
26557     },
26558
26559     
26560     getId: function() {
26561         return this.get(this.idProperty);
26562     },
26563
26564     
26565     setId: function(id) {
26566         this.set(this.idProperty, id);
26567     },
26568
26569     
26570     join : function(store) {
26571         
26572         this.store = store;
26573     },
26574
26575     
26576     unjoin: function() {
26577         delete this.store;
26578     },
26579
26580     
26581     afterEdit : function() {
26582         this.callStore('afterEdit');
26583     },
26584
26585     
26586     afterReject : function() {
26587         this.callStore("afterReject");
26588     },
26589
26590     
26591     afterCommit: function() {
26592         this.callStore('afterCommit');
26593     },
26594
26595     
26596     callStore: function(fn) {
26597         var store = this.store;
26598
26599         if (store !== undefined && typeof store[fn] == "function") {
26600             store[fn](this);
26601         }
26602     },
26603
26604     
26605     getAssociatedData: function(){
26606         return this.prepareAssociatedData(this, [], null);
26607     },
26608
26609     
26610     prepareAssociatedData: function(record, ids, associationType) {
26611         
26612         var associations     = record.associations.items,
26613             associationCount = associations.length,
26614             associationData  = {},
26615             associatedStore, associatedName, associatedRecords, associatedRecord,
26616             associatedRecordCount, association, id, i, j, type, allow;
26617
26618         for (i = 0; i < associationCount; i++) {
26619             association = associations[i];
26620             type = association.type;
26621             allow = true;
26622             if (associationType) {
26623                 allow = type == associationType;
26624             }
26625             if (allow && type == 'hasMany') {
26626
26627                 
26628                 associatedStore = record[association.storeName];
26629
26630                 
26631                 associationData[association.name] = [];
26632
26633                 
26634                 if (associatedStore && associatedStore.data.length > 0) {
26635                     associatedRecords = associatedStore.data.items;
26636                     associatedRecordCount = associatedRecords.length;
26637
26638                     
26639                     for (j = 0; j < associatedRecordCount; j++) {
26640                         associatedRecord = associatedRecords[j];
26641                         
26642                         id = associatedRecord.id;
26643
26644                         
26645                         
26646                         if (Ext.Array.indexOf(ids, id) == -1) {
26647                             ids.push(id);
26648
26649                             associationData[association.name][j] = associatedRecord.data;
26650                             Ext.apply(associationData[association.name][j], this.prepareAssociatedData(associatedRecord, ids, type));
26651                         }
26652                     }
26653                 }
26654             } else if (allow && type == 'belongsTo') {
26655                 associatedRecord = record[association.instanceName];
26656                 if (associatedRecord !== undefined) {
26657                     id = associatedRecord.id;
26658                     if (Ext.Array.indexOf(ids, id) == -1) {
26659                         ids.push(id);
26660                         associationData[association.name] = associatedRecord.data;
26661                         Ext.apply(associationData[association.name], this.prepareAssociatedData(associatedRecord, ids, type));
26662                     }
26663                 }
26664             }
26665         }
26666
26667         return associationData;
26668     }
26669 });
26670
26671
26672
26673 Ext.define('Ext.Component', {
26674
26675     
26676
26677     alias: ['widget.component', 'widget.box'],
26678
26679     extend: 'Ext.AbstractComponent',
26680
26681     requires: [
26682         'Ext.util.DelayedTask'
26683     ],
26684
26685     uses: [
26686         'Ext.Layer',
26687         'Ext.resizer.Resizer',
26688         'Ext.util.ComponentDragger'
26689     ],
26690
26691     mixins: {
26692         floating: 'Ext.util.Floating'
26693     },
26694
26695     statics: {
26696         
26697         DIRECTION_TOP: 'top',
26698         DIRECTION_RIGHT: 'right',
26699         DIRECTION_BOTTOM: 'bottom',
26700         DIRECTION_LEFT: 'left'
26701     },
26702
26703     
26704
26705     
26706
26707     
26708     resizeHandles: 'all',
26709
26710     
26711
26712     
26713     floating: false,
26714
26715     
26716     toFrontOnShow: true,
26717
26718     
26719
26720      
26721
26722     
26723
26724     
26725
26726     hideMode: 'display',
26727     
26728     hideParent: false,
26729
26730     ariaRole: 'presentation',
26731
26732     bubbleEvents: [],
26733
26734     actionMode: 'el',
26735     monPropRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
26736
26737     
26738     
26739     
26740     
26741     
26742     
26743     constructor: function(config) {
26744         config = config || {};
26745         if (config.initialConfig) {
26746
26747             
26748             if (config.isAction) {
26749                 this.baseAction = config;
26750             }
26751             config = config.initialConfig;
26752             
26753         }
26754         else if (config.tagName || config.dom || Ext.isString(config)) {
26755             
26756             config = {
26757                 applyTo: config,
26758                 id: config.id || config
26759             };
26760         }
26761
26762         this.callParent([config]);
26763
26764         
26765         
26766         if (this.baseAction){
26767             this.baseAction.addComponent(this);
26768         }
26769     },
26770
26771     initComponent: function() {
26772         var me = this;
26773
26774         if (me.listeners) {
26775             me.on(me.listeners);
26776             delete me.listeners;
26777         }
26778         me.enableBubble(me.bubbleEvents);
26779         me.mons = [];
26780     },
26781
26782     
26783     afterRender: function() {
26784         var me = this,
26785             resizable = me.resizable;
26786
26787         if (me.floating) {
26788             me.makeFloating(me.floating);
26789         } else {
26790             me.el.setVisibilityMode(Ext.core.Element[me.hideMode.toUpperCase()]);
26791         }
26792
26793         me.setAutoScroll(me.autoScroll);
26794         me.callParent();
26795
26796         if (!(me.x && me.y) && (me.pageX || me.pageY)) {
26797             me.setPagePosition(me.pageX, me.pageY);
26798         }
26799
26800         if (resizable) {
26801             me.initResizable(resizable);
26802         }
26803
26804         if (me.draggable) {
26805             me.initDraggable();
26806         }
26807
26808         me.initAria();
26809     },
26810
26811     initAria: function() {
26812         var actionEl = this.getActionEl(),
26813             role = this.ariaRole;
26814         if (role) {
26815             actionEl.dom.setAttribute('role', role);
26816         }
26817     },
26818
26819     
26820     setAutoScroll : function(scroll){
26821         var me = this,
26822             targetEl;
26823         scroll = !!scroll;
26824         if (me.rendered) {
26825             targetEl = me.getTargetEl();
26826             targetEl.setStyle('overflow', scroll ? 'auto' : '');
26827             if (scroll && (Ext.isIE6 || Ext.isIE7)) {
26828                 
26829                 
26830                 targetEl.position();
26831             }
26832         }
26833         me.autoScroll = scroll;
26834         return me;
26835     },
26836
26837     
26838     makeFloating : function(cfg){
26839         this.mixins.floating.constructor.call(this, cfg);
26840     },
26841
26842     initResizable: function(resizable) {
26843         resizable = Ext.apply({
26844             target: this,
26845             dynamic: false,
26846             constrainTo: this.constrainTo,
26847             handles: this.resizeHandles
26848         }, resizable);
26849         resizable.target = this;
26850         this.resizer = Ext.create('Ext.resizer.Resizer', resizable);
26851     },
26852
26853     getDragEl: function() {
26854         return this.el;
26855     },
26856
26857     initDraggable: function() {
26858         var me = this,
26859             ddConfig = Ext.applyIf({
26860                 el: this.getDragEl(),
26861                 constrainTo: me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.el.dom.parentNode)
26862             }, this.draggable);
26863
26864         
26865         if (me.constrain || me.constrainDelegate) {
26866             ddConfig.constrain = me.constrain;
26867             ddConfig.constrainDelegate = me.constrainDelegate;
26868         }
26869
26870         this.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig);
26871     },
26872
26873     
26874     setPosition: function(x, y, animate) {
26875         var me = this,
26876             el = me.el,
26877             to = {},
26878             adj, adjX, adjY, xIsNumber, yIsNumber;
26879
26880         if (Ext.isArray(x)) {
26881             animate = y;
26882             y = x[1];
26883             x = x[0];
26884         }
26885         me.x = x;
26886         me.y = y;
26887
26888         if (!me.rendered) {
26889             return me;
26890         }
26891
26892         adj = me.adjustPosition(x, y);
26893         adjX = adj.x;
26894         adjY = adj.y;
26895         xIsNumber = Ext.isNumber(adjX);
26896         yIsNumber = Ext.isNumber(adjY);
26897
26898         if (xIsNumber || yIsNumber) {
26899             if (animate) {
26900                 if (xIsNumber) {
26901                     to.left = adjX;
26902                 }
26903                 if (yIsNumber) {
26904                     to.top = adjY;
26905                 }
26906
26907                 me.stopAnimation();
26908                 me.animate(Ext.apply({
26909                     duration: 1000,
26910                     listeners: {
26911                         afteranimate: Ext.Function.bind(me.afterSetPosition, me, [adjX, adjY])
26912                     },
26913                     to: to
26914                 }, animate));
26915             }
26916             else {
26917                 if (!xIsNumber) {
26918                     el.setTop(adjY);
26919                 }
26920                 else if (!yIsNumber) {
26921                     el.setLeft(adjX);
26922                 }
26923                 else {
26924                     el.setLeftTop(adjX, adjY);
26925                 }
26926                 me.afterSetPosition(adjX, adjY);
26927             }
26928         }
26929         return me;
26930     },
26931
26932     
26933     afterSetPosition: function(ax, ay) {
26934         this.onPosition(ax, ay);
26935         this.fireEvent('move', this, ax, ay);
26936     },
26937
26938     showAt: function(x, y, animate) {
26939         
26940         if (this.floating) {
26941             this.setPosition(x, y, animate);
26942         } else {
26943             this.setPagePosition(x, y, animate);
26944         }
26945         this.show();
26946     },
26947
26948     
26949     setPagePosition: function(x, y, animate) {
26950         var me = this,
26951             p;
26952
26953         if (Ext.isArray(x)) {
26954             y = x[1];
26955             x = x[0];
26956         }
26957         me.pageX = x;
26958         me.pageY = y;
26959         if (me.floating && me.floatParent) {
26960             
26961             p = me.floatParent.getTargetEl().getViewRegion();
26962             if (Ext.isNumber(x) && Ext.isNumber(p.left)) {
26963                 x -= p.left;
26964             }
26965             if (Ext.isNumber(y) && Ext.isNumber(p.top)) {
26966                 y -= p.top;
26967             }
26968             me.setPosition(x, y, animate);
26969         }
26970         else {
26971             p = me.el.translatePoints(x, y);
26972             me.setPosition(p.left, p.top, animate);
26973         }
26974         return me;
26975     },
26976
26977     
26978     getBox : function(local){
26979         var pos = this.getPosition(local);
26980         var s = this.getSize();
26981         s.x = pos[0];
26982         s.y = pos[1];
26983         return s;
26984     },
26985
26986     
26987     updateBox : function(box){
26988         this.setSize(box.width, box.height);
26989         this.setPagePosition(box.x, box.y);
26990         return this;
26991     },
26992
26993     
26994     getOuterSize: function() {
26995         var el = this.el;
26996         return {
26997             width: el.getWidth() + el.getMargin('lr'),
26998             height: el.getHeight() + el.getMargin('tb')
26999         };
27000     },
27001
27002     
27003     adjustSize: function(w, h) {
27004         if (this.autoWidth) {
27005             w = 'auto';
27006         }
27007
27008         if (this.autoHeight) {
27009             h = 'auto';
27010         }
27011
27012         return {
27013             width: w,
27014             height: h
27015         };
27016     },
27017
27018     
27019     adjustPosition: function(x, y) {
27020
27021         
27022         if (this.floating && this.floatParent) {
27023             var o = this.floatParent.getTargetEl().getViewRegion();
27024             x += o.left;
27025             y += o.top;
27026         }
27027
27028         return {
27029             x: x,
27030             y: y
27031         };
27032     },
27033
27034     
27035     getPosition: function(local) {
27036         var el = this.el,
27037             xy;
27038
27039         if (local === true) {
27040             return [el.getLeft(true), el.getTop(true)];
27041         }
27042         xy = this.xy || el.getXY();
27043
27044         
27045         if (this.floating && this.floatParent) {
27046             var o = this.floatParent.getTargetEl().getViewRegion();
27047             xy[0] -= o.left;
27048             xy[1] -= o.top;
27049         }
27050         return xy;
27051     },
27052
27053     
27054     getId: function() {
27055         return this.id || (this.id = (this.getXType() || 'ext-comp') + '-' + this.getAutoId());
27056     },
27057
27058     onEnable: function() {
27059         var actionEl = this.getActionEl();
27060         actionEl.dom.removeAttribute('aria-disabled');
27061         actionEl.dom.disabled = false;
27062         this.callParent();
27063     },
27064
27065     onDisable: function() {
27066         var actionEl = this.getActionEl();
27067         actionEl.dom.setAttribute('aria-disabled', true);
27068         actionEl.dom.disabled = true;
27069         this.callParent();
27070     },
27071
27072     
27073     show: function(animateTarget, cb, scope) {
27074         if (this.rendered && this.isVisible()) {
27075             if (this.toFrontOnShow && this.floating) {
27076                 this.toFront();
27077             }
27078         } else if (this.fireEvent('beforeshow', this) !== false) {
27079             this.hidden = false;
27080
27081             
27082             if (!this.rendered && (this.autoRender || this.floating)) {
27083                 this.doAutoRender();
27084             }
27085             if (this.rendered) {
27086                 this.beforeShow();
27087                 this.onShow.apply(this, arguments);
27088
27089                 
27090                 
27091                 if (this.ownerCt && !this.floating && !(this.ownerCt.suspendLayout || this.ownerCt.layout.layoutBusy)) {
27092                     this.ownerCt.doLayout();
27093                 }
27094                 this.afterShow.apply(this, arguments);
27095             }
27096         }
27097         return this;
27098     },
27099
27100     beforeShow: Ext.emptyFn,
27101
27102     
27103     onShow: function() {
27104         var me = this;
27105
27106         me.el.show();
27107         if (this.floating && this.constrain) {
27108             this.doConstrain();
27109         }
27110         me.callParent(arguments);
27111     },
27112
27113     afterShow: function(animateTarget, cb, scope) {
27114         var me = this,
27115             fromBox,
27116             toBox,
27117             ghostPanel;
27118
27119         
27120         animateTarget = animateTarget || me.animateTarget;
27121
27122         
27123         if (!me.ghost) {
27124             animateTarget = null;
27125         }
27126         
27127         if (animateTarget) {
27128             animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget);
27129             toBox = me.el.getBox();
27130             fromBox = animateTarget.getBox();
27131             fromBox.width += 'px';
27132             fromBox.height += 'px';
27133             toBox.width += 'px';
27134             toBox.height += 'px';
27135             me.el.addCls(Ext.baseCSSPrefix + 'hide-offsets');
27136             ghostPanel = me.ghost();
27137             ghostPanel.el.stopAnimation();
27138
27139             ghostPanel.el.animate({
27140                 from: fromBox,
27141                 to: toBox,
27142                 listeners: {
27143                     afteranimate: function() {
27144                         delete ghostPanel.componentLayout.lastComponentSize;
27145                         me.unghost();
27146                         me.el.removeCls(Ext.baseCSSPrefix + 'hide-offsets');
27147                         if (me.floating) {
27148                             me.toFront();
27149                         }
27150                         Ext.callback(cb, scope || me);
27151                     }
27152                 }
27153             });
27154         }
27155         else {
27156             if (me.floating) {
27157                 me.toFront();
27158             }
27159             Ext.callback(cb, scope || me);
27160         }
27161         me.fireEvent('show', me);
27162     },
27163
27164     
27165     hide: function() {
27166
27167         
27168         
27169         this.showOnParentShow = false;
27170
27171         if (!(this.rendered && !this.isVisible()) && this.fireEvent('beforehide', this) !== false) {
27172             this.hidden = true;
27173             if (this.rendered) {
27174                 this.onHide.apply(this, arguments);
27175
27176                 
27177                 
27178                 if (this.ownerCt && !this.floating && !(this.ownerCt.suspendLayout || this.ownerCt.layout.layoutBusy)) {
27179                     this.ownerCt.doLayout();
27180                 }
27181             }
27182         }
27183         return this;
27184     },
27185
27186     
27187     onHide: function(animateTarget, cb, scope) {
27188         var me = this,
27189             ghostPanel,
27190             toBox;
27191
27192         
27193         animateTarget = animateTarget || me.animateTarget;
27194
27195         
27196         if (!me.ghost) {
27197             animateTarget = null;
27198         }
27199         
27200         if (animateTarget) {
27201             animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget);
27202             ghostPanel = me.ghost();
27203             ghostPanel.el.stopAnimation();
27204             toBox = animateTarget.getBox();
27205             toBox.width += 'px';
27206             toBox.height += 'px';
27207             ghostPanel.el.animate({
27208                 to: toBox,
27209                 listeners: {
27210                     afteranimate: function() {
27211                         delete ghostPanel.componentLayout.lastComponentSize;
27212                         ghostPanel.el.hide();
27213                         me.afterHide(cb, scope);
27214                     }
27215                 }
27216             });
27217         }
27218         me.el.hide();
27219         if (!animateTarget) {
27220             me.afterHide(cb, scope);
27221         }
27222     },
27223
27224     afterHide: function(cb, scope) {
27225         Ext.callback(cb, scope || this);
27226         this.fireEvent('hide', this);
27227     },
27228
27229     
27230     onDestroy: function() {
27231         var me = this;
27232
27233         
27234         if (me.rendered) {
27235             Ext.destroy(
27236                 me.proxy,
27237                 me.resizer
27238             );
27239             
27240             if (me.actionMode == 'container' || me.removeMode == 'container') {
27241                 me.container.remove();
27242             }
27243         }
27244         me.callParent();
27245     },
27246
27247     deleteMembers: function() {
27248         var args = arguments,
27249             len = args.length,
27250             i = 0;
27251         for (; i < len; ++i) {
27252             delete this[args[i]];
27253         }
27254     },
27255
27256     
27257     focus: function(selectText, delay) {
27258         var me = this,
27259                 focusEl;
27260
27261         if (delay) {
27262             me.focusTask.delay(Ext.isNumber(delay) ? delay: 10, null, me, [selectText, false]);
27263             return me;
27264         }
27265
27266         if (me.rendered && !me.isDestroyed) {
27267             
27268             focusEl = me.getFocusEl();
27269             focusEl.focus();
27270             if (focusEl.dom && selectText === true) {
27271                 focusEl.dom.select();
27272             }
27273
27274             
27275             
27276             if (me.floating) {
27277                 me.toFront(true);
27278             }
27279         }
27280         return me;
27281     },
27282
27283     
27284     getFocusEl: function() {
27285         return this.el;
27286     },
27287
27288     
27289     blur: function() {
27290         if (this.rendered) {
27291             this.getFocusEl().blur();
27292         }
27293         return this;
27294     },
27295
27296     getEl: function() {
27297         return this.el;
27298     },
27299
27300     
27301     getResizeEl: function() {
27302         return this.el;
27303     },
27304
27305     
27306     getPositionEl: function() {
27307         return this.el;
27308     },
27309
27310     
27311     getActionEl: function() {
27312         return this.el;
27313     },
27314
27315     
27316     getVisibilityEl: function() {
27317         return this.el;
27318     },
27319
27320     
27321     onResize: Ext.emptyFn,
27322
27323     
27324     getBubbleTarget: function() {
27325         return this.ownerCt;
27326     },
27327
27328     
27329     getContentTarget: function() {
27330         return this.el;
27331     },
27332
27333     
27334     cloneConfig: function(overrides) {
27335         overrides = overrides || {};
27336         var id = overrides.id || Ext.id();
27337         var cfg = Ext.applyIf(overrides, this.initialConfig);
27338         cfg.id = id;
27339
27340         var self = Ext.getClass(this);
27341
27342         
27343         return new self(cfg);
27344     },
27345
27346     
27347     getXType: function() {
27348         return this.self.xtype;
27349     },
27350
27351     
27352     findParentBy: function(fn) {
27353         var p;
27354
27355         
27356         for (p = this.ownerCt; p && !fn(p, this); p = p.ownerCt);
27357         return p || null;
27358     },
27359
27360     
27361     findParentByType: function(xtype) {
27362         return Ext.isFunction(xtype) ?
27363             this.findParentBy(function(p) {
27364                 return p.constructor === xtype;
27365             })
27366         :
27367             this.up(xtype);
27368     },
27369
27370     
27371     bubble: function(fn, scope, args) {
27372         var p = this;
27373         while (p) {
27374             if (fn.apply(scope || p, args || [p]) === false) {
27375                 break;
27376             }
27377             p = p.ownerCt;
27378         }
27379         return this;
27380     },
27381
27382     getProxy: function() {
27383         if (!this.proxy) {
27384             this.proxy = this.el.createProxy(Ext.baseCSSPrefix + 'proxy-el', Ext.getBody(), true);
27385         }
27386         return this.proxy;
27387     }
27388
27389 }, function() {
27390
27391     
27392     this.prototype.focusTask = Ext.create('Ext.util.DelayedTask', this.prototype.focus);
27393
27394 });
27395
27396
27397 Ext.define('Ext.layout.container.Container', {
27398
27399     
27400
27401     extend: 'Ext.layout.container.AbstractContainer',
27402     alternateClassName: 'Ext.layout.ContainerLayout',
27403     
27404     
27405
27406     layoutItem: function(item, box) {
27407         box = box || {};
27408         if (item.componentLayout.initialized !== true) {
27409             this.setItemSize(item, box.width || item.width || undefined, box.height || item.height || undefined);
27410             
27411         }
27412     },
27413
27414     getLayoutTargetSize : function() {
27415         var target = this.getTarget(),
27416             ret;
27417
27418         if (target) {
27419             ret = target.getViewSize();
27420
27421             
27422             
27423             
27424             if (Ext.isIE && ret.width == 0){
27425                 ret = target.getStyleSize();
27426             }
27427
27428             ret.width -= target.getPadding('lr');
27429             ret.height -= target.getPadding('tb');
27430         }
27431         return ret;
27432     },
27433
27434     beforeLayout: function() {
27435         if (this.owner.beforeLayout(arguments) !== false) {
27436             return this.callParent(arguments);
27437         }
27438         else {
27439             return false;
27440         }
27441     },
27442
27443     afterLayout: function() {
27444         this.owner.afterLayout(arguments);
27445         this.callParent(arguments);
27446     },
27447
27448     
27449     getRenderedItems: function() {
27450         var me = this,
27451             target = me.getTarget(),
27452             items = me.getLayoutItems(),
27453             ln = items.length,
27454             renderedItems = [],
27455             i, item;
27456
27457         for (i = 0; i < ln; i++) {
27458             item = items[i];
27459             if (item.rendered && me.isValidParent(item, target, i)) {
27460                 renderedItems.push(item);
27461             }
27462         }
27463
27464         return renderedItems;
27465     },
27466
27467     
27468     getVisibleItems: function() {
27469         var target   = this.getTarget(),
27470             items = this.getLayoutItems(),
27471             ln = items.length,
27472             visibleItems = [],
27473             i, item;
27474
27475         for (i = 0; i < ln; i++) {
27476             item = items[i];
27477             if (item.rendered && this.isValidParent(item, target, i) && item.hidden !== true) {
27478                 visibleItems.push(item);
27479             }
27480         }
27481
27482         return visibleItems;
27483     }
27484 });
27485
27486
27487 Ext.define('Ext.layout.container.Auto', {
27488
27489     
27490
27491     alias: ['layout.auto', 'layout.autocontainer'],
27492
27493     extend: 'Ext.layout.container.Container',
27494
27495     
27496
27497     type: 'autocontainer',
27498
27499     fixedLayout: false,
27500
27501     bindToOwnerCtComponent: true,
27502
27503     
27504     onLayout : function(owner, target) {
27505         var me = this,
27506             items = me.getLayoutItems(),
27507             ln = items.length,
27508             i;
27509
27510         
27511         if (ln) {
27512             
27513             
27514             
27515             if (!me.clearEl) {
27516                 me.clearEl = me.getRenderTarget().createChild({
27517                     cls: Ext.baseCSSPrefix + 'clear',
27518                     role: 'presentation'
27519                 });
27520             }
27521
27522             
27523             for (i = 0; i < ln; i++) {
27524                 me.setItemSize(items[i]);
27525             }
27526         }
27527     }
27528 });
27529
27530 Ext.define('Ext.container.AbstractContainer', {
27531
27532     
27533
27534     extend: 'Ext.Component',
27535
27536     requires: [
27537         'Ext.util.MixedCollection',
27538         'Ext.layout.container.Auto',
27539         'Ext.ZIndexManager'
27540     ],
27541
27542     
27543     
27544
27545     
27546     
27547     
27548
27549     
27550     suspendLayout : false,
27551
27552     
27553     autoDestroy : true,
27554
27555      
27556     defaultType: 'panel',
27557
27558     isContainer : true,
27559
27560     baseCls: Ext.baseCSSPrefix + 'container',
27561
27562     
27563     bubbleEvents: ['add', 'remove'],
27564     
27565     
27566     initComponent : function(){
27567         var me = this;
27568         me.addEvents(
27569             
27570             'afterlayout',
27571             
27572             'beforeadd',
27573             
27574             'beforeremove',
27575             
27576             'add',
27577             
27578             'remove',
27579             
27580             'beforecardswitch',
27581             
27582             'cardswitch'
27583         );
27584
27585         
27586         me.layoutOnShow = Ext.create('Ext.util.MixedCollection');
27587         me.callParent();
27588         me.initItems();
27589     },
27590
27591     
27592     initItems : function() {
27593         var me = this,
27594             items = me.items;
27595
27596         
27597         me.items = Ext.create('Ext.util.MixedCollection', false, me.getComponentId);
27598
27599         if (items) {
27600             if (!Ext.isArray(items)) {
27601                 items = [items];
27602             }
27603
27604             me.add(items);
27605         }
27606     },
27607
27608     
27609     afterRender : function() {
27610         this.getLayout();
27611         this.callParent();
27612     },
27613
27614     
27615     setLayout : function(layout) {
27616         var currentLayout = this.layout;
27617
27618         if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
27619             currentLayout.setOwner(null);
27620         }
27621
27622         this.layout = layout;
27623         layout.setOwner(this);
27624     },
27625
27626     
27627     getLayout : function() {
27628         var me = this;
27629         if (!me.layout || !me.layout.isLayout) {
27630             me.setLayout(Ext.layout.Layout.create(me.layout, 'autocontainer'));
27631         }
27632
27633         return me.layout;
27634     },
27635
27636     
27637     doLayout : function() {
27638         var me = this,
27639             layout = me.getLayout();
27640
27641         if (me.rendered && layout && !me.suspendLayout) {
27642             
27643             if ((!Ext.isNumber(me.width) || !Ext.isNumber(me.height)) && me.componentLayout.type !== 'autocomponent') {
27644                 
27645                 if (me.componentLayout.layoutBusy !== true) {
27646                     me.doComponentLayout();
27647                     if (me.componentLayout.layoutCancelled === true) {
27648                         layout.layout();
27649                     }
27650                 }
27651             }
27652             
27653             else {
27654                 
27655                 if (layout.layoutBusy !== true) {
27656                     layout.layout();
27657                 }
27658             }
27659         }
27660
27661         return me;
27662     },
27663
27664     
27665     afterLayout : function(layout) {
27666         this.fireEvent('afterlayout', this, layout);
27667     },
27668
27669     
27670     prepareItems : function(items, applyDefaults) {
27671         if (!Ext.isArray(items)) {
27672             items = [items];
27673         }
27674
27675         
27676         var i = 0,
27677             len = items.length,
27678             item;
27679
27680         for (; i < len; i++) {
27681             item = items[i];
27682             if (applyDefaults) {
27683                 item = this.applyDefaults(item);
27684             }
27685             items[i] = this.lookupComponent(item);
27686         }
27687         return items;
27688     },
27689
27690     
27691     applyDefaults : function(config) {
27692         var defaults = this.defaults;
27693
27694         if (defaults) {
27695             if (Ext.isFunction(defaults)) {
27696                 defaults = defaults.call(this, config);
27697             }
27698
27699             if (Ext.isString(config)) {
27700                 config = Ext.ComponentManager.get(config);
27701                 Ext.applyIf(config, defaults);
27702             } else if (!config.isComponent) {
27703                 Ext.applyIf(config, defaults);
27704             } else {
27705                 Ext.applyIf(config, defaults);
27706             }
27707         }
27708
27709         return config;
27710     },
27711
27712     
27713     lookupComponent : function(comp) {
27714         return Ext.isString(comp) ? Ext.ComponentManager.get(comp) : this.createComponent(comp);
27715     },
27716
27717     
27718     createComponent : function(config, defaultType) {
27719         
27720         
27721         
27722         
27723         
27724         
27725
27726         return Ext.ComponentManager.create(config, defaultType || this.defaultType);
27727     },
27728
27729     
27730     getComponentId : function(comp) {
27731         return comp.getItemId();
27732     },
27733
27734     
27735     add : function() {
27736         var me = this,
27737             args = Array.prototype.slice.call(arguments),
27738             hasMultipleArgs,
27739             items,
27740             results = [],
27741             i,
27742             ln,
27743             item,
27744             index = -1,
27745             cmp;
27746
27747         if (typeof args[0] == 'number') {
27748             index = args.shift();
27749         }
27750
27751         hasMultipleArgs = args.length > 1;
27752         if (hasMultipleArgs || Ext.isArray(args[0])) {
27753
27754             items = hasMultipleArgs ? args : args[0];
27755             
27756             me.suspendLayout = true;
27757             for (i = 0, ln = items.length; i < ln; i++) {
27758                 item = items[i];
27759                 
27760                 if (!item) {
27761                     Ext.Error.raise("Trying to add a null item as a child of Container with itemId/id: " + me.getItemId());
27762                 }
27763                 
27764                 if (index != -1) {
27765                     item = me.add(index + i, item);
27766                 } else {
27767                     item = me.add(item);
27768                 }
27769                 results.push(item);
27770             }
27771             
27772             me.suspendLayout = false;
27773             me.doLayout();
27774             return results;
27775         }
27776
27777         cmp = me.prepareItems(args[0], true)[0];
27778
27779         
27780         
27781         
27782         if (cmp.floating) {
27783             cmp.onAdded(me, index);
27784         } else {
27785             index = (index !== -1) ? index : me.items.length;
27786             if (me.fireEvent('beforeadd', me, cmp, index) !== false && me.onBeforeAdd(cmp) !== false) {
27787                 me.items.insert(index, cmp);
27788                 cmp.onAdded(me, index);
27789                 me.onAdd(cmp, index);
27790                 me.fireEvent('add', me, cmp, index);
27791             }
27792             me.doLayout();
27793         }
27794         return cmp;
27795     },
27796
27797     
27798     registerFloatingItem: function(cmp) {
27799         var me = this;
27800         if (!me.floatingItems) {
27801             me.floatingItems = Ext.create('Ext.ZIndexManager', me);
27802         }
27803         me.floatingItems.register(cmp);
27804     },
27805
27806     onAdd : Ext.emptyFn,
27807     onRemove : Ext.emptyFn,
27808
27809     
27810     insert : function(index, comp) {
27811         return this.add(index, comp);
27812     },
27813
27814     
27815     move : function(fromIdx, toIdx) {
27816         var items = this.items,
27817             item;
27818         item = items.removeAt(fromIdx);
27819         if (item === false) {
27820             return false;
27821         }
27822         items.insert(toIdx, item);
27823         this.doLayout();
27824         return item;
27825     },
27826
27827     
27828     onBeforeAdd : function(item) {
27829         var me = this;
27830         
27831         if (item.ownerCt) {
27832             item.ownerCt.remove(item, false);
27833         }
27834
27835         if (me.border === false || me.border === 0) {
27836             item.border = (item.border === true);
27837         }
27838     },
27839
27840     
27841     remove : function(comp, autoDestroy) {
27842         var me = this,
27843             c = me.getComponent(comp);
27844             if (Ext.isDefined(Ext.global.console) && !c) {
27845                 console.warn("Attempted to remove a component that does not exist. Ext.container.Container: remove takes an argument of the component to remove. cmp.remove() is incorrect usage.");
27846             }
27847
27848         if (c && me.fireEvent('beforeremove', me, c) !== false) {
27849             me.doRemove(c, autoDestroy);
27850             me.fireEvent('remove', me, c);
27851         }
27852
27853         return c;
27854     },
27855
27856     
27857     doRemove : function(component, autoDestroy) {
27858         var me = this,
27859             layout = me.layout,
27860             hasLayout = layout && me.rendered;
27861
27862         me.items.remove(component);
27863         component.onRemoved();
27864
27865         if (hasLayout) {
27866             layout.onRemove(component);
27867         }
27868
27869         me.onRemove(component, autoDestroy);
27870
27871         if (autoDestroy === true || (autoDestroy !== false && me.autoDestroy)) {
27872             component.destroy();
27873         }
27874
27875         if (hasLayout && !autoDestroy) {
27876             layout.afterRemove(component);
27877         }
27878
27879         if (!me.destroying) {
27880             me.doLayout();
27881         }
27882     },
27883
27884     
27885     removeAll : function(autoDestroy) {
27886         var me = this,
27887             removeItems = me.items.items.slice(),
27888             items = [],
27889             i = 0,
27890             len = removeItems.length,
27891             item;
27892
27893         
27894         me.suspendLayout = true;
27895         for (; i < len; i++) {
27896             item = removeItems[i];
27897             me.remove(item, autoDestroy);
27898
27899             if (item.ownerCt !== me) {
27900                 items.push(item);
27901             }
27902         }
27903
27904         
27905         me.suspendLayout = false;
27906         me.doLayout();
27907         return items;
27908     },
27909
27910     
27911     
27912     
27913     
27914     
27915     
27916     
27917     
27918     getRefItems : function(deep) {
27919         var me = this,
27920             items = me.items.items,
27921             len = items.length,
27922             i = 0,
27923             item,
27924             result = [];
27925
27926         for (; i < len; i++) {
27927             item = items[i];
27928             result.push(item);
27929             if (deep && item.getRefItems) {
27930                 result.push.apply(result, item.getRefItems(true));
27931             }
27932         }
27933
27934         
27935         
27936         if (me.floatingItems && me.floatingItems.accessList) {
27937             result.push.apply(result, me.floatingItems.accessList);
27938         }
27939
27940         return result;
27941     },
27942
27943     
27944     cascade : function(fn, scope, origArgs){
27945         var me = this,
27946             cs = me.items ? me.items.items : [],
27947             len = cs.length,
27948             i = 0,
27949             c,
27950             args = origArgs ? origArgs.concat(me) : [me],
27951             componentIndex = args.length - 1;
27952
27953         if (fn.apply(scope || me, args) !== false) {
27954             for(; i < len; i++){
27955                 c = cs[i];
27956                 if (c.cascade) {
27957                     c.cascade(fn, scope, origArgs);
27958                 } else {
27959                     args[componentIndex] = c;
27960                     fn.apply(scope || cs, args);
27961                 }
27962             }
27963         }
27964         return this;
27965     },
27966
27967     
27968     getComponent : function(comp) {
27969         if (Ext.isObject(comp)) {
27970             comp = comp.getItemId();
27971         }
27972
27973         return this.items.get(comp);
27974     },
27975
27976     
27977     query : function(selector) {
27978         return Ext.ComponentQuery.query(selector, this);
27979     },
27980
27981     
27982     child : function(selector) {
27983         return this.query('> ' + selector)[0] || null;
27984     },
27985
27986     
27987     down : function(selector) {
27988         return this.query(selector)[0] || null;
27989     },
27990
27991     
27992     show : function() {
27993         this.callParent(arguments);
27994         this.performDeferredLayouts();
27995         return this;
27996     },
27997
27998     
27999     
28000     performDeferredLayouts: function() {
28001         var layoutCollection = this.layoutOnShow,
28002             ln = layoutCollection.getCount(),
28003             i = 0,
28004             needsLayout,
28005             item;
28006
28007         for (; i < ln; i++) {
28008             item = layoutCollection.get(i);
28009             needsLayout = item.needsLayout;
28010
28011             if (Ext.isObject(needsLayout)) {
28012                 item.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
28013             }
28014         }
28015         layoutCollection.clear();
28016     },    
28017     
28018     //@private
28019
28020     
28021     onEnable: function() {
28022         Ext.Array.each(this.query('[isFormField]'), function(item) {
28023             if (item.resetDisable) {
28024                 item.enable();
28025                 delete item.resetDisable;             
28026             }
28027         });
28028         this.callParent();
28029     },
28030     
28031     
28032     
28033     onDisable: function() {
28034         Ext.Array.each(this.query('[isFormField]'), function(item) {
28035             if (item.resetDisable !== false && !item.disabled) {
28036                 item.disable();
28037                 item.resetDisable = true;
28038             }
28039         });
28040         this.callParent();
28041     },
28042
28043     
28044     beforeLayout: function() {
28045         return true;
28046     },
28047
28048     
28049     beforeDestroy : function() {
28050         var me = this,
28051             items = me.items,
28052             c;
28053
28054         if (items) {
28055             while ((c = items.first())) {
28056                 me.doRemove(c, true);
28057             }
28058         }
28059
28060         Ext.destroy(
28061             me.layout,
28062             me.floatingItems
28063         );
28064         me.callParent();
28065     }
28066 });
28067
28068 Ext.define('Ext.container.Container', {
28069     extend: 'Ext.container.AbstractContainer',
28070     alias: 'widget.container',
28071     alternateClassName: 'Ext.Container',
28072
28073     
28074     getChildByElement: function(el) {
28075         var item,
28076             itemEl,
28077             i = 0,
28078             it = this.items.items,
28079             ln = it.length;
28080
28081         el = Ext.getDom(el);
28082         for (; i < ln; i++) {
28083             item = it[i];
28084             itemEl = item.getEl();
28085             if ((itemEl.dom === el) || itemEl.contains(el)) {
28086                 return item;
28087             }
28088         }
28089         return null;
28090     }
28091 });
28092
28093
28094 Ext.define('Ext.toolbar.Fill', {
28095     extend: 'Ext.Component',
28096     alias: 'widget.tbfill',
28097     alternateClassName: 'Ext.Toolbar.Fill',
28098     isFill : true,
28099     flex: 1
28100 });
28101
28102 Ext.define('Ext.toolbar.Item', {
28103     extend: 'Ext.Component',
28104     alias: 'widget.tbitem',
28105     alternateClassName: 'Ext.Toolbar.Item',
28106     enable:Ext.emptyFn,
28107     disable:Ext.emptyFn,
28108     focus:Ext.emptyFn
28109     
28110 });
28111
28112 Ext.define('Ext.toolbar.Separator', {
28113     extend: 'Ext.toolbar.Item',
28114     alias: 'widget.tbseparator',
28115     alternateClassName: 'Ext.Toolbar.Separator',
28116     baseCls: Ext.baseCSSPrefix + 'toolbar-separator',
28117     focusable: false
28118 });
28119
28120 Ext.define('Ext.menu.Manager', {
28121     singleton: true,
28122     requires: [
28123         'Ext.util.MixedCollection',
28124         'Ext.util.KeyMap'
28125     ],
28126     alternateClassName: 'Ext.menu.MenuMgr',
28127
28128     uses: ['Ext.menu.Menu'],
28129
28130     menus: {},
28131     groups: {},
28132     attached: false,
28133     lastShow: new Date(),
28134
28135     init: function() {
28136         var me = this;
28137         
28138         me.active = Ext.create('Ext.util.MixedCollection');
28139         Ext.getDoc().addKeyListener(27, function() {
28140             if (me.active.length > 0) {
28141                 me.hideAll();
28142             }
28143         }, me);
28144     },
28145
28146     
28147     hideAll: function() {
28148         var active = this.active,
28149             c;
28150         if (active && active.length > 0) {
28151             c = active.clone();
28152             c.each(function(m) {
28153                 m.hide();
28154             });
28155             return true;
28156         }
28157         return false;
28158     },
28159
28160     onHide: function(m) {
28161         var me = this,
28162             active = me.active;
28163         active.remove(m);
28164         if (active.length < 1) {
28165             Ext.getDoc().un('mousedown', me.onMouseDown, me);
28166             me.attached = false;
28167         }
28168     },
28169
28170     onShow: function(m) {
28171         var me = this,
28172             active   = me.active,
28173             last     = active.last(),
28174             attached = me.attached,
28175             menuEl   = m.getEl(),
28176             zIndex;
28177
28178         me.lastShow = new Date();
28179         active.add(m);
28180         if (!attached) {
28181             Ext.getDoc().on('mousedown', me.onMouseDown, me);
28182             me.attached = true;
28183         }
28184         m.toFront();
28185     },
28186
28187     onBeforeHide: function(m) {
28188         if (m.activeChild) {
28189             m.activeChild.hide();
28190         }
28191         if (m.autoHideTimer) {
28192             clearTimeout(m.autoHideTimer);
28193             delete m.autoHideTimer;
28194         }
28195     },
28196
28197     onBeforeShow: function(m) {
28198         var active = this.active,
28199             parentMenu = m.parentMenu;
28200             
28201         active.remove(m);
28202         if (!parentMenu && !m.allowOtherMenus) {
28203             this.hideAll();
28204         }
28205         else if (parentMenu && parentMenu.activeChild && m != parentMenu.activeChild) {
28206             parentMenu.activeChild.hide();
28207         }
28208     },
28209
28210     
28211     onMouseDown: function(e) {
28212         var me = this,
28213             active = me.active,
28214             lastShow = me.lastShow;
28215
28216         if (Ext.Date.getElapsed(lastShow) > 50 && active.length > 0 && !e.getTarget('.' + Ext.baseCSSPrefix + 'menu')) {
28217             me.hideAll();
28218         }
28219     },
28220
28221     
28222     register: function(menu) {
28223         var me = this;
28224
28225         if (!me.active) {
28226             me.init();
28227         }
28228
28229         if (menu.floating) {
28230             me.menus[menu.id] = menu;
28231             menu.on({
28232                 beforehide: me.onBeforeHide,
28233                 hide: me.onHide,
28234                 beforeshow: me.onBeforeShow,
28235                 show: me.onShow,
28236                 scope: me
28237             });
28238         }
28239     },
28240
28241     
28242     get: function(menu) {
28243         var menus = this.menus;
28244         
28245         if (typeof menu == 'string') { 
28246             if (!menus) {  
28247                 return null;
28248             }
28249             return menus[menu];
28250         } else if (menu.isMenu) {  
28251             return menu;
28252         } else if (Ext.isArray(menu)) { 
28253             return Ext.create('Ext.menu.Menu', {items:menu});
28254         } else { 
28255             return Ext.ComponentManager.create(menu, 'menu');
28256         }
28257     },
28258
28259     
28260     unregister: function(menu) {
28261         var me = this,
28262             menus = me.menus,
28263             active = me.active;
28264
28265         delete menus[menu.id];
28266         active.remove(menu);
28267         menu.un({
28268             beforehide: me.onBeforeHide,
28269             hide: me.onHide,
28270             beforeshow: me.onBeforeShow,
28271             show: me.onShow,
28272             scope: me
28273         });
28274     },
28275
28276     
28277     registerCheckable: function(menuItem) {
28278         var groups  = this.groups,
28279             groupId = menuItem.group;
28280
28281         if (groupId) {
28282             if (!groups[groupId]) {
28283                 groups[groupId] = [];
28284             }
28285
28286             groups[groupId].push(menuItem);
28287         }
28288     },
28289
28290     
28291     unregisterCheckable: function(menuItem) {
28292         var groups  = this.groups,
28293             groupId = menuItem.group;
28294
28295         if (groupId) {
28296             Ext.Array.remove(groups[groupId], menuItem);
28297         }
28298     },
28299
28300     onCheckChange: function(menuItem, state) {
28301         var groups  = this.groups,
28302             groupId = menuItem.group,
28303             i       = 0,
28304             group, ln, curr;
28305
28306         if (groupId && state) {
28307             group = groups[groupId];
28308             ln = group.length;
28309             for (; i < ln; i++) {
28310                 curr = group[i];
28311                 if (curr != menuItem) {
28312                     curr.setChecked(false);
28313                 }
28314             }
28315         }
28316     }
28317 });
28318
28319 Ext.define('Ext.button.Button', {
28320
28321     
28322     alias: 'widget.button',
28323     extend: 'Ext.Component',
28324
28325     requires: [
28326         'Ext.menu.Manager',
28327         'Ext.util.ClickRepeater',
28328         'Ext.layout.component.Button',
28329         'Ext.util.TextMetrics',
28330         'Ext.util.KeyMap'
28331     ],
28332
28333     alternateClassName: 'Ext.Button',
28334     
28335
28336     isButton: true,
28337     componentLayout: 'button',
28338
28339     
28340     hidden: false,
28341
28342     
28343     disabled: false,
28344
28345     
28346     pressed: false,
28347
28348     
28349
28350     
28351
28352     
28353
28354     
28355
28356     
28357
28358     
28359
28360     
28361
28362     
28363
28364     
28365
28366     
28367
28368     
28369
28370     
28371
28372     
28373     enableToggle: false,
28374
28375     
28376
28377     
28378
28379     
28380     menuAlign: 'tl-bl?',
28381
28382     
28383
28384     
28385
28386     
28387     type: 'button',
28388
28389     
28390     clickEvent: 'click',
28391     
28392     
28393     preventDefault: true,
28394
28395     
28396     handleMouseEvents: true,
28397
28398     
28399     tooltipType: 'qtip',
28400
28401     
28402     baseCls: Ext.baseCSSPrefix + 'btn',
28403
28404     
28405     pressedCls: 'pressed',
28406     
28407     
28408     overCls: 'over',
28409     
28410     
28411     focusCls: 'focus',
28412     
28413     
28414     menuActiveCls: 'menu-active',
28415
28416     ariaRole: 'button',
28417
28418     
28419     renderTpl:
28420         '<em class="{splitCls}">' +
28421             '<tpl if="href">' +
28422                 '<a href="{href}" target="{target}"<tpl if="tabIndex"> tabIndex="{tabIndex}"</tpl> role="link">' +
28423                     '<span class="{baseCls}-inner">{text}</span>' +
28424                 '</a>' +
28425             '</tpl>' +
28426             '<tpl if="!href">' +
28427                 '<button type="{type}" hidefocus="true"' +
28428                     
28429                     
28430                     '<tpl if="tabIndex"> tabIndex="{tabIndex}"</tpl> role="button" autocomplete="off">' +
28431                     '<span class="{baseCls}-inner" style="{innerSpanStyle}">{text}</span>' +
28432                 '</button>' +
28433             '</tpl>' +
28434         '</em>' ,
28435
28436     
28437     scale: 'small',
28438     
28439     
28440     allowedScales: ['small', 'medium', 'large'],
28441     
28442     
28443
28444     
28445     iconAlign: 'left',
28446
28447     
28448     arrowAlign: 'right',
28449
28450     
28451     arrowCls: 'arrow',
28452
28453     
28454
28455     
28456
28457     
28458
28459     
28460      
28461     maskOnDisable: false,
28462
28463     
28464     initComponent: function() {
28465         var me = this;
28466         me.callParent(arguments);
28467
28468         me.addEvents(
28469             
28470             'click',
28471
28472             
28473             'toggle',
28474
28475             
28476             'mouseover',
28477
28478             
28479             'mouseout',
28480
28481             
28482             'menushow',
28483
28484             
28485             'menuhide',
28486
28487             
28488             'menutriggerover',
28489
28490             
28491             'menutriggerout'
28492         );
28493
28494         if (me.menu) {
28495             
28496             me.split = true;
28497
28498             
28499             me.menu = Ext.menu.Manager.get(me.menu);
28500             me.menu.ownerCt = me;
28501         }
28502
28503         
28504         if (me.url) {
28505             me.href = me.url;
28506         }
28507
28508         
28509         if (me.href && !me.hasOwnProperty('preventDefault')) {
28510             me.preventDefault = false;
28511         }
28512
28513         if (Ext.isString(me.toggleGroup)) {
28514             me.enableToggle = true;
28515         }
28516
28517     },
28518
28519     
28520     initAria: function() {
28521         this.callParent();
28522         var actionEl = this.getActionEl();
28523         if (this.menu) {
28524             actionEl.dom.setAttribute('aria-haspopup', true);
28525         }
28526     },
28527
28528     
28529     getActionEl: function() {
28530         return this.btnEl;
28531     },
28532
28533     
28534     getFocusEl: function() {
28535         return this.btnEl;
28536     },
28537
28538     
28539     setButtonCls: function() {
28540         var me = this,
28541             el = me.el,
28542             cls = [];
28543
28544         if (me.useSetClass) {
28545             if (!Ext.isEmpty(me.oldCls)) {
28546                 me.removeClsWithUI(me.oldCls);
28547                 me.removeClsWithUI(me.pressedCls);
28548             }
28549             
28550             
28551             if (me.iconCls || me.icon) {
28552                 if (me.text) {
28553                     cls.push('icon-text-' + me.iconAlign);
28554                 } else {
28555                     cls.push('icon');
28556                 }
28557             } else if (me.text) {
28558                 cls.push('noicon');
28559             }
28560             
28561             me.oldCls = cls;
28562             me.addClsWithUI(cls);
28563             me.addClsWithUI(me.pressed ? me.pressedCls : null);
28564         }
28565     },
28566     
28567     
28568     onRender: function(ct, position) {
28569         
28570         var me = this,
28571             repeater, btn;
28572             
28573         
28574         Ext.applyIf(me.renderData, me.getTemplateArgs());
28575
28576         
28577         Ext.applyIf(me.renderSelectors, {
28578             btnEl  : me.href ? 'a' : 'button',
28579             btnWrap: 'em',
28580             btnInnerEl: '.' + me.baseCls + '-inner'
28581         });
28582         
28583         if (me.scale) {
28584             me.ui = me.ui + '-' + me.scale;
28585         }
28586
28587         
28588         me.callParent(arguments);
28589
28590         
28591         if (me.split && me.arrowTooltip) {
28592             me.arrowEl.dom[me.tooltipType] = me.arrowTooltip;
28593         }
28594
28595         
28596         me.mon(me.btnEl, {
28597             scope: me,
28598             focus: me.onFocus,
28599             blur : me.onBlur
28600         });
28601
28602         
28603         btn = me.el;
28604
28605         if (me.icon) {
28606             me.setIcon(me.icon);
28607         }
28608
28609         if (me.iconCls) {
28610             me.setIconCls(me.iconCls);
28611         }
28612
28613         if (me.tooltip) {
28614             me.setTooltip(me.tooltip, true);
28615         }
28616
28617         
28618         if (me.handleMouseEvents) {
28619             me.mon(btn, {
28620                 scope: me,
28621                 mouseover: me.onMouseOver,
28622                 mouseout: me.onMouseOut,
28623                 mousedown: me.onMouseDown
28624             });
28625
28626             if (me.split) {
28627                 me.mon(btn, {
28628                     mousemove: me.onMouseMove,
28629                     scope: me
28630                 });
28631             }
28632         }
28633
28634         
28635         if (me.menu) {
28636             me.mon(me.menu, {
28637                 scope: me,
28638                 show: me.onMenuShow,
28639                 hide: me.onMenuHide
28640             });
28641
28642             me.keyMap = Ext.create('Ext.util.KeyMap', me.el, {
28643                 key: Ext.EventObject.DOWN,
28644                 handler: me.onDownKey,
28645                 scope: me
28646             });
28647         }
28648
28649         
28650         if (me.repeat) {
28651             repeater = Ext.create('Ext.util.ClickRepeater', btn, Ext.isObject(me.repeat) ? me.repeat: {});
28652             me.mon(repeater, 'click', me.onRepeatClick, me);
28653         } else {
28654             me.mon(btn, me.clickEvent, me.onClick, me);
28655         }
28656
28657         
28658         Ext.ButtonToggleManager.register(me);
28659     },
28660
28661     
28662     getTemplateArgs: function() {
28663         var me = this,
28664             persistentPadding = me.getPersistentBtnPadding(),
28665             innerSpanStyle = '';
28666
28667         
28668         if (Math.max.apply(Math, persistentPadding) > 0) {
28669             innerSpanStyle = 'margin:' + Ext.Array.map(persistentPadding, function(pad) {
28670                 return -pad + 'px';
28671             }).join(' ');
28672         }
28673
28674         return {
28675             href     : me.getHref(),
28676             target   : me.target || '_blank',
28677             type     : me.type,
28678             splitCls : me.getSplitCls(),
28679             cls      : me.cls,
28680             text     : me.text || '&#160;',
28681             tabIndex : me.tabIndex,
28682             innerSpanStyle: innerSpanStyle
28683         };
28684     },
28685
28686     
28687     getHref: function() {
28688         var me = this;
28689         return me.href ? Ext.urlAppend(me.href, me.params + Ext.Object.toQueryString(Ext.apply(Ext.apply({}, me.baseParams)))) : false;
28690     },
28691
28692     
28693     setParams: function(p) {
28694         this.params = p;
28695         this.btnEl.dom.href = this.getHref();
28696     },
28697
28698     getSplitCls: function() {
28699         var me = this;
28700         return me.split ? (me.baseCls + '-' + me.arrowCls) + ' ' + (me.baseCls + '-' + me.arrowCls + '-' + me.arrowAlign) : '';
28701     },
28702
28703     
28704     afterRender: function() {
28705         var me = this;
28706         me.useSetClass = true;
28707         me.setButtonCls();
28708         me.doc = Ext.getDoc();
28709         this.callParent(arguments);
28710     },
28711
28712     
28713     setIconCls: function(cls) {
28714         var me = this,
28715             btnInnerEl = me.btnInnerEl;
28716         if (btnInnerEl) {
28717             
28718             btnInnerEl.removeCls(me.iconCls);
28719             btnInnerEl.addCls(cls || '');
28720             me.setButtonCls();
28721         }
28722         me.iconCls = cls;
28723         return me;
28724     },
28725
28726     
28727     setTooltip: function(tooltip, initial) {
28728         var me = this;
28729
28730         if (me.rendered) {
28731             if (!initial) {
28732                 me.clearTip();
28733             }
28734             if (Ext.isObject(tooltip)) {
28735                 Ext.tip.QuickTipManager.register(Ext.apply({
28736                     target: me.btnEl.id
28737                 },
28738                 tooltip));
28739                 me.tooltip = tooltip;
28740             } else {
28741                 me.btnEl.dom.setAttribute('data-' + this.tooltipType, tooltip);
28742             }
28743         } else {
28744             me.tooltip = tooltip;
28745         }
28746         return me;
28747     },
28748
28749     
28750     getRefItems: function(deep){
28751         var menu = this.menu,
28752             items;
28753
28754         if (menu) {
28755             items = menu.getRefItems(deep);
28756             items.unshift(menu);
28757         }
28758         return items || [];
28759     },
28760
28761     
28762     clearTip: function() {
28763         if (Ext.isObject(this.tooltip)) {
28764             Ext.tip.QuickTipManager.unregister(this.btnEl);
28765         }
28766     },
28767
28768     
28769     beforeDestroy: function() {
28770         var me = this;
28771         if (me.rendered) {
28772             me.clearTip();
28773         }
28774         if (me.menu && me.destroyMenu !== false) {
28775             Ext.destroy(me.btnEl, me.btnInnerEl, me.menu);
28776         }
28777         Ext.destroy(me.repeater);
28778     },
28779
28780     
28781     onDestroy: function() {
28782         var me = this;
28783         if (me.rendered) {
28784             me.doc.un('mouseover', me.monitorMouseOver, me);
28785             me.doc.un('mouseup', me.onMouseUp, me);
28786             delete me.doc;
28787             delete me.btnEl;
28788             delete me.btnInnerEl;
28789             Ext.ButtonToggleManager.unregister(me);
28790             
28791             Ext.destroy(me.keyMap);
28792             delete me.keyMap;
28793         }
28794         me.callParent();
28795     },
28796
28797     
28798     setHandler: function(handler, scope) {
28799         this.handler = handler;
28800         this.scope = scope;
28801         return this;
28802     },
28803
28804     
28805     setText: function(text) {
28806         var me = this;
28807         me.text = text;
28808         if (me.el) {
28809             me.btnInnerEl.update(text || '&#160;');
28810             me.setButtonCls();
28811         }
28812         me.doComponentLayout();
28813         return me;
28814     },
28815
28816     
28817     setIcon: function(icon) {
28818         var me = this,
28819             btnInnerEl = me.btnInnerEl;
28820         me.icon = icon;
28821         if (btnInnerEl) {
28822             btnInnerEl.setStyle('background-image', icon ? 'url(' + icon + ')': '');
28823             me.setButtonCls();
28824         }
28825         return me;
28826     },
28827
28828     
28829     getText: function() {
28830         return this.text;
28831     },
28832
28833     
28834     toggle: function(state, suppressEvent) {
28835         var me = this;
28836         state = state === undefined ? !me.pressed: !!state;
28837         if (state !== me.pressed) {
28838             if (me.rendered) {
28839                 me[state ? 'addClsWithUI': 'removeClsWithUI'](me.pressedCls);
28840             }
28841             me.btnEl.dom.setAttribute('aria-pressed', state);
28842             me.pressed = state;
28843             if (!suppressEvent) {
28844                 me.fireEvent('toggle', me, state);
28845                 Ext.callback(me.toggleHandler, me.scope || me, [me, state]);
28846             }
28847         }
28848         return me;
28849     },
28850
28851     
28852     showMenu: function() {
28853         var me = this;
28854         if (me.rendered && me.menu) {
28855             if (me.tooltip) {
28856                 Ext.tip.QuickTipManager.getQuickTip().cancelShow(me.btnEl);
28857             }
28858             if (me.menu.isVisible()) {
28859                 me.menu.hide();
28860             }
28861
28862             me.menu.showBy(me.el, me.menuAlign);
28863         }
28864         return me;
28865     },
28866
28867     
28868     hideMenu: function() {
28869         if (this.hasVisibleMenu()) {
28870             this.menu.hide();
28871         }
28872         return this;
28873     },
28874
28875     
28876     hasVisibleMenu: function() {
28877         var menu = this.menu;
28878         return menu && menu.rendered && menu.isVisible();
28879     },
28880
28881     
28882     onRepeatClick: function(repeat, e) {
28883         this.onClick(e);
28884     },
28885
28886     
28887     onClick: function(e) {
28888         var me = this;
28889         if (me.preventDefault || (me.disabled && me.getHref()) && e) {
28890             e.preventDefault();
28891         }
28892         if (e.button !== 0) {
28893             return;
28894         }
28895         if (!me.disabled) {
28896             if (me.enableToggle && (me.allowDepress !== false || !me.pressed)) {
28897                 me.toggle();
28898             }
28899             if (me.menu && !me.hasVisibleMenu() && !me.ignoreNextClick) {
28900                 me.showMenu();
28901             }
28902             me.fireEvent('click', me, e);
28903             if (me.handler) {
28904                 me.handler.call(me.scope || me, me, e);
28905             }
28906             me.onBlur();
28907         }
28908     },
28909
28910     
28911     onMouseOver: function(e) {
28912         var me = this;
28913         if (!me.disabled && !e.within(me.el, true, true)) {
28914             me.onMouseEnter(e);
28915         }
28916     },
28917
28918     
28919     onMouseOut: function(e) {
28920         var me = this;
28921         if (!e.within(me.el, true, true)) {
28922             if (me.overMenuTrigger) {
28923                 me.onMenuTriggerOut(e);
28924             }
28925             me.onMouseLeave(e);
28926         }
28927     },
28928
28929     
28930     onMouseMove: function(e) {
28931         var me = this,
28932             el = me.el,
28933             over = me.overMenuTrigger,
28934             overlap, btnSize;
28935
28936         if (me.split) {
28937             if (me.arrowAlign === 'right') {
28938                 overlap = e.getX() - el.getX();
28939                 btnSize = el.getWidth();
28940             } else {
28941                 overlap = e.getY() - el.getY();
28942                 btnSize = el.getHeight();
28943             }
28944
28945             if (overlap > (btnSize - me.getTriggerSize())) {
28946                 if (!over) {
28947                     me.onMenuTriggerOver(e);
28948                 }
28949             } else {
28950                 if (over) {
28951                     me.onMenuTriggerOut(e);
28952                 }
28953             }
28954         }
28955     },
28956
28957     
28958     getTriggerSize: function() {
28959         var me = this,
28960             size = me.triggerSize,
28961             side, sideFirstLetter, undef;
28962             
28963         if (size === undef) {
28964             side = me.arrowAlign;
28965             sideFirstLetter = side.charAt(0);
28966             size = me.triggerSize = me.el.getFrameWidth(sideFirstLetter) + me.btnWrap.getFrameWidth(sideFirstLetter) + (me.frameSize && me.frameSize[side] || 0);
28967         }
28968         return size;
28969     },
28970
28971     
28972     onMouseEnter: function(e) {
28973         var me = this;
28974         me.addClsWithUI(me.overCls);
28975         me.fireEvent('mouseover', me, e);
28976     },
28977
28978     
28979     onMouseLeave: function(e) {
28980         var me = this;
28981         me.removeClsWithUI(me.overCls);
28982         me.fireEvent('mouseout', me, e);
28983     },
28984
28985     
28986     onMenuTriggerOver: function(e) {
28987         var me = this;
28988         me.overMenuTrigger = true;
28989         me.fireEvent('menutriggerover', me, me.menu, e);
28990     },
28991
28992     
28993     onMenuTriggerOut: function(e) {
28994         var me = this;
28995         delete me.overMenuTrigger;
28996         me.fireEvent('menutriggerout', me, me.menu, e);
28997     },
28998     
28999     
29000     enable : function(silent) {
29001         var me = this;
29002
29003         me.callParent(arguments);
29004         
29005         me.removeClsWithUI('disabled');
29006
29007         return me;
29008     },
29009
29010     
29011     disable : function(silent) {
29012         var me = this;
29013         
29014         me.callParent(arguments);
29015         
29016         me.addClsWithUI('disabled');
29017
29018         return me;
29019     },
29020     
29021     
29022     setScale: function(scale) {
29023         var me = this,
29024             ui = me.ui.replace('-' + me.scale, '');
29025         
29026         
29027         if (!Ext.Array.contains(me.allowedScales, scale)) {
29028             throw('#setScale: scale must be an allowed scale (' + me.allowedScales.join(', ') + ')');
29029         }
29030         
29031         me.scale = scale;
29032         me.setUI(ui);
29033     },
29034     
29035     
29036     setUI: function(ui) {
29037         var me = this;
29038         
29039         
29040         if (me.scale && !ui.match(me.scale)) {
29041             ui = ui + '-' + me.scale;
29042         }
29043         
29044         me.callParent([ui]);
29045         
29046         
29047         
29048     },
29049     
29050     
29051     onFocus: function(e) {
29052         var me = this;
29053         if (!me.disabled) {
29054             me.addClsWithUI(me.focusCls);
29055         }
29056     },
29057
29058     
29059     onBlur: function(e) {
29060         var me = this;
29061         me.removeClsWithUI(me.focusCls);
29062     },
29063
29064     
29065     onMouseDown: function(e) {
29066         var me = this;
29067         if (!me.disabled && e.button === 0) {
29068             me.addClsWithUI(me.pressedCls);
29069             me.doc.on('mouseup', me.onMouseUp, me);
29070         }
29071     },
29072     
29073     onMouseUp: function(e) {
29074         var me = this;
29075         if (e.button === 0) {
29076             if (!me.pressed) {
29077                 me.removeClsWithUI(me.pressedCls);
29078             }
29079             me.doc.un('mouseup', me.onMouseUp, me);
29080         }
29081     },
29082     
29083     onMenuShow: function(e) {
29084         var me = this;
29085         me.ignoreNextClick = 0;
29086         me.addClsWithUI(me.menuActiveCls);
29087         me.fireEvent('menushow', me, me.menu);
29088     },
29089
29090     
29091     onMenuHide: function(e) {
29092         var me = this;
29093         me.removeClsWithUI(me.menuActiveCls);
29094         me.ignoreNextClick = Ext.defer(me.restoreClick, 250, me);
29095         me.fireEvent('menuhide', me, me.menu);
29096     },
29097
29098     
29099     restoreClick: function() {
29100         this.ignoreNextClick = 0;
29101     },
29102
29103     
29104     onDownKey: function() {
29105         var me = this;
29106
29107         if (!me.disabled) {
29108             if (me.menu) {
29109                 me.showMenu();
29110             }
29111         }
29112     },
29113
29114     
29115     getPersistentBtnPadding: function() {
29116         var cls = Ext.button.Button,
29117             padding = cls.persistentPadding,
29118             btn, leftTop, btnEl, btnInnerEl;
29119
29120         if (!padding) {
29121             padding = cls.persistentPadding = [0, 0, 0, 0]; 
29122
29123             if (!Ext.isIE) { 
29124                 
29125                 btn = Ext.create('Ext.button.Button', {
29126                     renderTo: Ext.getBody(),
29127                     text: 'test',
29128                     style: 'position:absolute;top:-999px;'
29129                 });
29130                 btnEl = btn.btnEl;
29131                 btnInnerEl = btn.btnInnerEl;
29132                 btnEl.setSize(null, null); 
29133
29134                 leftTop = btnInnerEl.getOffsetsTo(btnEl);
29135                 padding[0] = leftTop[1];
29136                 padding[1] = btnEl.getWidth() - btnInnerEl.getWidth() - leftTop[0];
29137                 padding[2] = btnEl.getHeight() - btnInnerEl.getHeight() - leftTop[1];
29138                 padding[3] = leftTop[0];
29139
29140                 btn.destroy();
29141             }
29142         }
29143
29144         return padding;
29145     }
29146
29147 }, function() {
29148     var groups = {},
29149         g, i, l;
29150
29151     function toggleGroup(btn, state) {
29152         if (state) {
29153             g = groups[btn.toggleGroup];
29154             for (i = 0, l = g.length; i < l; i++) {
29155                 if (g[i] !== btn) {
29156                     g[i].toggle(false);
29157                 }
29158             }
29159         }
29160     }
29161     
29162     Ext.ButtonToggleManager = {
29163         register: function(btn) {
29164             if (!btn.toggleGroup) {
29165                 return;
29166             }
29167             var group = groups[btn.toggleGroup];
29168             if (!group) {
29169                 group = groups[btn.toggleGroup] = [];
29170             }
29171             group.push(btn);
29172             btn.on('toggle', toggleGroup);
29173         },
29174
29175         unregister: function(btn) {
29176             if (!btn.toggleGroup) {
29177                 return;
29178             }
29179             var group = groups[btn.toggleGroup];
29180             if (group) {
29181                 Ext.Array.remove(group, btn);
29182                 btn.un('toggle', toggleGroup);
29183             }
29184         },
29185
29186         
29187         getPressed: function(group) {
29188             var g = groups[group],
29189                 i = 0,
29190                 len;
29191             if (g) {
29192                 for (len = g.length; i < len; i++) {
29193                     if (g[i].pressed === true) {
29194                         return g[i];
29195                     }
29196                 }
29197             }
29198             return null;
29199         }
29200     };
29201 });
29202
29203
29204 Ext.define('Ext.layout.container.boxOverflow.Menu', {
29205
29206     
29207
29208     extend: 'Ext.layout.container.boxOverflow.None',
29209     requires: ['Ext.toolbar.Separator', 'Ext.button.Button'],
29210     alternateClassName: 'Ext.layout.boxOverflow.Menu',
29211     
29212     
29213
29214     
29215
29216     
29217     noItemsMenuText : '<div class="' + Ext.baseCSSPrefix + 'toolbar-no-items">(None)</div>',
29218
29219     constructor: function(layout) {
29220         var me = this;
29221
29222         me.callParent(arguments);
29223
29224         
29225         layout.beforeLayout = Ext.Function.createInterceptor(layout.beforeLayout, this.clearOverflow, this);
29226
29227         me.afterCtCls = me.afterCtCls || Ext.baseCSSPrefix + 'box-menu-' + layout.parallelAfter;
29228         
29229         me.menuItems = [];
29230     },
29231
29232     handleOverflow: function(calculations, targetSize) {
29233         var me = this,
29234             layout = me.layout,
29235             methodName = 'get' + layout.parallelPrefixCap,
29236             newSize = {},
29237             posArgs = [null, null];
29238
29239         me.callParent(arguments);
29240         this.createMenu(calculations, targetSize);
29241         newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
29242         newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - me.afterCt[methodName]();
29243
29244         
29245         
29246         posArgs[layout.perpendicularSizeIndex] = (calculations.meta.maxSize - me.menuTrigger['get' + layout.perpendicularPrefixCap]()) / 2;
29247         me.menuTrigger.setPosition.apply(me.menuTrigger, posArgs);
29248
29249         return { targetSize: newSize };
29250     },
29251
29252     
29253     clearOverflow: function(calculations, targetSize) {
29254         var me = this,
29255             newWidth = targetSize ? targetSize.width + (me.afterCt ? me.afterCt.getWidth() : 0) : 0,
29256             items = me.menuItems,
29257             i = 0,
29258             length = items.length,
29259             item;
29260
29261         me.hideTrigger();
29262         for (; i < length; i++) {
29263             items[i].show();
29264         }
29265         items.length = 0;
29266
29267         return targetSize ? {
29268             targetSize: {
29269                 height: targetSize.height,
29270                 width : newWidth
29271             }
29272         } : null;
29273     },
29274
29275     
29276     showTrigger: function() {
29277         this.menuTrigger.show();
29278     },
29279
29280     
29281     hideTrigger: function() {
29282         if (this.menuTrigger != undefined) {
29283             this.menuTrigger.hide();
29284         }
29285     },
29286
29287     
29288     beforeMenuShow: function(menu) {
29289         var me = this,
29290             items = me.menuItems,
29291             i = 0,
29292             len   = items.length,
29293             item,
29294             prev;
29295
29296         var needsSep = function(group, prev){
29297             return group.isXType('buttongroup') && !(prev instanceof Ext.toolbar.Separator);
29298         };
29299
29300         me.clearMenu();
29301         menu.removeAll();
29302
29303         for (; i < len; i++) {
29304             item = items[i];
29305
29306             
29307             if (!i && (item instanceof Ext.toolbar.Separator)) {
29308                 continue;
29309             }
29310             if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
29311                 menu.add('-');
29312             }
29313
29314             me.addComponentToMenu(menu, item);
29315             prev = item;
29316         }
29317
29318         
29319         if (menu.items.length < 1) {
29320             menu.add(me.noItemsMenuText);
29321         }
29322     },
29323     
29324     
29325     createMenuConfig : function(component, hideOnClick) {
29326         var config = Ext.apply({}, component.initialConfig),
29327             group  = component.toggleGroup;
29328
29329         Ext.copyTo(config, component, [
29330             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
29331         ]);
29332
29333         Ext.apply(config, {
29334             text       : component.overflowText || component.text,
29335             hideOnClick: hideOnClick,
29336             destroyMenu: false
29337         });
29338
29339         if (group || component.enableToggle) {
29340             Ext.apply(config, {
29341                 group  : group,
29342                 checked: component.pressed,
29343                 listeners: {
29344                     checkchange: function(item, checked){
29345                         component.toggle(checked);
29346                     }
29347                 }
29348             });
29349         }
29350
29351         delete config.ownerCt;
29352         delete config.xtype;
29353         delete config.id;
29354         return config;
29355     },
29356
29357     
29358     addComponentToMenu : function(menu, component) {
29359         var me = this;
29360         if (component instanceof Ext.toolbar.Separator) {
29361             menu.add('-');
29362         } else if (component.isComponent) {
29363             if (component.isXType('splitbutton')) {
29364                 menu.add(me.createMenuConfig(component, true));
29365
29366             } else if (component.isXType('button')) {
29367                 menu.add(me.createMenuConfig(component, !component.menu));
29368
29369             } else if (component.isXType('buttongroup')) {
29370                 component.items.each(function(item){
29371                      me.addComponentToMenu(menu, item);
29372                 });
29373             } else {
29374                 menu.add(Ext.create(Ext.getClassName(component), me.createMenuConfig(component)));
29375             }
29376         }
29377     },
29378
29379     
29380     clearMenu : function() {
29381         var menu = this.moreMenu;
29382         if (menu && menu.items) {
29383             menu.items.each(function(item) {
29384                 if (item.menu) {
29385                     delete item.menu;
29386                 }
29387             });
29388         }
29389     },
29390
29391     
29392     createMenu: function(calculations, targetSize) {
29393         var me = this,
29394             layout = me.layout,
29395             startProp = layout.parallelBefore,
29396             sizeProp = layout.parallelPrefix,
29397             available = targetSize[sizeProp],
29398             boxes = calculations.boxes,
29399             i = 0,
29400             len = boxes.length,
29401             box;
29402
29403         if (!me.menuTrigger) {
29404             me.createInnerElements();
29405
29406             
29407             me.menu = Ext.create('Ext.menu.Menu', {
29408                 hideMode: 'offsets',
29409                 listeners: {
29410                     scope: me,
29411                     beforeshow: me.beforeMenuShow
29412                 }
29413             });
29414
29415             
29416             me.menuTrigger = Ext.create('Ext.button.Button', {
29417                 ownerCt : me.layout.owner, 
29418                 iconCls : Ext.baseCSSPrefix + layout.owner.getXType() + '-more-icon',
29419                 ui      : layout.owner instanceof Ext.toolbar.Toolbar ? 'default-toolbar' : 'default',
29420                 menu    : me.menu,
29421                 getSplitCls: function() { return '';},
29422                 renderTo: me.afterCt
29423             });
29424         }
29425         me.showTrigger();
29426         available -= me.afterCt.getWidth();
29427
29428         
29429         
29430         me.menuItems.length = 0;
29431         for (; i < len; i++) {
29432             box = boxes[i];
29433             if (box[startProp] + box[sizeProp] > available) {
29434                 me.menuItems.push(box.component);
29435                 box.component.hide();
29436             }
29437         }
29438     },
29439
29440     
29441     createInnerElements: function() {
29442         var me = this,
29443             target = me.layout.getRenderTarget();
29444
29445         if (!this.afterCt) {
29446             target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
29447             this.afterCt  = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + this.afterCtCls}, 'before');
29448         }
29449     },
29450
29451     
29452     destroy: function() {
29453         Ext.destroy(this.menu, this.menuTrigger);
29454     }
29455 });
29456
29457
29458 Ext.define('Ext.util.Region', {
29459
29460     
29461
29462     requires: ['Ext.util.Offset'],
29463
29464     statics: {
29465         
29466         getRegion: function(el) {
29467             return Ext.fly(el).getPageBox(true);
29468         },
29469
29470         
29471         from: function(o) {
29472             return new this(o.top, o.right, o.bottom, o.left);
29473         }
29474     },
29475
29476     
29477
29478     
29479     constructor : function(t, r, b, l) {
29480         var me = this;
29481         me.y = me.top = me[1] = t;
29482         me.right = r;
29483         me.bottom = b;
29484         me.x = me.left = me[0] = l;
29485     },
29486
29487     
29488     contains : function(region) {
29489         var me = this;
29490         return (region.x >= me.x &&
29491                 region.right <= me.right &&
29492                 region.y >= me.y &&
29493                 region.bottom <= me.bottom);
29494
29495     },
29496
29497     
29498     intersect : function(region) {
29499         var me = this,
29500             t = Math.max(me.y, region.y),
29501             r = Math.min(me.right, region.right),
29502             b = Math.min(me.bottom, region.bottom),
29503             l = Math.max(me.x, region.x);
29504
29505         if (b > t && r > l) {
29506             return new this.self(t, r, b, l);
29507         }
29508         else {
29509             return false;
29510         }
29511     },
29512
29513     
29514     union : function(region) {
29515         var me = this,
29516             t = Math.min(me.y, region.y),
29517             r = Math.max(me.right, region.right),
29518             b = Math.max(me.bottom, region.bottom),
29519             l = Math.min(me.x, region.x);
29520
29521         return new this.self(t, r, b, l);
29522     },
29523
29524     
29525     constrainTo : function(r) {
29526         var me = this,
29527             constrain = Ext.Number.constrain;
29528         me.top = me.y = constrain(me.top, r.y, r.bottom);
29529         me.bottom = constrain(me.bottom, r.y, r.bottom);
29530         me.left = me.x = constrain(me.left, r.x, r.right);
29531         me.right = constrain(me.right, r.x, r.right);
29532         return me;
29533     },
29534
29535     
29536     adjust : function(t, r, b, l) {
29537         var me = this;
29538         me.top = me.y += t;
29539         me.left = me.x += l;
29540         me.right += r;
29541         me.bottom += b;
29542         return me;
29543     },
29544
29545     
29546     getOutOfBoundOffset: function(axis, p) {
29547         if (!Ext.isObject(axis)) {
29548             if (axis == 'x') {
29549                 return this.getOutOfBoundOffsetX(p);
29550             } else {
29551                 return this.getOutOfBoundOffsetY(p);
29552             }
29553         } else {
29554             p = axis;
29555             var d = Ext.create('Ext.util.Offset');
29556             d.x = this.getOutOfBoundOffsetX(p.x);
29557             d.y = this.getOutOfBoundOffsetY(p.y);
29558             return d;
29559         }
29560
29561     },
29562
29563     
29564     getOutOfBoundOffsetX: function(p) {
29565         if (p <= this.x) {
29566             return this.x - p;
29567         } else if (p >= this.right) {
29568             return this.right - p;
29569         }
29570
29571         return 0;
29572     },
29573
29574     
29575     getOutOfBoundOffsetY: function(p) {
29576         if (p <= this.y) {
29577             return this.y - p;
29578         } else if (p >= this.bottom) {
29579             return this.bottom - p;
29580         }
29581
29582         return 0;
29583     },
29584
29585     
29586     isOutOfBound: function(axis, p) {
29587         if (!Ext.isObject(axis)) {
29588             if (axis == 'x') {
29589                 return this.isOutOfBoundX(p);
29590             } else {
29591                 return this.isOutOfBoundY(p);
29592             }
29593         } else {
29594             p = axis;
29595             return (this.isOutOfBoundX(p.x) || this.isOutOfBoundY(p.y));
29596         }
29597     },
29598
29599     
29600     isOutOfBoundX: function(p) {
29601         return (p < this.x || p > this.right);
29602     },
29603
29604     
29605     isOutOfBoundY: function(p) {
29606         return (p < this.y || p > this.bottom);
29607     },
29608
29609     
29610     restrict: function(axis, p, factor) {
29611         if (Ext.isObject(axis)) {
29612             var newP;
29613
29614             factor = p;
29615             p = axis;
29616
29617             if (p.copy) {
29618                 newP = p.copy();
29619             }
29620             else {
29621                 newP = {
29622                     x: p.x,
29623                     y: p.y
29624                 };
29625             }
29626
29627             newP.x = this.restrictX(p.x, factor);
29628             newP.y = this.restrictY(p.y, factor);
29629             return newP;
29630         } else {
29631             if (axis == 'x') {
29632                 return this.restrictX(p, factor);
29633             } else {
29634                 return this.restrictY(p, factor);
29635             }
29636         }
29637     },
29638
29639     
29640     restrictX : function(p, factor) {
29641         if (!factor) {
29642             factor = 1;
29643         }
29644
29645         if (p <= this.x) {
29646             p -= (p - this.x) * factor;
29647         }
29648         else if (p >= this.right) {
29649             p -= (p - this.right) * factor;
29650         }
29651         return p;
29652     },
29653
29654     
29655     restrictY : function(p, factor) {
29656         if (!factor) {
29657             factor = 1;
29658         }
29659
29660         if (p <= this.y) {
29661             p -= (p - this.y) * factor;
29662         }
29663         else if (p >= this.bottom) {
29664             p -= (p - this.bottom) * factor;
29665         }
29666         return p;
29667     },
29668
29669     
29670     getSize: function() {
29671         return {
29672             width: this.right - this.x,
29673             height: this.bottom - this.y
29674         };
29675     },
29676
29677     
29678     copy: function() {
29679         return new this.self(this.y, this.right, this.bottom, this.x);
29680     },
29681
29682     
29683     copyFrom: function(p) {
29684         var me = this;
29685         me.top = me.y = me[1] = p.y;
29686         me.right = p.right;
29687         me.bottom = p.bottom;
29688         me.left = me.x = me[0] = p.x;
29689
29690         return this;
29691     },
29692
29693     
29694     toString: function() {
29695         return "Region[" + this.top + "," + this.right + "," + this.bottom + "," + this.left + "]";
29696     },
29697
29698
29699     
29700     translateBy: function(x, y) {
29701         if (arguments.length == 1) {
29702             y = x.y;
29703             x = x.x;
29704         }
29705         var me = this;
29706         me.top = me.y += y;
29707         me.right += x;
29708         me.bottom += y;
29709         me.left = me.x += x;
29710
29711         return me;
29712     },
29713
29714     
29715     round: function() {
29716         var me = this;
29717         me.top = me.y = Math.round(me.y);
29718         me.right = Math.round(me.right);
29719         me.bottom = Math.round(me.bottom);
29720         me.left = me.x = Math.round(me.x);
29721
29722         return me;
29723     },
29724
29725     
29726     equals: function(region) {
29727         return (this.top == region.top && this.right == region.right && this.bottom == region.bottom && this.left == region.left);
29728     }
29729 });
29730
29731
29732
29733
29734
29735 Ext.define('Ext.dd.DragDropManager', {
29736     singleton: true,
29737
29738     requires: ['Ext.util.Region'],
29739
29740     uses: ['Ext.tip.QuickTipManager'],
29741
29742     
29743     alternateClassName: ['Ext.dd.DragDropMgr', 'Ext.dd.DDM'],
29744     
29745     
29746     ids: {},
29747
29748     
29749     handleIds: {},
29750
29751     
29752     dragCurrent: null,
29753
29754     
29755     dragOvers: {},
29756
29757     
29758     deltaX: 0,
29759
29760     
29761     deltaY: 0,
29762
29763     
29764     preventDefault: true,
29765
29766     
29767     stopPropagation: true,
29768
29769     
29770     initialized: false,
29771
29772     
29773     locked: false,
29774
29775     
29776     init: function() {
29777         this.initialized = true;
29778     },
29779
29780     
29781     POINT: 0,
29782
29783     
29784     INTERSECT: 1,
29785
29786     
29787     mode: 0,
29788
29789     
29790     _execOnAll: function(sMethod, args) {
29791         for (var i in this.ids) {
29792             for (var j in this.ids[i]) {
29793                 var oDD = this.ids[i][j];
29794                 if (! this.isTypeOfDD(oDD)) {
29795                     continue;
29796                 }
29797                 oDD[sMethod].apply(oDD, args);
29798             }
29799         }
29800     },
29801
29802     
29803     _onLoad: function() {
29804
29805         this.init();
29806
29807         var Event = Ext.EventManager;
29808         Event.on(document, "mouseup",   this.handleMouseUp, this, true);
29809         Event.on(document, "mousemove", this.handleMouseMove, this, true);
29810         Event.on(window,   "unload",    this._onUnload, this, true);
29811         Event.on(window,   "resize",    this._onResize, this, true);
29812         
29813
29814     },
29815
29816     
29817     _onResize: function(e) {
29818         this._execOnAll("resetConstraints", []);
29819     },
29820
29821     
29822     lock: function() { this.locked = true; },
29823
29824     
29825     unlock: function() { this.locked = false; },
29826
29827     
29828     isLocked: function() { return this.locked; },
29829
29830     
29831     locationCache: {},
29832
29833     
29834     useCache: true,
29835
29836     
29837     clickPixelThresh: 3,
29838
29839     
29840     clickTimeThresh: 350,
29841
29842     
29843     dragThreshMet: false,
29844
29845     
29846     clickTimeout: null,
29847
29848     
29849     startX: 0,
29850
29851     
29852     startY: 0,
29853
29854     
29855     regDragDrop: function(oDD, sGroup) {
29856         if (!this.initialized) { this.init(); }
29857
29858         if (!this.ids[sGroup]) {
29859             this.ids[sGroup] = {};
29860         }
29861         this.ids[sGroup][oDD.id] = oDD;
29862     },
29863
29864     
29865     removeDDFromGroup: function(oDD, sGroup) {
29866         if (!this.ids[sGroup]) {
29867             this.ids[sGroup] = {};
29868         }
29869
29870         var obj = this.ids[sGroup];
29871         if (obj && obj[oDD.id]) {
29872             delete obj[oDD.id];
29873         }
29874     },
29875
29876     
29877     _remove: function(oDD) {
29878         for (var g in oDD.groups) {
29879             if (g && this.ids[g] && this.ids[g][oDD.id]) {
29880                 delete this.ids[g][oDD.id];
29881             }
29882         }
29883         delete this.handleIds[oDD.id];
29884     },
29885
29886     
29887     regHandle: function(sDDId, sHandleId) {
29888         if (!this.handleIds[sDDId]) {
29889             this.handleIds[sDDId] = {};
29890         }
29891         this.handleIds[sDDId][sHandleId] = sHandleId;
29892     },
29893
29894     
29895     isDragDrop: function(id) {
29896         return ( this.getDDById(id) ) ? true : false;
29897     },
29898
29899     
29900     getRelated: function(p_oDD, bTargetsOnly) {
29901         var oDDs = [];
29902         for (var i in p_oDD.groups) {
29903             for (var j in this.ids[i]) {
29904                 var dd = this.ids[i][j];
29905                 if (! this.isTypeOfDD(dd)) {
29906                     continue;
29907                 }
29908                 if (!bTargetsOnly || dd.isTarget) {
29909                     oDDs[oDDs.length] = dd;
29910                 }
29911             }
29912         }
29913
29914         return oDDs;
29915     },
29916
29917     
29918     isLegalTarget: function (oDD, oTargetDD) {
29919         var targets = this.getRelated(oDD, true);
29920         for (var i=0, len=targets.length;i<len;++i) {
29921             if (targets[i].id == oTargetDD.id) {
29922                 return true;
29923             }
29924         }
29925
29926         return false;
29927     },
29928
29929     
29930     isTypeOfDD: function (oDD) {
29931         return (oDD && oDD.__ygDragDrop);
29932     },
29933
29934     
29935     isHandle: function(sDDId, sHandleId) {
29936         return ( this.handleIds[sDDId] &&
29937                         this.handleIds[sDDId][sHandleId] );
29938     },
29939
29940     
29941     getDDById: function(id) {
29942         for (var i in this.ids) {
29943             if (this.ids[i][id]) {
29944                 return this.ids[i][id];
29945             }
29946         }
29947         return null;
29948     },
29949
29950     
29951     handleMouseDown: function(e, oDD) {
29952         if(Ext.tip.QuickTipManager){
29953             Ext.tip.QuickTipManager.ddDisable();
29954         }
29955         if(this.dragCurrent){
29956             
29957             
29958             this.handleMouseUp(e);
29959         }
29960         
29961         this.currentTarget = e.getTarget();
29962         this.dragCurrent = oDD;
29963
29964         var el = oDD.getEl();
29965
29966         
29967         this.startX = e.getPageX();
29968         this.startY = e.getPageY();
29969
29970         this.deltaX = this.startX - el.offsetLeft;
29971         this.deltaY = this.startY - el.offsetTop;
29972
29973         this.dragThreshMet = false;
29974
29975         this.clickTimeout = setTimeout(
29976                 function() {
29977                     var DDM = Ext.dd.DragDropManager;
29978                     DDM.startDrag(DDM.startX, DDM.startY);
29979                 },
29980                 this.clickTimeThresh );
29981     },
29982
29983     
29984     startDrag: function(x, y) {
29985         clearTimeout(this.clickTimeout);
29986         if (this.dragCurrent) {
29987             this.dragCurrent.b4StartDrag(x, y);
29988             this.dragCurrent.startDrag(x, y);
29989         }
29990         this.dragThreshMet = true;
29991     },
29992
29993     
29994     handleMouseUp: function(e) {
29995
29996         if(Ext.tip.QuickTipManager){
29997             Ext.tip.QuickTipManager.ddEnable();
29998         }
29999         if (! this.dragCurrent) {
30000             return;
30001         }
30002
30003         clearTimeout(this.clickTimeout);
30004
30005         if (this.dragThreshMet) {
30006             this.fireEvents(e, true);
30007         } else {
30008         }
30009
30010         this.stopDrag(e);
30011
30012         this.stopEvent(e);
30013     },
30014
30015     
30016     stopEvent: function(e){
30017         if(this.stopPropagation) {
30018             e.stopPropagation();
30019         }
30020
30021         if (this.preventDefault) {
30022             e.preventDefault();
30023         }
30024     },
30025
30026     
30027     stopDrag: function(e) {
30028         
30029         if (this.dragCurrent) {
30030             if (this.dragThreshMet) {
30031                 this.dragCurrent.b4EndDrag(e);
30032                 this.dragCurrent.endDrag(e);
30033             }
30034
30035             this.dragCurrent.onMouseUp(e);
30036         }
30037
30038         this.dragCurrent = null;
30039         this.dragOvers = {};
30040     },
30041
30042     
30043     handleMouseMove: function(e) {
30044         if (! this.dragCurrent) {
30045             return true;
30046         }
30047         
30048
30049         
30050         if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
30051             this.stopEvent(e);
30052             return this.handleMouseUp(e);
30053         }
30054
30055         if (!this.dragThreshMet) {
30056             var diffX = Math.abs(this.startX - e.getPageX());
30057             var diffY = Math.abs(this.startY - e.getPageY());
30058             if (diffX > this.clickPixelThresh ||
30059                         diffY > this.clickPixelThresh) {
30060                 this.startDrag(this.startX, this.startY);
30061             }
30062         }
30063
30064         if (this.dragThreshMet) {
30065             this.dragCurrent.b4Drag(e);
30066             this.dragCurrent.onDrag(e);
30067             if(!this.dragCurrent.moveOnly){
30068                 this.fireEvents(e, false);
30069             }
30070         }
30071
30072         this.stopEvent(e);
30073
30074         return true;
30075     },
30076
30077     
30078     fireEvents: function(e, isDrop) {
30079         var dc = this.dragCurrent;
30080
30081         
30082         
30083         if (!dc || dc.isLocked()) {
30084             return;
30085         }
30086
30087         var pt = e.getPoint();
30088
30089         
30090         var oldOvers = [];
30091
30092         var outEvts   = [];
30093         var overEvts  = [];
30094         var dropEvts  = [];
30095         var enterEvts = [];
30096
30097         
30098         
30099         for (var i in this.dragOvers) {
30100
30101             var ddo = this.dragOvers[i];
30102
30103             if (! this.isTypeOfDD(ddo)) {
30104                 continue;
30105             }
30106
30107             if (! this.isOverTarget(pt, ddo, this.mode)) {
30108                 outEvts.push( ddo );
30109             }
30110
30111             oldOvers[i] = true;
30112             delete this.dragOvers[i];
30113         }
30114
30115         for (var sGroup in dc.groups) {
30116
30117             if ("string" != typeof sGroup) {
30118                 continue;
30119             }
30120
30121             for (i in this.ids[sGroup]) {
30122                 var oDD = this.ids[sGroup][i];
30123                 if (! this.isTypeOfDD(oDD)) {
30124                     continue;
30125                 }
30126
30127                 if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
30128                     if (this.isOverTarget(pt, oDD, this.mode)) {
30129                         
30130                         if (isDrop) {
30131                             dropEvts.push( oDD );
30132                         
30133                         } else {
30134
30135                             
30136                             if (!oldOvers[oDD.id]) {
30137                                 enterEvts.push( oDD );
30138                             
30139                             } else {
30140                                 overEvts.push( oDD );
30141                             }
30142
30143                             this.dragOvers[oDD.id] = oDD;
30144                         }
30145                     }
30146                 }
30147             }
30148         }
30149
30150         if (this.mode) {
30151             if (outEvts.length) {
30152                 dc.b4DragOut(e, outEvts);
30153                 dc.onDragOut(e, outEvts);
30154             }
30155
30156             if (enterEvts.length) {
30157                 dc.onDragEnter(e, enterEvts);
30158             }
30159
30160             if (overEvts.length) {
30161                 dc.b4DragOver(e, overEvts);
30162                 dc.onDragOver(e, overEvts);
30163             }
30164
30165             if (dropEvts.length) {
30166                 dc.b4DragDrop(e, dropEvts);
30167                 dc.onDragDrop(e, dropEvts);
30168             }
30169
30170         } else {
30171             
30172             var len = 0;
30173             for (i=0, len=outEvts.length; i<len; ++i) {
30174                 dc.b4DragOut(e, outEvts[i].id);
30175                 dc.onDragOut(e, outEvts[i].id);
30176             }
30177
30178             
30179             for (i=0,len=enterEvts.length; i<len; ++i) {
30180                 
30181                 dc.onDragEnter(e, enterEvts[i].id);
30182             }
30183
30184             
30185             for (i=0,len=overEvts.length; i<len; ++i) {
30186                 dc.b4DragOver(e, overEvts[i].id);
30187                 dc.onDragOver(e, overEvts[i].id);
30188             }
30189
30190             
30191             for (i=0, len=dropEvts.length; i<len; ++i) {
30192                 dc.b4DragDrop(e, dropEvts[i].id);
30193                 dc.onDragDrop(e, dropEvts[i].id);
30194             }
30195
30196         }
30197
30198         
30199         if (isDrop && !dropEvts.length) {
30200             dc.onInvalidDrop(e);
30201         }
30202
30203     },
30204
30205     
30206     getBestMatch: function(dds) {
30207         var winner = null;
30208         
30209         
30210            
30211         
30212         
30213
30214         var len = dds.length;
30215
30216         if (len == 1) {
30217             winner = dds[0];
30218         } else {
30219             
30220             for (var i=0; i<len; ++i) {
30221                 var dd = dds[i];
30222                 
30223                 
30224                 
30225                 if (dd.cursorIsOver) {
30226                     winner = dd;
30227                     break;
30228                 
30229                 } else {
30230                     if (!winner ||
30231                         winner.overlap.getArea() < dd.overlap.getArea()) {
30232                         winner = dd;
30233                     }
30234                 }
30235             }
30236         }
30237
30238         return winner;
30239     },
30240
30241     
30242     refreshCache: function(groups) {
30243         for (var sGroup in groups) {
30244             if ("string" != typeof sGroup) {
30245                 continue;
30246             }
30247             for (var i in this.ids[sGroup]) {
30248                 var oDD = this.ids[sGroup][i];
30249
30250                 if (this.isTypeOfDD(oDD)) {
30251                 
30252                     var loc = this.getLocation(oDD);
30253                     if (loc) {
30254                         this.locationCache[oDD.id] = loc;
30255                     } else {
30256                         delete this.locationCache[oDD.id];
30257                         
30258                         
30259                         
30260                     }
30261                 }
30262             }
30263         }
30264     },
30265
30266     
30267     verifyEl: function(el) {
30268         if (el) {
30269             var parent;
30270             if(Ext.isIE){
30271                 try{
30272                     parent = el.offsetParent;
30273                 }catch(e){}
30274             }else{
30275                 parent = el.offsetParent;
30276             }
30277             if (parent) {
30278                 return true;
30279             }
30280         }
30281
30282         return false;
30283     },
30284
30285     
30286     getLocation: function(oDD) {
30287         if (! this.isTypeOfDD(oDD)) {
30288             return null;
30289         }
30290
30291         
30292         
30293         if (oDD.getRegion) {
30294             return oDD.getRegion();
30295         }
30296
30297         var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
30298
30299         try {
30300             pos= Ext.core.Element.getXY(el);
30301         } catch (e) { }
30302
30303         if (!pos) {
30304             return null;
30305         }
30306
30307         x1 = pos[0];
30308         x2 = x1 + el.offsetWidth;
30309         y1 = pos[1];
30310         y2 = y1 + el.offsetHeight;
30311
30312         t = y1 - oDD.padding[0];
30313         r = x2 + oDD.padding[1];
30314         b = y2 + oDD.padding[2];
30315         l = x1 - oDD.padding[3];
30316
30317         return Ext.create('Ext.util.Region', t, r, b, l);
30318     },
30319
30320     
30321     isOverTarget: function(pt, oTarget, intersect) {
30322         
30323         var loc = this.locationCache[oTarget.id];
30324         if (!loc || !this.useCache) {
30325             loc = this.getLocation(oTarget);
30326             this.locationCache[oTarget.id] = loc;
30327
30328         }
30329
30330         if (!loc) {
30331             return false;
30332         }
30333
30334         oTarget.cursorIsOver = loc.contains( pt );
30335
30336         
30337         
30338         
30339         
30340         
30341         var dc = this.dragCurrent;
30342         if (!dc || !dc.getTargetCoord ||
30343                 (!intersect && !dc.constrainX && !dc.constrainY)) {
30344             return oTarget.cursorIsOver;
30345         }
30346
30347         oTarget.overlap = null;
30348
30349         
30350         
30351         
30352         
30353         var pos = dc.getTargetCoord(pt.x, pt.y);
30354
30355         var el = dc.getDragEl();
30356         var curRegion = Ext.create('Ext.util.Region', pos.y,
30357                                                pos.x + el.offsetWidth,
30358                                                pos.y + el.offsetHeight,
30359                                                pos.x );
30360
30361         var overlap = curRegion.intersect(loc);
30362
30363         if (overlap) {
30364             oTarget.overlap = overlap;
30365             return (intersect) ? true : oTarget.cursorIsOver;
30366         } else {
30367             return false;
30368         }
30369     },
30370
30371     
30372     _onUnload: function(e, me) {
30373         Ext.dd.DragDropManager.unregAll();
30374     },
30375
30376     
30377     unregAll: function() {
30378
30379         if (this.dragCurrent) {
30380             this.stopDrag();
30381             this.dragCurrent = null;
30382         }
30383
30384         this._execOnAll("unreg", []);
30385
30386         for (var i in this.elementCache) {
30387             delete this.elementCache[i];
30388         }
30389
30390         this.elementCache = {};
30391         this.ids = {};
30392     },
30393
30394     
30395     elementCache: {},
30396
30397     
30398     getElWrapper: function(id) {
30399         var oWrapper = this.elementCache[id];
30400         if (!oWrapper || !oWrapper.el) {
30401             oWrapper = this.elementCache[id] =
30402                 new this.ElementWrapper(Ext.getDom(id));
30403         }
30404         return oWrapper;
30405     },
30406
30407     
30408     getElement: function(id) {
30409         return Ext.getDom(id);
30410     },
30411
30412     
30413     getCss: function(id) {
30414         var el = Ext.getDom(id);
30415         return (el) ? el.style : null;
30416     },
30417
30418     
30419     ElementWrapper: function(el) {
30420             
30421             this.el = el || null;
30422             
30423             this.id = this.el && el.id;
30424             
30425             this.css = this.el && el.style;
30426         },
30427
30428     
30429     getPosX: function(el) {
30430         return Ext.core.Element.getX(el);
30431     },
30432
30433     
30434     getPosY: function(el) {
30435         return Ext.core.Element.getY(el);
30436     },
30437
30438     
30439     swapNode: function(n1, n2) {
30440         if (n1.swapNode) {
30441             n1.swapNode(n2);
30442         } else {
30443             var p = n2.parentNode;
30444             var s = n2.nextSibling;
30445
30446             if (s == n1) {
30447                 p.insertBefore(n1, n2);
30448             } else if (n2 == n1.nextSibling) {
30449                 p.insertBefore(n2, n1);
30450             } else {
30451                 n1.parentNode.replaceChild(n2, n1);
30452                 p.insertBefore(n1, s);
30453             }
30454         }
30455     },
30456
30457     
30458     getScroll: function () {
30459         var doc   = window.document,
30460             docEl = doc.documentElement,
30461             body  = doc.body,
30462             top   = 0,
30463             left  = 0;
30464             
30465         if (Ext.isGecko4) {
30466             top  = window.scrollYOffset;
30467             left = window.scrollXOffset;
30468         } else {
30469             if (docEl && (docEl.scrollTop || docEl.scrollLeft)) {
30470                 top  = docEl.scrollTop;
30471                 left = docEl.scrollLeft;
30472             } else if (body) {
30473                 top  = body.scrollTop;
30474                 left = body.scrollLeft;
30475             } 
30476         }
30477         return {
30478             top: top,
30479             left: left
30480         };
30481     },
30482
30483     
30484     getStyle: function(el, styleProp) {
30485         return Ext.fly(el).getStyle(styleProp);
30486     },
30487
30488     
30489     getScrollTop: function () {
30490         return this.getScroll().top;
30491     },
30492
30493     
30494     getScrollLeft: function () {
30495         return this.getScroll().left;
30496     },
30497
30498     
30499     moveToEl: function (moveEl, targetEl) {
30500         var aCoord = Ext.core.Element.getXY(targetEl);
30501         Ext.core.Element.setXY(moveEl, aCoord);
30502     },
30503
30504     
30505     numericSort: function(a, b) {
30506         return (a - b);
30507     },
30508
30509     
30510     _timeoutCount: 0,
30511
30512     
30513     _addListeners: function() {
30514         if ( document ) {
30515             this._onLoad();
30516         } else {
30517             if (this._timeoutCount > 2000) {
30518             } else {
30519                 setTimeout(this._addListeners, 10);
30520                 if (document && document.body) {
30521                     this._timeoutCount += 1;
30522                 }
30523             }
30524         }
30525     },
30526
30527     
30528     handleWasClicked: function(node, id) {
30529         if (this.isHandle(id, node.id)) {
30530             return true;
30531         } else {
30532             
30533             var p = node.parentNode;
30534
30535             while (p) {
30536                 if (this.isHandle(id, p.id)) {
30537                     return true;
30538                 } else {
30539                     p = p.parentNode;
30540                 }
30541             }
30542         }
30543
30544         return false;
30545     }
30546 }, function() {
30547     this._addListeners();
30548 });
30549
30550
30551
30552 Ext.define('Ext.layout.container.Box', {
30553
30554     
30555
30556     alias: ['layout.box'],
30557     extend: 'Ext.layout.container.Container',
30558     alternateClassName: 'Ext.layout.BoxLayout',
30559     
30560     requires: [
30561         'Ext.layout.container.boxOverflow.None',
30562         'Ext.layout.container.boxOverflow.Menu',
30563         'Ext.layout.container.boxOverflow.Scroller',
30564         'Ext.util.Format',
30565         'Ext.dd.DragDropManager'
30566     ],
30567
30568     
30569
30570     
30571
30572     
30573     defaultMargins: {
30574         top: 0,
30575         right: 0,
30576         bottom: 0,
30577         left: 0
30578     },
30579
30580     
30581     padding: '0',
30582     
30583     pack: 'start',
30584
30585     
30586     
30587
30588     type: 'box',
30589     scrollOffset: 0,
30590     itemCls: Ext.baseCSSPrefix + 'box-item',
30591     targetCls: Ext.baseCSSPrefix + 'box-layout-ct',
30592     innerCls: Ext.baseCSSPrefix + 'box-inner',
30593
30594     bindToOwnerCtContainer: true,
30595
30596     fixedLayout: false,
30597     
30598     
30599     
30600     availableSpaceOffset: 0,
30601     
30602     
30603     reserveOffset: true,
30604     
30605     
30606     clearInnerCtOnLayout: false,
30607
30608     flexSortFn: function (a, b) {
30609         var maxParallelPrefix = 'max' + this.parallelPrefixCap,
30610             infiniteValue = Infinity;
30611         a = a.component[maxParallelPrefix] || infiniteValue;
30612         b = b.component[maxParallelPrefix] || infiniteValue;
30613         
30614         if (!isFinite(a) && !isFinite(b)) {
30615             return false;
30616         }
30617         return a - b;
30618     },
30619
30620     
30621     minSizeSortFn: function(a, b) {
30622         return b.available - a.available;
30623     },
30624
30625     constructor: function(config) {
30626         var me = this;
30627
30628         me.callParent(arguments);
30629
30630         
30631         me.flexSortFn = Ext.Function.bind(me.flexSortFn, me);
30632
30633         me.initOverflowHandler();
30634     },
30635
30636     
30637     getChildBox: function(child) {
30638         child = child.el || this.owner.getComponent(child).el;
30639         return {
30640             left: child.getLeft(true),
30641             top: child.getTop(true),
30642             width: child.getWidth(),
30643             height: child.getHeight()
30644         };
30645     },
30646
30647     
30648     calculateChildBox: function(child) {
30649         var me = this,
30650             boxes = me.calculateChildBoxes(me.getVisibleItems(), me.getLayoutTargetSize()).boxes,
30651             ln = boxes.length,
30652             i = 0;
30653
30654         child = me.owner.getComponent(child);
30655         for (; i < ln; i++) {
30656             if (boxes[i].component === child) {
30657                 return boxes[i];
30658             }
30659         }
30660     },
30661
30662     
30663     calculateChildBoxes: function(visibleItems, targetSize) {
30664         var me = this,
30665             math = Math,
30666             mmax = math.max,
30667             infiniteValue = Infinity,
30668             undefinedValue,
30669
30670             parallelPrefix = me.parallelPrefix,
30671             parallelPrefixCap = me.parallelPrefixCap,
30672             perpendicularPrefix = me.perpendicularPrefix,
30673             perpendicularPrefixCap = me.perpendicularPrefixCap,
30674             parallelMinString = 'min' + parallelPrefixCap,
30675             perpendicularMinString = 'min' + perpendicularPrefixCap,
30676             perpendicularMaxString = 'max' + perpendicularPrefixCap,
30677
30678             parallelSize = targetSize[parallelPrefix] - me.scrollOffset,
30679             perpendicularSize = targetSize[perpendicularPrefix],
30680             padding = me.padding,
30681             parallelOffset = padding[me.parallelBefore],
30682             paddingParallel = parallelOffset + padding[me.parallelAfter],
30683             perpendicularOffset = padding[me.perpendicularLeftTop],
30684             paddingPerpendicular =  perpendicularOffset + padding[me.perpendicularRightBottom],
30685             availPerpendicularSize = mmax(0, perpendicularSize - paddingPerpendicular),
30686
30687             isStart = me.pack == 'start',
30688             isCenter = me.pack == 'center',
30689             isEnd = me.pack == 'end',
30690
30691             constrain = Ext.Number.constrain,
30692             visibleCount = visibleItems.length,
30693             nonFlexSize = 0,
30694             totalFlex = 0,
30695             desiredSize = 0,
30696             minimumSize = 0,
30697             maxSize = 0,
30698             boxes = [],
30699             minSizes = [],
30700             calculatedWidth,
30701
30702             i, child, childParallel, childPerpendicular, childMargins, childSize, minParallel, tmpObj, shortfall, 
30703             tooNarrow, availableSpace, minSize, item, length, itemIndex, box, oldSize, newSize, reduction, diff, 
30704             flexedBoxes, remainingSpace, remainingFlex, flexedSize, parallelMargins, calcs, offset, 
30705             perpendicularMargins, stretchSize;
30706
30707         
30708         for (i = 0; i < visibleCount; i++) {
30709             child = visibleItems[i];
30710             childPerpendicular = child[perpendicularPrefix];
30711             me.layoutItem(child);
30712             childMargins = child.margins;
30713             parallelMargins = childMargins[me.parallelBefore] + childMargins[me.parallelAfter];
30714
30715             
30716             tmpObj = {
30717                 component: child,
30718                 margins: childMargins
30719             };
30720
30721             
30722             if (child.flex) {
30723                 totalFlex += child.flex;
30724                 childParallel = undefinedValue;
30725             }
30726             
30727             else {
30728                 if (!(child[parallelPrefix] && childPerpendicular)) {
30729                     childSize = child.getSize();
30730                 }
30731                 childParallel = child[parallelPrefix] || childSize[parallelPrefix];
30732                 childPerpendicular = childPerpendicular || childSize[perpendicularPrefix];
30733             }
30734
30735             nonFlexSize += parallelMargins + (childParallel || 0);
30736             desiredSize += parallelMargins + (child.flex ? child[parallelMinString] || 0 : childParallel);
30737             minimumSize += parallelMargins + (child[parallelMinString] || childParallel || 0);
30738
30739             
30740             if (typeof childPerpendicular != 'number') {
30741                 
30742                 
30743                 childPerpendicular = child['get' + perpendicularPrefixCap]();
30744             }
30745
30746             
30747             maxSize = mmax(maxSize, childPerpendicular + childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom]);
30748
30749             tmpObj[parallelPrefix] = childParallel || undefinedValue;
30750             tmpObj[perpendicularPrefix] = childPerpendicular || undefinedValue;
30751             boxes.push(tmpObj);
30752         }
30753         shortfall = desiredSize - parallelSize;
30754         tooNarrow = minimumSize > parallelSize;
30755
30756         
30757         availableSpace = mmax(0, parallelSize - nonFlexSize - paddingParallel - (me.reserveOffset ? me.availableSpaceOffset : 0));
30758
30759         if (tooNarrow) {
30760             for (i = 0; i < visibleCount; i++) {
30761                 box = boxes[i];
30762                 minSize = visibleItems[i][parallelMinString] || visibleItems[i][parallelPrefix] || box[parallelPrefix];
30763                 box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
30764                 box[parallelPrefix] = minSize;
30765             }
30766         }
30767         else {
30768             
30769             
30770             if (shortfall > 0) {
30771                 
30772                 for (i = 0; i < visibleCount; i++) {
30773                     item = visibleItems[i];
30774                     minSize = item[parallelMinString] || 0;
30775
30776                     
30777                     
30778                     if (item.flex) {
30779                         box = boxes[i];
30780                         box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
30781                         box[parallelPrefix] = minSize;
30782                     }
30783                     else {
30784                         minSizes.push({
30785                             minSize: minSize,
30786                             available: boxes[i][parallelPrefix] - minSize,
30787                             index: i
30788                         });
30789                     }
30790                 }
30791
30792                 
30793                 Ext.Array.sort(minSizes, me.minSizeSortFn);
30794
30795                 
30796                 for (i = 0, length = minSizes.length; i < length; i++) {
30797                     itemIndex = minSizes[i].index;
30798
30799                     if (itemIndex == undefinedValue) {
30800                         continue;
30801                     }
30802                     item = visibleItems[itemIndex];
30803                     minSize = minSizes[i].minSize;
30804
30805                     box = boxes[itemIndex];
30806                     oldSize = box[parallelPrefix];
30807                     newSize = mmax(minSize, oldSize - math.ceil(shortfall / (length - i)));
30808                     reduction = oldSize - newSize;
30809
30810                     box.dirtySize = box.dirtySize || box[parallelPrefix] != newSize;
30811                     box[parallelPrefix] = newSize;
30812                     shortfall -= reduction;
30813                 }
30814             }
30815             else {
30816                 remainingSpace = availableSpace;
30817                 remainingFlex = totalFlex;
30818                 flexedBoxes = [];
30819
30820                 
30821                 for (i = 0; i < visibleCount; i++) {
30822                     child = visibleItems[i];
30823                     if (isStart && child.flex) {
30824                         flexedBoxes.push(boxes[Ext.Array.indexOf(visibleItems, child)]);
30825                     }
30826                 }
30827                 
30828                 
30829                 
30830                 Ext.Array.sort(flexedBoxes, me.flexSortFn);
30831
30832                 
30833                 for (i = 0; i < flexedBoxes.length; i++) {
30834                     calcs = flexedBoxes[i];
30835                     child = calcs.component;
30836                     childMargins = calcs.margins;
30837
30838                     flexedSize = math.ceil((child.flex / remainingFlex) * remainingSpace);
30839
30840                     
30841                     flexedSize = Math.max(child['min' + parallelPrefixCap] || 0, math.min(child['max' + parallelPrefixCap] || infiniteValue, flexedSize));
30842
30843                     
30844                     remainingSpace -= flexedSize;
30845                     remainingFlex -= child.flex;
30846
30847                     calcs.dirtySize = calcs.dirtySize || calcs[parallelPrefix] != flexedSize;
30848                     calcs[parallelPrefix] = flexedSize;
30849                 }
30850             }
30851         }
30852
30853         if (isCenter) {
30854             parallelOffset += availableSpace / 2;
30855         }
30856         else if (isEnd) {
30857             parallelOffset += availableSpace;
30858         }
30859
30860         
30861         
30862         
30863         
30864         if (me.owner.dock && (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) && !me.owner.width && me.direction == 'vertical') {
30865
30866             calculatedWidth = maxSize + me.owner.el.getPadding('lr') + me.owner.el.getBorderWidth('lr');
30867             if (me.owner.frameSize) {
30868                 calculatedWidth += me.owner.frameSize.left + me.owner.frameSize.right;
30869             }
30870             
30871             availPerpendicularSize = Math.min(availPerpendicularSize, targetSize.width = maxSize + padding.left + padding.right);
30872         }
30873
30874         
30875         for (i = 0; i < visibleCount; i++) {
30876             child = visibleItems[i];
30877             calcs = boxes[i];
30878
30879             childMargins = calcs.margins;
30880
30881             perpendicularMargins = childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom];
30882
30883             
30884             parallelOffset += childMargins[me.parallelBefore];
30885
30886             calcs[me.parallelBefore] = parallelOffset;
30887             calcs[me.perpendicularLeftTop] = perpendicularOffset + childMargins[me.perpendicularLeftTop];
30888
30889             if (me.align == 'stretch') {
30890                 stretchSize = constrain(availPerpendicularSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
30891                 calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
30892                 calcs[perpendicularPrefix] = stretchSize;
30893             }
30894             else if (me.align == 'stretchmax') {
30895                 stretchSize = constrain(maxSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
30896                 calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
30897                 calcs[perpendicularPrefix] = stretchSize;
30898             }
30899             else if (me.align == me.alignCenteringString) {
30900                 
30901                 
30902                 
30903                 diff = mmax(availPerpendicularSize, maxSize) - me.innerCt.getBorderWidth(me.perpendicularLT + me.perpendicularRB) - calcs[perpendicularPrefix];
30904                 if (diff > 0) {
30905                     calcs[me.perpendicularLeftTop] = perpendicularOffset + Math.round(diff / 2);
30906                 }
30907             }
30908
30909             
30910             parallelOffset += (calcs[parallelPrefix] || 0) + childMargins[me.parallelAfter];
30911         }
30912
30913         return {
30914             boxes: boxes,
30915             meta : {
30916                 calculatedWidth: calculatedWidth,
30917                 maxSize: maxSize,
30918                 nonFlexSize: nonFlexSize,
30919                 desiredSize: desiredSize,
30920                 minimumSize: minimumSize,
30921                 shortfall: shortfall,
30922                 tooNarrow: tooNarrow
30923             }
30924         };
30925     },
30926
30927     
30928     initOverflowHandler: function() {
30929         var handler = this.overflowHandler;
30930
30931         if (typeof handler == 'string') {
30932             handler = {
30933                 type: handler
30934             };
30935         }
30936
30937         var handlerType = 'None';
30938         if (handler && handler.type != undefined) {
30939             handlerType = handler.type;
30940         }
30941
30942         var constructor = Ext.layout.container.boxOverflow[handlerType];
30943         if (constructor[this.type]) {
30944             constructor = constructor[this.type];
30945         }
30946
30947         this.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.' + handlerType, this, handler);
30948     },
30949
30950     
30951     onLayout: function() {
30952         this.callParent();
30953         
30954         if (this.clearInnerCtOnLayout === true && this.adjustmentPass !== true) {
30955             this.innerCt.setSize(null, null);
30956         }
30957
30958         var me = this,
30959             targetSize = me.getLayoutTargetSize(),
30960             items = me.getVisibleItems(),
30961             calcs = me.calculateChildBoxes(items, targetSize),
30962             boxes = calcs.boxes,
30963             meta = calcs.meta,
30964             handler, method, results;
30965
30966         if (me.autoSize && calcs.meta.desiredSize) {
30967             targetSize[me.parallelPrefix] = calcs.meta.desiredSize;
30968         }
30969
30970         
30971         if (meta.shortfall > 0) {
30972             handler = me.overflowHandler;
30973             method = meta.tooNarrow ? 'handleOverflow': 'clearOverflow';
30974
30975             results = handler[method](calcs, targetSize);
30976
30977             if (results) {
30978                 if (results.targetSize) {
30979                     targetSize = results.targetSize;
30980                 }
30981
30982                 if (results.recalculate) {
30983                     items = me.getVisibleItems(owner);
30984                     calcs = me.calculateChildBoxes(items, targetSize);
30985                     boxes = calcs.boxes;
30986                 }
30987             }
30988         } else {
30989             me.overflowHandler.clearOverflow();
30990         }
30991
30992         
30993         me.layoutTargetLastSize = targetSize;
30994
30995         
30996         me.childBoxCache = calcs;
30997
30998         me.updateInnerCtSize(targetSize, calcs);
30999         me.updateChildBoxes(boxes);
31000         me.handleTargetOverflow(targetSize);
31001     },
31002
31003     
31004     updateChildBoxes: function(boxes) {
31005         var me = this,
31006             i = 0,
31007             length = boxes.length,
31008             animQueue = [],
31009             dd = Ext.dd.DDM.getDDById(me.innerCt.id), 
31010             oldBox, newBox, changed, comp, boxAnim, animCallback;
31011
31012         for (; i < length; i++) {
31013             newBox = boxes[i];
31014             comp = newBox.component;
31015
31016             
31017             
31018             if (dd && (dd.getDragEl() === comp.el.dom)) {
31019                 continue;
31020             }
31021
31022             changed = false;
31023
31024             oldBox = me.getChildBox(comp);
31025
31026             
31027             
31028             
31029             if (me.animate) {
31030                 
31031                 animCallback = me.animate.callback || me.animate;
31032                 boxAnim = {
31033                     layoutAnimation: true,  
31034                     target: comp,
31035                     from: {},
31036                     to: {},
31037                     listeners: {}
31038                 };
31039                 
31040                 
31041                 
31042                 
31043                 if (!isNaN(newBox.width) && (newBox.width != oldBox.width)) {
31044                     changed = true;
31045                     
31046                     boxAnim.to.width = newBox.width;
31047                 }
31048                 if (!isNaN(newBox.height) && (newBox.height != oldBox.height)) {
31049                     changed = true;
31050                     
31051                     boxAnim.to.height = newBox.height;
31052                 }
31053                 if (!isNaN(newBox.left) && (newBox.left != oldBox.left)) {
31054                     changed = true;
31055                     
31056                     boxAnim.to.left = newBox.left;
31057                 }
31058                 if (!isNaN(newBox.top) && (newBox.top != oldBox.top)) {
31059                     changed = true;
31060                     
31061                     boxAnim.to.top = newBox.top;
31062                 }
31063                 if (changed) {
31064                     animQueue.push(boxAnim);
31065                 }
31066             } else {
31067                 if (newBox.dirtySize) {
31068                     if (newBox.width !== oldBox.width || newBox.height !== oldBox.height) {
31069                         me.setItemSize(comp, newBox.width, newBox.height);
31070                     }
31071                 }
31072                 
31073                 if (isNaN(newBox.left) || isNaN(newBox.top)) {
31074                     continue;
31075                 }
31076                 comp.setPosition(newBox.left, newBox.top);
31077             }
31078         }
31079
31080         
31081         length = animQueue.length;
31082         if (length) {
31083
31084             
31085             
31086             var afterAnimate = function(anim) {
31087                 
31088                 length -= 1;
31089                 if (!length) {
31090                     me.layoutBusy = false;
31091                     if (Ext.isFunction(animCallback)) {
31092                         animCallback();
31093                     }
31094                 }
31095             };
31096
31097             var beforeAnimate = function() {
31098                 me.layoutBusy = true;
31099             };
31100
31101             
31102             for (i = 0, length = animQueue.length; i < length; i++) {
31103                 boxAnim = animQueue[i];
31104
31105                 
31106                 boxAnim.listeners.afteranimate = afterAnimate;
31107
31108                 
31109                 if (!i) {
31110                     boxAnim.listeners.beforeanimate = beforeAnimate;
31111                 }
31112                 if (me.animate.duration) {
31113                     boxAnim.duration = me.animate.duration;
31114                 }
31115                 comp = boxAnim.target;
31116                 delete boxAnim.target;
31117                 
31118                 comp.stopAnimation();
31119                 comp.animate(boxAnim);
31120             }
31121         }
31122     },
31123
31124     
31125     updateInnerCtSize: function(tSize, calcs) {
31126         var me = this,
31127             mmax = Math.max,
31128             align = me.align,
31129             padding = me.padding,
31130             width = tSize.width,
31131             height = tSize.height,
31132             meta = calcs.meta,
31133             innerCtWidth,
31134             innerCtHeight;
31135
31136         if (me.direction == 'horizontal') {
31137             innerCtWidth = width;
31138             innerCtHeight = meta.maxSize + padding.top + padding.bottom + me.innerCt.getBorderWidth('tb');
31139
31140             if (align == 'stretch') {
31141                 innerCtHeight = height;
31142             }
31143             else if (align == 'middle') {
31144                 innerCtHeight = mmax(height, innerCtHeight);
31145             }
31146         } else {
31147             innerCtHeight = height;
31148             innerCtWidth = meta.maxSize + padding.left + padding.right + me.innerCt.getBorderWidth('lr');
31149
31150             if (align == 'stretch') {
31151                 innerCtWidth = width;
31152             }
31153             else if (align == 'center') {
31154                 innerCtWidth = mmax(width, innerCtWidth);
31155             }
31156         }
31157         me.getRenderTarget().setSize(innerCtWidth || undefined, innerCtHeight || undefined);
31158
31159         
31160         
31161         if (meta.calculatedWidth && me.owner.el.getWidth() > meta.calculatedWidth) {
31162             me.owner.el.setWidth(meta.calculatedWidth);
31163         }
31164
31165         if (me.innerCt.dom.scrollTop) {
31166             me.innerCt.dom.scrollTop = 0;
31167         }
31168     },
31169
31170     
31171     handleTargetOverflow: function(previousTargetSize) {
31172         var target = this.getTarget(),
31173             overflow = target.getStyle('overflow'),
31174             newTargetSize;
31175
31176         if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
31177             newTargetSize = this.getLayoutTargetSize();
31178             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height) {
31179                 this.adjustmentPass = true;
31180                 this.onLayout();
31181                 return true;
31182             }
31183         }
31184
31185         delete this.adjustmentPass;
31186     },
31187
31188     
31189     isValidParent : function(item, target, position) {
31190         
31191         
31192         var itemEl = item.el ? item.el.dom : Ext.getDom(item);
31193         return (itemEl && this.innerCt && itemEl.parentNode === this.innerCt.dom) || false;
31194     },
31195
31196     
31197     
31198     getRenderTarget: function() {
31199         if (!this.innerCt) {
31200             
31201             this.innerCt = this.getTarget().createChild({
31202                 cls: this.innerCls,
31203                 role: 'presentation'
31204             });
31205             this.padding = Ext.util.Format.parseBox(this.padding);
31206         }
31207         return this.innerCt;
31208     },
31209
31210     
31211     renderItem: function(item, target) {
31212         this.callParent(arguments);
31213         var me = this,
31214             itemEl = item.getEl(),
31215             style = itemEl.dom.style,
31216             margins = item.margins || item.margin;
31217
31218         
31219         if (margins) {
31220             if (Ext.isString(margins) || Ext.isNumber(margins)) {
31221                 margins = Ext.util.Format.parseBox(margins);
31222             } else {
31223                 Ext.applyIf(margins, {top: 0, right: 0, bottom: 0, left: 0});
31224             }
31225         } else {
31226             margins = Ext.apply({}, me.defaultMargins);
31227         }
31228
31229         
31230         margins.top    += itemEl.getMargin('t');
31231         margins.right  += itemEl.getMargin('r');
31232         margins.bottom += itemEl.getMargin('b');
31233         margins.left   += itemEl.getMargin('l');
31234         style.marginTop = style.marginRight = style.marginBottom = style.marginLeft = '0';
31235
31236         
31237         item.margins = margins;
31238     },
31239
31240     
31241     destroy: function() {
31242         Ext.destroy(this.overflowHandler);
31243         this.callParent(arguments);
31244     }
31245 });
31246
31247 Ext.define('Ext.layout.container.HBox', {
31248
31249     
31250
31251     alias: ['layout.hbox'],
31252     extend: 'Ext.layout.container.Box',
31253     alternateClassName: 'Ext.layout.HBoxLayout',
31254     
31255     
31256
31257     
31258     align: 'top', 
31259
31260     //@private
31261
31262     alignCenteringString: 'middle',
31263
31264     type : 'hbox',
31265
31266     direction: 'horizontal',
31267
31268     
31269     parallelSizeIndex: 0,
31270     perpendicularSizeIndex: 1,
31271
31272     parallelPrefix: 'width',
31273     parallelPrefixCap: 'Width',
31274     parallelLT: 'l',
31275     parallelRB: 'r',
31276     parallelBefore: 'left',
31277     parallelBeforeCap: 'Left',
31278     parallelAfter: 'right',
31279     parallelPosition: 'x',
31280
31281     perpendicularPrefix: 'height',
31282     perpendicularPrefixCap: 'Height',
31283     perpendicularLT: 't',
31284     perpendicularRB: 'b',
31285     perpendicularLeftTop: 'top',
31286     perpendicularRightBottom: 'bottom',
31287     perpendicularPosition: 'y'
31288 });
31289
31290 Ext.define('Ext.layout.container.VBox', {
31291
31292     
31293
31294     alias: ['layout.vbox'],
31295     extend: 'Ext.layout.container.Box',
31296     alternateClassName: 'Ext.layout.VBoxLayout',
31297     
31298     
31299
31300     
31301     align : 'left', 
31302
31303     //@private
31304
31305     alignCenteringString: 'center',
31306
31307     type: 'vbox',
31308
31309     direction: 'vertical',
31310
31311     
31312     parallelSizeIndex: 1,
31313     perpendicularSizeIndex: 0,
31314
31315     parallelPrefix: 'height',
31316     parallelPrefixCap: 'Height',
31317     parallelLT: 't',
31318     parallelRB: 'b',
31319     parallelBefore: 'top',
31320     parallelBeforeCap: 'Top',
31321     parallelAfter: 'bottom',
31322     parallelPosition: 'y',
31323
31324     perpendicularPrefix: 'width',
31325     perpendicularPrefixCap: 'Width',
31326     perpendicularLT: 'l',
31327     perpendicularRB: 'r',
31328     perpendicularLeftTop: 'left',
31329     perpendicularRightBottom: 'right',
31330     perpendicularPosition: 'x'
31331 });
31332
31333 Ext.define('Ext.FocusManager', {
31334     singleton: true,
31335     alternateClassName: 'Ext.FocusMgr',
31336
31337     mixins: {
31338         observable: 'Ext.util.Observable'
31339     },
31340
31341     requires: [
31342         'Ext.ComponentManager',
31343         'Ext.ComponentQuery',
31344         'Ext.util.HashMap',
31345         'Ext.util.KeyNav'
31346     ],
31347
31348     
31349     enabled: false,
31350
31351     
31352
31353     focusElementCls: Ext.baseCSSPrefix + 'focus-element',
31354
31355     focusFrameCls: Ext.baseCSSPrefix + 'focus-frame',
31356
31357     
31358     whitelist: [
31359         'textfield'
31360     ],
31361
31362     tabIndexWhitelist: [
31363         'a',
31364         'button',
31365         'embed',
31366         'frame',
31367         'iframe',
31368         'img',
31369         'input',
31370         'object',
31371         'select',
31372         'textarea'
31373     ],
31374
31375     constructor: function() {
31376         var me = this,
31377             CQ = Ext.ComponentQuery;
31378
31379         me.addEvents(
31380             
31381             'beforecomponentfocus',
31382
31383             
31384             'componentfocus',
31385
31386             
31387             'disable',
31388
31389             
31390             'enable'
31391         );
31392
31393         
31394         
31395         me.keyNav = Ext.create('Ext.util.KeyNav', Ext.getDoc(), {
31396             disabled: true,
31397             scope: me,
31398
31399             backspace: me.focusLast,
31400             enter: me.navigateIn,
31401             esc: me.navigateOut,
31402             tab: me.navigateSiblings
31403
31404             
31405             
31406             
31407             
31408             
31409             
31410         });
31411
31412         me.focusData = {};
31413         me.subscribers = Ext.create('Ext.util.HashMap');
31414         me.focusChain = {};
31415
31416         
31417         Ext.apply(CQ.pseudos, {
31418             focusable: function(cmps) {
31419                 var len = cmps.length,
31420                     results = [],
31421                     i = 0,
31422                     c,
31423
31424                     isFocusable = function(x) {
31425                         return x && x.focusable !== false && CQ.is(x, '[rendered]:not([destroying]):not([isDestroyed]):not([disabled]){isVisible(true)}{el && c.el.dom && c.el.isVisible()}');
31426                     };
31427
31428                 for (; i < len; i++) {
31429                     c = cmps[i];
31430                     if (isFocusable(c)) {
31431                         results.push(c);
31432                     }
31433                 }
31434
31435                 return results;
31436             },
31437
31438             nextFocus: function(cmps, idx, step) {
31439                 step = step || 1;
31440                 idx = parseInt(idx, 10);
31441
31442                 var len = cmps.length,
31443                     i = idx + step,
31444                     c;
31445
31446                 for (; i != idx; i += step) {
31447                     if (i >= len) {
31448                         i = 0;
31449                     } else if (i < 0) {
31450                         i = len - 1;
31451                     }
31452
31453                     c = cmps[i];
31454                     if (CQ.is(c, ':focusable')) {
31455                         return [c];
31456                     } else if (c.placeholder && CQ.is(c.placeholder, ':focusable')) {
31457                         return [c.placeholder];
31458                     }
31459                 }
31460
31461                 return [];
31462             },
31463
31464             prevFocus: function(cmps, idx) {
31465                 return this.nextFocus(cmps, idx, -1);
31466             },
31467
31468             root: function(cmps) {
31469                 var len = cmps.length,
31470                     results = [],
31471                     i = 0,
31472                     c;
31473
31474                 for (; i < len; i++) {
31475                     c = cmps[i];
31476                     if (!c.ownerCt) {
31477                         results.push(c);
31478                     }
31479                 }
31480
31481                 return results;
31482             }
31483         });
31484     },
31485
31486     
31487     addXTypeToWhitelist: function(xtype) {
31488         var me = this;
31489
31490         if (Ext.isArray(xtype)) {
31491             Ext.Array.forEach(xtype, me.addXTypeToWhitelist, me);
31492             return;
31493         }
31494
31495         if (!Ext.Array.contains(me.whitelist, xtype)) {
31496             me.whitelist.push(xtype);
31497         }
31498     },
31499
31500     clearComponent: function(cmp) {
31501         clearTimeout(this.cmpFocusDelay);
31502         if (!cmp.isDestroyed) {
31503             cmp.blur();
31504         }
31505     },
31506
31507     
31508     disable: function() {
31509         var me = this;
31510
31511         if (!me.enabled) {
31512             return;
31513         }
31514
31515         delete me.options;
31516         me.enabled = false;
31517
31518         Ext.ComponentManager.all.un('add', me.onComponentCreated, me);
31519
31520         me.removeDOM();
31521
31522         
31523         me.keyNav.disable();
31524
31525         
31526         me.setFocusAll(false);
31527
31528         me.fireEvent('disable', me);
31529     },
31530
31531     
31532     enable: function(options) {
31533         var me = this;
31534
31535         if (options === true) {
31536             options = { focusFrame: true };
31537         }
31538         me.options = options = options || {};
31539
31540         if (me.enabled) {
31541             return;
31542         }
31543
31544         
31545         Ext.ComponentManager.all.on('add', me.onComponentCreated, me);
31546
31547         me.initDOM(options);
31548
31549         
31550         me.keyNav.enable();
31551
31552         
31553         me.setFocusAll(true, options);
31554
31555         
31556         me.focusEl.focus();
31557         delete me.focusedCmp;
31558
31559         me.enabled = true;
31560         me.fireEvent('enable', me);
31561     },
31562
31563     focusLast: function(e) {
31564         var me = this;
31565
31566         if (me.isWhitelisted(me.focusedCmp)) {
31567             return true;
31568         }
31569
31570         
31571         if (me.previousFocusedCmp) {
31572             me.previousFocusedCmp.focus();
31573         }
31574     },
31575
31576     getRootComponents: function() {
31577         var me = this,
31578             CQ = Ext.ComponentQuery,
31579             inline = CQ.query(':focusable:root:not([floating])'),
31580             floating = CQ.query(':focusable:root[floating]');
31581
31582         
31583         
31584         floating.sort(function(a, b) {
31585             return a.el.getZIndex() > b.el.getZIndex();
31586         });
31587
31588         return floating.concat(inline);
31589     },
31590
31591     initDOM: function(options) {
31592         var me = this,
31593             sp = '&#160',
31594             cls = me.focusFrameCls;
31595
31596         if (!Ext.isReady) {
31597             Ext.onReady(me.initDOM, me);
31598             return;
31599         }
31600
31601         
31602         if (!me.focusEl) {
31603             me.focusEl = Ext.getBody().createChild({
31604                 tabIndex: '-1',
31605                 cls: me.focusElementCls,
31606                 html: sp
31607             });
31608         }
31609
31610         
31611         if (!me.focusFrame && options.focusFrame) {
31612             me.focusFrame = Ext.getBody().createChild({
31613                 cls: cls,
31614                 children: [
31615                     { cls: cls + '-top' },
31616                     { cls: cls + '-bottom' },
31617                     { cls: cls + '-left' },
31618                     { cls: cls + '-right' }
31619                 ],
31620                 style: 'top: -100px; left: -100px;'
31621             });
31622             me.focusFrame.setVisibilityMode(Ext.core.Element.DISPLAY);
31623             me.focusFrameWidth = me.focusFrame.child('.' + cls + '-top').getHeight();
31624             me.focusFrame.hide().setLeftTop(0, 0);
31625         }
31626     },
31627
31628     isWhitelisted: function(cmp) {
31629         return cmp && Ext.Array.some(this.whitelist, function(x) {
31630             return cmp.isXType(x);
31631         });
31632     },
31633
31634     navigateIn: function(e) {
31635         var me = this,
31636             focusedCmp = me.focusedCmp,
31637             rootCmps,
31638             firstChild;
31639
31640         if (!focusedCmp) {
31641             
31642             rootCmps = me.getRootComponents();
31643             if (rootCmps.length) {
31644                 rootCmps[0].focus();
31645             }
31646         } else {
31647             
31648             
31649             firstChild = Ext.ComponentQuery.query('>:focusable', focusedCmp)[0];
31650             if (firstChild) {
31651                 firstChild.focus();
31652             } else {
31653                 
31654                 if (Ext.isFunction(focusedCmp.onClick)) {
31655                     e.button = 0;
31656                     focusedCmp.onClick(e);
31657                     focusedCmp.focus();
31658                 }
31659             }
31660         }
31661     },
31662
31663     navigateOut: function(e) {
31664         var me = this,
31665             parent;
31666
31667         if (!me.focusedCmp || !(parent = me.focusedCmp.up(':focusable'))) {
31668             me.focusEl.focus();
31669             return;
31670         }
31671
31672         parent.focus();
31673     },
31674
31675     navigateSiblings: function(e, source, parent) {
31676         var me = this,
31677             src = source || me,
31678             key = e.getKey(),
31679             EO = Ext.EventObject,
31680             goBack = e.shiftKey || key == EO.LEFT || key == EO.UP,
31681             checkWhitelist = key == EO.LEFT || key == EO.RIGHT || key == EO.UP || key == EO.DOWN,
31682             nextSelector = goBack ? 'prev' : 'next',
31683             idx, next, focusedCmp;
31684
31685         focusedCmp = (src.focusedCmp && src.focusedCmp.comp) || src.focusedCmp;
31686         if (!focusedCmp && !parent) {
31687             return;
31688         }
31689
31690         if (checkWhitelist && me.isWhitelisted(focusedCmp)) {
31691             return true;
31692         }
31693
31694         parent = parent || focusedCmp.up();
31695         if (parent) {
31696             idx = focusedCmp ? Ext.Array.indexOf(parent.getRefItems(), focusedCmp) : -1;
31697             next = Ext.ComponentQuery.query('>:' + nextSelector + 'Focus(' + idx + ')', parent)[0];
31698             if (next && focusedCmp !== next) {
31699                 next.focus();
31700                 return next;
31701             }
31702         }
31703     },
31704
31705     onComponentBlur: function(cmp, e) {
31706         var me = this;
31707
31708         if (me.focusedCmp === cmp) {
31709             me.previousFocusedCmp = cmp;
31710             delete me.focusedCmp;
31711         }
31712
31713         if (me.focusFrame) {
31714             me.focusFrame.hide();
31715         }
31716     },
31717
31718     onComponentCreated: function(hash, id, cmp) {
31719         this.setFocus(cmp, true, this.options);
31720     },
31721
31722     onComponentDestroy: function(cmp) {
31723         this.setFocus(cmp, false);
31724     },
31725
31726     onComponentFocus: function(cmp, e) {
31727         var me = this,
31728             chain = me.focusChain;
31729
31730         if (!Ext.ComponentQuery.is(cmp, ':focusable')) {
31731             me.clearComponent(cmp);
31732
31733             
31734             
31735             
31736             
31737             if (chain[cmp.id]) {
31738                 return;
31739             }
31740
31741             
31742             var parent = cmp.up();
31743             if (parent) {
31744                 
31745                 
31746                 
31747                 chain[cmp.id] = true;
31748                 parent.focus();
31749             }
31750
31751             return;
31752         }
31753
31754         
31755         me.focusChain = {};
31756
31757         
31758         
31759         clearTimeout(me.cmpFocusDelay);
31760         if (arguments.length !== 2) {
31761             me.cmpFocusDelay = Ext.defer(me.onComponentFocus, 90, me, [cmp, e]);
31762             return;
31763         }
31764
31765         if (me.fireEvent('beforecomponentfocus', me, cmp, me.previousFocusedCmp) === false) {
31766             me.clearComponent(cmp);
31767             return;
31768         }
31769
31770         me.focusedCmp = cmp;
31771
31772         
31773         if (me.shouldShowFocusFrame(cmp)) {
31774             var cls = '.' + me.focusFrameCls + '-',
31775                 ff = me.focusFrame,
31776                 fw = me.focusFrameWidth,
31777                 box = cmp.el.getPageBox(),
31778
31779             
31780             
31781             
31782                 bt = box.top,
31783                 bl = box.left,
31784                 bw = box.width,
31785                 bh = box.height,
31786                 ft = ff.child(cls + 'top'),
31787                 fb = ff.child(cls + 'bottom'),
31788                 fl = ff.child(cls + 'left'),
31789                 fr = ff.child(cls + 'right');
31790
31791             ft.setWidth(bw - 2).setLeftTop(bl + 1, bt);
31792             fb.setWidth(bw - 2).setLeftTop(bl + 1, bt + bh - fw);
31793             fl.setHeight(bh - 2).setLeftTop(bl, bt + 1);
31794             fr.setHeight(bh - 2).setLeftTop(bl + bw - fw, bt + 1);
31795
31796             ff.show();
31797         }
31798
31799         me.fireEvent('componentfocus', me, cmp, me.previousFocusedCmp);
31800     },
31801
31802     onComponentHide: function(cmp) {
31803         var me = this,
31804             CQ = Ext.ComponentQuery,
31805             cmpHadFocus = false,
31806             focusedCmp,
31807             parent;
31808
31809         if (me.focusedCmp) {
31810             focusedCmp = CQ.query('[id=' + me.focusedCmp.id + ']', cmp)[0];
31811             cmpHadFocus = me.focusedCmp.id === cmp.id || focusedCmp;
31812
31813             if (focusedCmp) {
31814                 me.clearComponent(focusedCmp);
31815             }
31816         }
31817
31818         me.clearComponent(cmp);
31819
31820         if (cmpHadFocus) {
31821             parent = CQ.query('^:focusable', cmp)[0];
31822             if (parent) {
31823                 parent.focus();
31824             }
31825         }
31826     },
31827
31828     removeDOM: function() {
31829         var me = this;
31830
31831         
31832         
31833         if (me.enabled || me.subscribers.length) {
31834             return;
31835         }
31836
31837         Ext.destroy(
31838             me.focusEl,
31839             me.focusFrame
31840         );
31841         delete me.focusEl;
31842         delete me.focusFrame;
31843         delete me.focusFrameWidth;
31844     },
31845
31846     
31847     removeXTypeFromWhitelist: function(xtype) {
31848         var me = this;
31849
31850         if (Ext.isArray(xtype)) {
31851             Ext.Array.forEach(xtype, me.removeXTypeFromWhitelist, me);
31852             return;
31853         }
31854
31855         Ext.Array.remove(me.whitelist, xtype);
31856     },
31857
31858     setFocus: function(cmp, focusable, options) {
31859         var me = this,
31860             el, dom, data,
31861
31862             needsTabIndex = function(n) {
31863                 return !Ext.Array.contains(me.tabIndexWhitelist, n.tagName.toLowerCase())
31864                     && n.tabIndex <= 0;
31865             };
31866
31867         options = options || {};
31868
31869         
31870         if (!cmp.rendered) {
31871             cmp.on('afterrender', Ext.pass(me.setFocus, arguments, me), me, { single: true });
31872             return;
31873         }
31874
31875         el = cmp.getFocusEl();
31876         dom = el.dom;
31877
31878         
31879         if ((focusable && !me.focusData[cmp.id]) || (!focusable && me.focusData[cmp.id])) {
31880             if (focusable) {
31881                 data = {
31882                     focusFrame: options.focusFrame
31883                 };
31884
31885                 
31886                 
31887                 
31888                 
31889                 if (needsTabIndex(dom)) {
31890                     data.tabIndex = dom.tabIndex;
31891                     dom.tabIndex = -1;
31892                 }
31893
31894                 el.on({
31895                     focus: data.focusFn = Ext.bind(me.onComponentFocus, me, [cmp], 0),
31896                     blur: data.blurFn = Ext.bind(me.onComponentBlur, me, [cmp], 0),
31897                     scope: me
31898                 });
31899                 cmp.on({
31900                     hide: me.onComponentHide,
31901                     close: me.onComponentHide,
31902                     beforedestroy: me.onComponentDestroy,
31903                     scope: me
31904                 });
31905
31906                 me.focusData[cmp.id] = data;
31907             } else {
31908                 data = me.focusData[cmp.id];
31909                 if ('tabIndex' in data) {
31910                     dom.tabIndex = data.tabIndex;
31911                 }
31912                 el.un('focus', data.focusFn, me);
31913                 el.un('blur', data.blurFn, me);
31914                 cmp.un('hide', me.onComponentHide, me);
31915                 cmp.un('close', me.onComponentHide, me);
31916                 cmp.un('beforedestroy', me.onComponentDestroy, me);
31917
31918                 delete me.focusData[cmp.id];
31919             }
31920         }
31921     },
31922
31923     setFocusAll: function(focusable, options) {
31924         var me = this,
31925             cmps = Ext.ComponentManager.all.getArray(),
31926             len = cmps.length,
31927             cmp,
31928             i = 0;
31929
31930         for (; i < len; i++) {
31931             me.setFocus(cmps[i], focusable, options);
31932         }
31933     },
31934
31935     setupSubscriberKeys: function(container, keys) {
31936         var me = this,
31937             el = container.getFocusEl(),
31938             scope = keys.scope,
31939             handlers = {
31940                 backspace: me.focusLast,
31941                 enter: me.navigateIn,
31942                 esc: me.navigateOut,
31943                 scope: me
31944             },
31945
31946             navSiblings = function(e) {
31947                 if (me.focusedCmp === container) {
31948                     
31949                     
31950                     
31951                     return me.navigateSiblings(e, me, container);
31952                 } else {
31953                     return me.navigateSiblings(e);
31954                 }
31955             };
31956
31957         Ext.iterate(keys, function(key, cb) {
31958             handlers[key] = function(e) {
31959                 var ret = navSiblings(e);
31960
31961                 if (Ext.isFunction(cb) && cb.call(scope || container, e, ret) === true) {
31962                     return true;
31963                 }
31964
31965                 return ret;
31966             };
31967         }, me);
31968
31969         return Ext.create('Ext.util.KeyNav', el, handlers);
31970     },
31971
31972     shouldShowFocusFrame: function(cmp) {
31973         var me = this,
31974             opts = me.options || {};
31975
31976         if (!me.focusFrame || !cmp) {
31977             return false;
31978         }
31979
31980         
31981         if (opts.focusFrame) {
31982             return true;
31983         }
31984
31985         if (me.focusData[cmp.id].focusFrame) {
31986             return true;
31987         }
31988
31989         return false;
31990     },
31991
31992     
31993     subscribe: function(container, options) {
31994         var me = this,
31995             EA = Ext.Array,
31996             data = {},
31997             subs = me.subscribers,
31998
31999             
32000             
32001             
32002             safeSetFocus = function(cmp) {
32003                 if (cmp.isContainer && !subs.containsKey(cmp.id)) {
32004                     EA.forEach(cmp.query('>'), safeSetFocus);
32005                     me.setFocus(cmp, true, options);
32006                     cmp.on('add', data.onAdd, me);
32007                 } else if (!cmp.isContainer) {
32008                     me.setFocus(cmp, true, options);
32009                 }
32010             };
32011
32012         
32013         if (!container || !container.isContainer) {
32014             return;
32015         }
32016
32017         if (!container.rendered) {
32018             container.on('afterrender', Ext.pass(me.subscribe, arguments, me), me, { single: true });
32019             return;
32020         }
32021
32022         
32023         me.initDOM(options);
32024
32025         
32026         data.keyNav = me.setupSubscriberKeys(container, options.keys);
32027
32028         
32029         
32030         
32031         
32032         data.onAdd = function(ct, cmp, idx) {
32033             safeSetFocus(cmp);
32034         };
32035         container.on('beforedestroy', me.unsubscribe, me);
32036
32037         
32038         safeSetFocus(container);
32039
32040         
32041         subs.add(container.id, data);
32042     },
32043
32044     
32045     unsubscribe: function(container) {
32046         var me = this,
32047             EA = Ext.Array,
32048             subs = me.subscribers,
32049             data,
32050
32051             
32052             
32053             
32054             safeSetFocus = function(cmp) {
32055                 if (cmp.isContainer && !subs.containsKey(cmp.id)) {
32056                     EA.forEach(cmp.query('>'), safeSetFocus);
32057                     me.setFocus(cmp, false);
32058                     cmp.un('add', data.onAdd, me);
32059                 } else if (!cmp.isContainer) {
32060                     me.setFocus(cmp, false);
32061                 }
32062             };
32063
32064         if (!container || !subs.containsKey(container.id)) {
32065             return;
32066         }
32067
32068         data = subs.get(container.id);
32069         data.keyNav.destroy();
32070         container.un('beforedestroy', me.unsubscribe, me);
32071         subs.removeAtKey(container.id);
32072         safeSetFocus(container);
32073         me.removeDOM();
32074     }
32075 });
32076
32077 Ext.define('Ext.toolbar.Toolbar', {
32078     extend: 'Ext.container.Container',
32079     requires: [
32080         'Ext.toolbar.Fill',
32081         'Ext.layout.container.HBox',
32082         'Ext.layout.container.VBox',
32083         'Ext.FocusManager'
32084     ],
32085     uses: [
32086         'Ext.toolbar.Separator'
32087     ],
32088     alias: 'widget.toolbar',
32089     alternateClassName: 'Ext.Toolbar',
32090     
32091     isToolbar: true,
32092     baseCls  : Ext.baseCSSPrefix + 'toolbar',
32093     ariaRole : 'toolbar',
32094     
32095     defaultType: 'button',
32096     
32097     
32098     vertical: false,
32099
32100     
32101
32102     
32103     enableOverflow: false,
32104     
32105     
32106     trackMenus: true,
32107     
32108     itemCls: Ext.baseCSSPrefix + 'toolbar-item',
32109     
32110     initComponent: function() {
32111         var me = this,
32112             keys;
32113
32114         
32115         if (!me.layout && me.enableOverflow) {
32116             me.layout = { overflowHandler: 'Menu' };
32117         }
32118         
32119         if (me.dock === 'right' || me.dock === 'left') {
32120             me.vertical = true;
32121         }
32122
32123         me.layout = Ext.applyIf(Ext.isString(me.layout) ? {
32124             type: me.layout
32125         } : me.layout || {}, {
32126             type: me.vertical ? 'vbox' : 'hbox',
32127             align: me.vertical ? 'stretchmax' : 'middle'
32128         });
32129         
32130         if (me.vertical) {
32131             me.addClsWithUI('vertical');
32132         }
32133         
32134         
32135         if (me.ui === 'footer') {
32136             me.ignoreBorderManagement = true;
32137         }
32138         
32139         me.callParent();
32140
32141         
32142         me.addEvents('overflowchange');
32143         
32144         
32145         keys = me.vertical ? ['up', 'down'] : ['left', 'right'];
32146         Ext.FocusManager.subscribe(me, {
32147             keys: keys
32148         });
32149     },
32150
32151     
32152
32153     
32154     lookupComponent: function(c) {
32155         if (Ext.isString(c)) {
32156             var shortcut = Ext.toolbar.Toolbar.shortcuts[c];
32157             if (shortcut) {
32158                 c = {
32159                     xtype: shortcut
32160                 };
32161             } else {
32162                 c = {
32163                     xtype: 'tbtext',
32164                     text: c
32165                 };
32166             }
32167             this.applyDefaults(c);
32168         }
32169         return this.callParent(arguments);
32170     },
32171
32172     
32173     applyDefaults: function(c) {
32174         if (!Ext.isString(c)) {
32175             c = this.callParent(arguments);
32176             var d = this.internalDefaults;
32177             if (c.events) {
32178                 Ext.applyIf(c.initialConfig, d);
32179                 Ext.apply(c, d);
32180             } else {
32181                 Ext.applyIf(c, d);
32182             }
32183         }
32184         return c;
32185     },
32186
32187     
32188     trackMenu: function(item, remove) {
32189         if (this.trackMenus && item.menu) {
32190             var method = remove ? 'mun' : 'mon',
32191                 me = this;
32192
32193             me[method](item, 'menutriggerover', me.onButtonTriggerOver, me);
32194             me[method](item, 'menushow', me.onButtonMenuShow, me);
32195             me[method](item, 'menuhide', me.onButtonMenuHide, me);
32196         }
32197     },
32198
32199     
32200     constructButton: function(item) {
32201         return item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
32202     },
32203
32204     
32205     onBeforeAdd: function(component) {
32206         if (component.is('field') || (component.is('button') && this.ui != 'footer')) {
32207             component.ui = component.ui + '-toolbar';
32208         }
32209         
32210         
32211         if (component instanceof Ext.toolbar.Separator) {
32212             component.setUI((this.vertical) ? 'vertical' : 'horizontal');
32213         }
32214         
32215         this.callParent(arguments);
32216     },
32217
32218     
32219     onAdd: function(component) {
32220         this.callParent(arguments);
32221
32222         this.trackMenu(component);
32223         if (this.disabled) {
32224             component.disable();
32225         }
32226     },
32227
32228     
32229     onRemove: function(c) {
32230         this.callParent(arguments);
32231         this.trackMenu(c, true);
32232     },
32233
32234     
32235     onButtonTriggerOver: function(btn){
32236         if (this.activeMenuBtn && this.activeMenuBtn != btn) {
32237             this.activeMenuBtn.hideMenu();
32238             btn.showMenu();
32239             this.activeMenuBtn = btn;
32240         }
32241     },
32242
32243     
32244     onButtonMenuShow: function(btn) {
32245         this.activeMenuBtn = btn;
32246     },
32247
32248     
32249     onButtonMenuHide: function(btn) {
32250         delete this.activeMenuBtn;
32251     }
32252 }, function() {
32253     this.shortcuts = {
32254         '-' : 'tbseparator',
32255         ' ' : 'tbspacer',
32256         '->': 'tbfill'
32257     };
32258 });
32259
32260 Ext.define('Ext.panel.AbstractPanel', {
32261
32262     
32263
32264     extend: 'Ext.container.Container',
32265
32266     requires: ['Ext.util.MixedCollection', 'Ext.core.Element', 'Ext.toolbar.Toolbar'],
32267
32268     
32269
32270     
32271     baseCls : Ext.baseCSSPrefix + 'panel',
32272
32273     
32274
32275     
32276     
32277     
32278     
32279     
32280
32281     isPanel: true,
32282
32283     componentLayout: 'dock',
32284
32285     renderTpl: ['<div class="{baseCls}-body<tpl if="bodyCls"> {bodyCls}</tpl> {baseCls}-body-{ui}<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl></tpl>"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>'],
32286
32287     
32288     
32289      
32290     border: true,
32291
32292     initComponent : function() {
32293         var me = this;
32294         
32295         me.addEvents(
32296             
32297             'bodyresize'
32298             
32299             
32300             
32301             
32302         );
32303
32304         Ext.applyIf(me.renderSelectors, {
32305             body: '.' + me.baseCls + '-body'
32306         });
32307         
32308         
32309         
32310         
32311         if (me.frame && me.border && me.bodyBorder === undefined) {
32312             me.bodyBorder = false;
32313         }
32314         if (me.frame && me.border && (me.bodyBorder === false || me.bodyBorder === 0)) {
32315             me.manageBodyBorders = true;
32316         }
32317         
32318         me.callParent();
32319     },
32320
32321     
32322     initItems : function() {
32323         var me = this,
32324             items = me.dockedItems;
32325             
32326         me.callParent();
32327         me.dockedItems = Ext.create('Ext.util.MixedCollection', false, me.getComponentId);
32328         if (items) {
32329             me.addDocked(items);
32330         }
32331     },
32332
32333     
32334     getDockedComponent: function(comp) {
32335         if (Ext.isObject(comp)) {
32336             comp = comp.getItemId();
32337         }
32338         return this.dockedItems.get(comp);
32339     },
32340
32341     
32342     getComponent: function(comp) {
32343         var component = this.callParent(arguments);
32344         if (component === undefined && !Ext.isNumber(comp)) {
32345             
32346             component = this.getDockedComponent(comp);
32347         }
32348         return component;
32349     },
32350
32351     
32352     initBodyStyles: function() {
32353         var me = this,
32354             bodyStyle = me.bodyStyle,
32355             styles = [],
32356             Element = Ext.core.Element,
32357             prop;
32358
32359         if (Ext.isFunction(bodyStyle)) {
32360             bodyStyle = bodyStyle();
32361         }
32362         if (Ext.isString(bodyStyle)) {
32363             styles = bodyStyle.split(';');
32364         } else {
32365             for (prop in bodyStyle) {
32366                 if (bodyStyle.hasOwnProperty(prop)) {
32367                     styles.push(prop + ':' + bodyStyle[prop]);
32368                 }
32369             }
32370         }
32371
32372         if (me.bodyPadding !== undefined) {
32373             styles.push('padding: ' + Element.unitizeBox((me.bodyPadding === true) ? 5 : me.bodyPadding));
32374         }
32375         if (me.frame && me.bodyBorder) {
32376             if (!Ext.isNumber(me.bodyBorder)) {
32377                 me.bodyBorder = 1;
32378             }
32379             styles.push('border-width: ' + Element.unitizeBox(me.bodyBorder));
32380         }
32381         delete me.bodyStyle;
32382         return styles.length ? styles.join(';') : undefined;
32383     },
32384     
32385     
32386     initBodyCls: function() {
32387         var me = this,
32388             cls = '',
32389             bodyCls = me.bodyCls;
32390         
32391         if (bodyCls) {
32392             Ext.each(bodyCls, function(v) {
32393                 cls += " " + v;
32394             });
32395             delete me.bodyCls;
32396         }
32397         return cls.length > 0 ? cls : undefined;
32398     },
32399     
32400     
32401     initRenderData: function() {
32402         return Ext.applyIf(this.callParent(), {
32403             bodyStyle: this.initBodyStyles(),
32404             bodyCls: this.initBodyCls()
32405         });
32406     },
32407
32408     
32409     addDocked : function(items, pos) {
32410         var me = this,
32411             i = 0,
32412             item, length;
32413
32414         items = me.prepareItems(items);
32415         length = items.length;
32416
32417         for (; i < length; i++) {
32418             item = items[i];
32419             item.dock = item.dock || 'top';
32420
32421             
32422             if (me.border === false) {
32423                 
32424             }
32425
32426             if (pos !== undefined) {
32427                 me.dockedItems.insert(pos + i, item);
32428             }
32429             else {
32430                 me.dockedItems.add(item);
32431             }
32432             item.onAdded(me, i);
32433             me.onDockedAdd(item);
32434         }
32435         if (me.rendered) {
32436             me.doComponentLayout();
32437         }
32438         return items;
32439     },
32440
32441     
32442     onDockedAdd : Ext.emptyFn,
32443     onDockedRemove : Ext.emptyFn,
32444
32445     
32446     insertDocked : function(pos, items) {
32447         this.addDocked(items, pos);
32448     },
32449
32450     
32451     removeDocked : function(item, autoDestroy) {
32452         var me = this,
32453             layout,
32454             hasLayout;
32455             
32456         if (!me.dockedItems.contains(item)) {
32457             return item;
32458         }
32459
32460         layout = me.componentLayout;
32461         hasLayout = layout && me.rendered;
32462
32463         if (hasLayout) {
32464             layout.onRemove(item);
32465         }
32466
32467         me.dockedItems.remove(item);
32468         item.onRemoved();
32469         me.onDockedRemove(item);
32470
32471         if (autoDestroy === true || (autoDestroy !== false && me.autoDestroy)) {
32472             item.destroy();
32473         }
32474
32475         if (hasLayout && !autoDestroy) {
32476             layout.afterRemove(item);
32477         }
32478         
32479         if (!this.destroying) {
32480             me.doComponentLayout();
32481         }
32482
32483         return item;
32484     },
32485
32486     
32487     getDockedItems : function(cqSelector) {
32488         var me = this,
32489             
32490             
32491             defaultWeight = { top: 1, left: 3, right: 5, bottom: 7 },
32492             dockedItems;
32493
32494         if (me.dockedItems && me.dockedItems.items.length) {
32495             
32496             if (cqSelector) {
32497                 dockedItems = Ext.ComponentQuery.query(cqSelector, me.dockedItems.items);
32498             } else {
32499                 dockedItems = me.dockedItems.items.slice();
32500             }
32501
32502             Ext.Array.sort(dockedItems, function(a, b) {
32503                 
32504                 
32505                 var aw = a.weight || defaultWeight[a.dock],
32506                     bw = b.weight || defaultWeight[b.dock];
32507                 if (Ext.isNumber(aw) && Ext.isNumber(bw)) {
32508                     return aw - bw;
32509                 }
32510                 return 0;
32511             });
32512             
32513             return dockedItems;
32514         }
32515         return [];
32516     },
32517     
32518     
32519     addUIClsToElement: function(cls, force) {
32520         var me = this;
32521         
32522         me.callParent(arguments);
32523         
32524         if (!force && me.rendered) {
32525             me.body.addCls(Ext.baseCSSPrefix + cls);
32526             me.body.addCls(me.baseCls + '-body-' + cls);
32527             me.body.addCls(me.baseCls + '-body-' + me.ui + '-' + cls);
32528         }
32529     },
32530     
32531     
32532     removeUIClsFromElement: function(cls, force) {
32533         var me = this;
32534         
32535         me.callParent(arguments);
32536         
32537         if (!force && me.rendered) {
32538             me.body.removeCls(Ext.baseCSSPrefix + cls);
32539             me.body.removeCls(me.baseCls + '-body-' + cls);
32540             me.body.removeCls(me.baseCls + '-body-' + me.ui + '-' + cls);
32541         }
32542     },
32543     
32544     
32545     addUIToElement: function(force) {
32546         var me = this;
32547         
32548         me.callParent(arguments);
32549         
32550         if (!force && me.rendered) {
32551             me.body.addCls(me.baseCls + '-body-' + me.ui);
32552         }
32553     },
32554     
32555     
32556     removeUIFromElement: function() {
32557         var me = this;
32558         
32559         me.callParent(arguments);
32560         
32561         if (me.rendered) {
32562             me.body.removeCls(me.baseCls + '-body-' + me.ui);
32563         }
32564     },
32565
32566     
32567     getTargetEl : function() {
32568         return this.body;
32569     },
32570
32571     getRefItems: function(deep) {
32572         var items = this.callParent(arguments),
32573             
32574             dockedItems = this.getDockedItems(deep ? '*,* *' : undefined),
32575             ln = dockedItems.length,
32576             i = 0,
32577             item;
32578         
32579         
32580         for (; i < ln; i++) {
32581             item = dockedItems[i];
32582             if (item.dock === 'right' || item.dock === 'bottom') {
32583                 break;
32584             }
32585         }
32586         
32587         
32588         
32589         
32590         return dockedItems.splice(0, i).concat(items).concat(dockedItems);
32591     },
32592
32593     beforeDestroy: function(){
32594         var docked = this.dockedItems,
32595             c;
32596
32597         if (docked) {
32598             while ((c = docked.first())) {
32599                 this.removeDocked(c, true);
32600             }
32601         }
32602         this.callParent();
32603     },
32604     
32605     setBorder: function(border) {
32606         var me = this;
32607         me.border = (border !== undefined) ? border : true;
32608         if (me.rendered) {
32609             me.doComponentLayout();
32610         }
32611     }
32612 });
32613
32614 Ext.define('Ext.panel.Header', {
32615     extend: 'Ext.container.Container',
32616     uses: ['Ext.panel.Tool', 'Ext.draw.Component', 'Ext.util.CSS'],
32617     alias: 'widget.header',
32618
32619     isHeader       : true,
32620     defaultType    : 'tool',
32621     indicateDrag   : false,
32622     weight         : -1,
32623
32624     renderTpl: ['<div class="{baseCls}-body<tpl if="bodyCls"> {bodyCls}</tpl><tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl></tpl>"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>'],
32625
32626     initComponent: function() {
32627         var me = this,
32628             rule,
32629             style,
32630             titleTextEl,
32631             ui;
32632
32633         me.indicateDragCls = me.baseCls + '-draggable';
32634         me.title = me.title || '&#160;';
32635         me.tools = me.tools || [];
32636         me.items = me.items || [];
32637         me.orientation = me.orientation || 'horizontal';
32638         me.dock = (me.dock) ? me.dock : (me.orientation == 'horizontal') ? 'top' : 'left';
32639
32640         
32641         
32642         me.addClsWithUI(me.orientation);
32643         me.addClsWithUI(me.dock);
32644
32645         Ext.applyIf(me.renderSelectors, {
32646             body: '.' + me.baseCls + '-body'
32647         });
32648
32649         
32650         if (!Ext.isEmpty(me.iconCls)) {
32651             me.initIconCmp();
32652             me.items.push(me.iconCmp);
32653         }
32654
32655         
32656         if (me.orientation == 'vertical') {
32657             
32658             if (Ext.isIE6 || Ext.isIE7) {
32659                 me.width = this.width || 24;
32660             } else if (Ext.isIEQuirks) {
32661                 me.width = this.width || 25;
32662             }
32663
32664             me.layout = {
32665                 type : 'vbox',
32666                 align: 'center',
32667                 clearInnerCtOnLayout: true,
32668                 bindToOwnerCtContainer: false
32669             };
32670             me.textConfig = {
32671                 cls: me.baseCls + '-text',
32672                 type: 'text',
32673                 text: me.title,
32674                 rotate: {
32675                     degrees: 90
32676                 }
32677             };
32678             ui = me.ui;
32679             if (Ext.isArray(ui)) {
32680                 ui = ui[0];
32681             }
32682             rule = Ext.util.CSS.getRule('.' + me.baseCls + '-text-' + ui);
32683             if (rule) {
32684                 style = rule.style;
32685             }
32686             if (style) {
32687                 Ext.apply(me.textConfig, {
32688                     'font-family': style.fontFamily,
32689                     'font-weight': style.fontWeight,
32690                     'font-size': style.fontSize,
32691                     fill: style.color
32692                 });
32693             }
32694             me.titleCmp = Ext.create('Ext.draw.Component', {
32695                 ariaRole  : 'heading',
32696                 focusable: false,
32697                 viewBox: false,
32698                 autoSize: true,
32699                 margins: '5 0 0 0',
32700                 items: [ me.textConfig ],
32701                 renderSelectors: {
32702                     textEl: '.' + me.baseCls + '-text'
32703                 }
32704             });
32705         } else {
32706             me.layout = {
32707                 type : 'hbox',
32708                 align: 'middle',
32709                 clearInnerCtOnLayout: true,
32710                 bindToOwnerCtContainer: false
32711             };
32712             me.titleCmp = Ext.create('Ext.Component', {
32713                 xtype     : 'component',
32714                 ariaRole  : 'heading',
32715                 focusable: false,
32716                 renderTpl : ['<span class="{cls}-text {cls}-text-{ui}">{title}</span>'],
32717                 renderData: {
32718                     title: me.title,
32719                     cls  : me.baseCls,
32720                     ui   : me.ui
32721                 },
32722                 renderSelectors: {
32723                     textEl: '.' + me.baseCls + '-text'
32724                 }
32725             });
32726         }
32727         me.items.push(me.titleCmp);
32728
32729         
32730         me.items.push({
32731             xtype: 'component',
32732             html : '&nbsp;',
32733             flex : 1,
32734             focusable: false
32735         });
32736
32737         
32738         me.items = me.items.concat(me.tools);
32739         this.callParent();
32740     },
32741
32742     initIconCmp: function() {
32743         this.iconCmp = Ext.create('Ext.Component', {
32744             focusable: false,
32745             renderTpl : ['<img alt="" src="{blank}" class="{cls}-icon {iconCls}"/>'],
32746             renderData: {
32747                 blank  : Ext.BLANK_IMAGE_URL,
32748                 cls    : this.baseCls,
32749                 iconCls: this.iconCls,
32750                 orientation: this.orientation
32751             },
32752             renderSelectors: {
32753                 iconEl: '.' + this.baseCls + '-icon'
32754             },
32755             iconCls: this.iconCls
32756         });
32757     },
32758
32759     afterRender: function() {
32760         var me = this;
32761
32762         me.el.unselectable();
32763         if (me.indicateDrag) {
32764             me.el.addCls(me.indicateDragCls);
32765         }
32766         me.mon(me.el, {
32767             click: me.onClick,
32768             scope: me
32769         });
32770         me.callParent();
32771     },
32772
32773     afterLayout: function() {
32774         var me = this;
32775         me.callParent(arguments);
32776
32777         
32778         if (Ext.isIE7) {
32779             me.el.repaint();
32780         }
32781     },
32782
32783     
32784     addUIClsToElement: function(cls, force) {
32785         var me = this;
32786
32787         me.callParent(arguments);
32788
32789         if (!force && me.rendered) {
32790             me.body.addCls(me.baseCls + '-body-' + cls);
32791             me.body.addCls(me.baseCls + '-body-' + me.ui + '-' + cls);
32792         }
32793     },
32794
32795     
32796     removeUIClsFromElement: function(cls, force) {
32797         var me = this;
32798
32799         me.callParent(arguments);
32800
32801         if (!force && me.rendered) {
32802             me.body.removeCls(me.baseCls + '-body-' + cls);
32803             me.body.removeCls(me.baseCls + '-body-' + me.ui + '-' + cls);
32804         }
32805     },
32806
32807     
32808     addUIToElement: function(force) {
32809         var me = this;
32810
32811         me.callParent(arguments);
32812
32813         if (!force && me.rendered) {
32814             me.body.addCls(me.baseCls + '-body-' + me.ui);
32815         }
32816
32817         if (!force && me.titleCmp && me.titleCmp.rendered && me.titleCmp.textEl) {
32818             me.titleCmp.textEl.addCls(me.baseCls + '-text-' + me.ui);
32819         }
32820     },
32821
32822     
32823     removeUIFromElement: function() {
32824         var me = this;
32825
32826         me.callParent(arguments);
32827
32828         if (me.rendered) {
32829             me.body.removeCls(me.baseCls + '-body-' + me.ui);
32830         }
32831
32832         if (me.titleCmp && me.titleCmp.rendered && me.titleCmp.textEl) {
32833             me.titleCmp.textEl.removeCls(me.baseCls + '-text-' + me.ui);
32834         }
32835     },
32836
32837     onClick: function(e) {
32838         if (!e.getTarget(Ext.baseCSSPrefix + 'tool')) {
32839             this.fireEvent('click', e);
32840         }
32841     },
32842
32843     getTargetEl: function() {
32844         return this.body || this.frameBody || this.el;
32845     },
32846
32847     
32848     setTitle: function(title) {
32849         var me = this;
32850         if (me.rendered) {
32851             if (me.titleCmp.rendered) {
32852                 if (me.titleCmp.surface) {
32853                     me.title = title || '';
32854                     var sprite = me.titleCmp.surface.items.items[0],
32855                         surface = me.titleCmp.surface;
32856
32857                     surface.remove(sprite);
32858                     me.textConfig.type = 'text';
32859                     me.textConfig.text = title;
32860                     sprite = surface.add(me.textConfig);
32861                     sprite.setAttributes({
32862                         rotate: {
32863                             degrees: 90
32864                         }
32865                     }, true);
32866                     me.titleCmp.autoSizeSurface();
32867                 } else {
32868                     me.title = title || '&#160;';
32869                     me.titleCmp.textEl.update(me.title);
32870                 }
32871             } else {
32872                 me.titleCmp.on({
32873                     render: function() {
32874                         me.setTitle(title);
32875                     },
32876                     single: true
32877                 });
32878             }
32879         } else {
32880             me.on({
32881                 render: function() {
32882                     me.layout.layout();
32883                     me.setTitle(title);
32884                 },
32885                 single: true
32886             });
32887         }
32888     },
32889
32890     
32891     setIconCls: function(cls) {
32892         this.iconCls = cls;
32893         if (!this.iconCmp) {
32894             this.initIconCmp();
32895             this.insert(0, this.iconCmp);
32896         }
32897         else {
32898             if (!cls || !cls.length) {
32899                 this.iconCmp.destroy();
32900             }
32901             else {
32902                 var iconCmp = this.iconCmp,
32903                     el      = iconCmp.iconEl;
32904
32905                 el.removeCls(iconCmp.iconCls);
32906                 el.addCls(cls);
32907                 iconCmp.iconCls = cls;
32908             }
32909         }
32910     },
32911
32912     
32913     addTool: function(tool) {
32914         this.tools.push(this.add(tool));
32915     },
32916
32917     
32918     onAdd: function(component, index) {
32919         this.callParent([arguments]);
32920         if (component instanceof Ext.panel.Tool) {
32921             component.bindTo(this.ownerCt);
32922             this.tools[component.type] = component;
32923         }
32924     }
32925 });
32926
32927
32928 Ext.define('Ext.fx.target.Element', {
32929
32930     
32931     
32932     extend: 'Ext.fx.target.Target',
32933     
32934     
32935
32936     type: 'element',
32937
32938     getElVal: function(el, attr, val) {
32939         if (val == undefined) {
32940             if (attr === 'x') {
32941                 val = el.getX();
32942             }
32943             else if (attr === 'y') {
32944                 val = el.getY();
32945             }
32946             else if (attr === 'scrollTop') {
32947                 val = el.getScroll().top;
32948             }
32949             else if (attr === 'scrollLeft') {
32950                 val = el.getScroll().left;
32951             }
32952             else if (attr === 'height') {
32953                 val = el.getHeight();
32954             }
32955             else if (attr === 'width') {
32956                 val = el.getWidth();
32957             }
32958             else {
32959                 val = el.getStyle(attr);
32960             }
32961         }
32962         return val;
32963     },
32964
32965     getAttr: function(attr, val) {
32966         var el = this.target;
32967         return [[ el, this.getElVal(el, attr, val)]];
32968     },
32969
32970     setAttr: function(targetData) {
32971         var target = this.target,
32972             ln = targetData.length,
32973             attrs, attr, o, i, j, ln2, element, value;
32974         for (i = 0; i < ln; i++) {
32975             attrs = targetData[i].attrs;
32976             for (attr in attrs) {
32977                 if (attrs.hasOwnProperty(attr)) {
32978                     ln2 = attrs[attr].length;
32979                     for (j = 0; j < ln2; j++) {
32980                         o = attrs[attr][j];
32981                         element = o[0];
32982                         value = o[1];
32983                         if (attr === 'x') {
32984                             element.setX(value);
32985                         }
32986                         else if (attr === 'y') {
32987                             element.setY(value);
32988                         }
32989                         else if (attr === 'scrollTop') {
32990                             element.scrollTo('top', value);
32991                         }
32992                         else if (attr === 'scrollLeft') {
32993                             element.scrollTo('left',value);
32994                         }
32995                         else {
32996                             element.setStyle(attr, value);
32997                         }
32998                     }
32999                 }
33000             }
33001         }
33002     }
33003 });
33004
33005
33006 Ext.define('Ext.fx.target.CompositeElement', {
33007
33008     
33009
33010     extend: 'Ext.fx.target.Element',
33011
33012     
33013
33014     isComposite: true,
33015     
33016     constructor: function(target) {
33017         target.id = target.id || Ext.id(null, 'ext-composite-');
33018         this.callParent([target]);
33019     },
33020
33021     getAttr: function(attr, val) {
33022         var out = [],
33023             target = this.target;
33024         target.each(function(el) {
33025             out.push([el, this.getElVal(el, attr, val)]);
33026         }, this);
33027         return out;
33028     }
33029 });
33030
33031
33032
33033 Ext.define('Ext.fx.Manager', {
33034
33035     
33036
33037     singleton: true,
33038
33039     requires: ['Ext.util.MixedCollection',
33040                'Ext.fx.target.Element',
33041                'Ext.fx.target.CompositeElement',
33042                'Ext.fx.target.Sprite',
33043                'Ext.fx.target.CompositeSprite',
33044                'Ext.fx.target.Component'],
33045
33046     mixins: {
33047         queue: 'Ext.fx.Queue'
33048     },
33049
33050     
33051
33052     constructor: function() {
33053         this.items = Ext.create('Ext.util.MixedCollection');
33054         this.mixins.queue.constructor.call(this);
33055
33056         
33057         
33058         
33059         
33060         
33061         
33062         
33063         
33064         
33065         
33066         
33067         
33068         
33069         
33070         
33071         
33072         
33073     },
33074
33075     
33076     interval: 16,
33077
33078     
33079     forceJS: true,
33080
33081     
33082     createTarget: function(target) {
33083         var me = this,
33084             useCSS3 = !me.forceJS && Ext.supports.Transitions,
33085             targetObj;
33086
33087         me.useCSS3 = useCSS3;
33088
33089         
33090         if (Ext.isString(target)) {
33091             target = Ext.get(target);
33092         }
33093         
33094         if (target && target.tagName) {
33095             target = Ext.get(target);
33096             targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
33097             me.targets.add(targetObj);
33098             return targetObj;
33099         }
33100         if (Ext.isObject(target)) {
33101             
33102             if (target.dom) {
33103                 targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
33104             }
33105             
33106             else if (target.isComposite) {
33107                 targetObj = Ext.create('Ext.fx.target.' + 'CompositeElement' + (useCSS3 ? 'CSS' : ''), target);
33108             }
33109             
33110             else if (target.isSprite) {
33111                 targetObj = Ext.create('Ext.fx.target.Sprite', target);
33112             }
33113             
33114             else if (target.isCompositeSprite) {
33115                 targetObj = Ext.create('Ext.fx.target.CompositeSprite', target);
33116             }
33117             
33118             else if (target.isComponent) {
33119                 targetObj = Ext.create('Ext.fx.target.Component', target);
33120             }
33121             else if (target.isAnimTarget) {
33122                 return target;
33123             }
33124             else {
33125                 return null;
33126             }
33127             me.targets.add(targetObj);
33128             return targetObj;
33129         }
33130         else {
33131             return null;
33132         }
33133     },
33134
33135     
33136     addAnim: function(anim) {
33137         var items = this.items,
33138             task = this.task;
33139         
33140         
33141         
33142         
33143         
33144         
33145         
33146         
33147         
33148         
33149         
33150         
33151
33152         items.add(anim);
33153
33154         
33155         if (!task && items.length) {
33156             task = this.task = {
33157                 run: this.runner,
33158                 interval: this.interval,
33159                 scope: this
33160             };
33161             Ext.TaskManager.start(task);
33162         }
33163
33164         
33165         
33166         
33167         
33168     },
33169
33170     
33171     removeAnim: function(anim) {
33172         
33173         var items = this.items,
33174             task = this.task;
33175         items.remove(anim);
33176         
33177         if (task && !items.length) {
33178             Ext.TaskManager.stop(task);
33179             delete this.task;
33180         }
33181     },
33182
33183     
33184     startingFilter: function(o) {
33185         return o.paused === false && o.running === false && o.iterations > 0;
33186     },
33187
33188     
33189     runningFilter: function(o) {
33190         return o.paused === false && o.running === true && o.isAnimator !== true;
33191     },
33192
33193     
33194     runner: function() {
33195         var me = this,
33196             items = me.items;
33197
33198         me.targetData = {};
33199         me.targetArr = {};
33200
33201         
33202         me.timestamp = new Date();
33203
33204         
33205         items.filterBy(me.startingFilter).each(me.startAnim, me);
33206
33207         
33208         items.filterBy(me.runningFilter).each(me.runAnim, me);
33209
33210         
33211         me.applyPendingAttrs();
33212     },
33213
33214     
33215     startAnim: function(anim) {
33216         anim.start(this.timestamp);
33217     },
33218
33219     
33220     runAnim: function(anim) {
33221         if (!anim) {
33222             return;
33223         }
33224         var me = this,
33225             targetId = anim.target.getId(),
33226             useCSS3 = me.useCSS3 && anim.target.type == 'element',
33227             elapsedTime = me.timestamp - anim.startTime,
33228             target, o;
33229
33230         this.collectTargetData(anim, elapsedTime, useCSS3);
33231
33232         
33233         
33234         if (useCSS3) {
33235             
33236             anim.target.setAttr(me.targetData[targetId], true);
33237
33238             
33239             me.targetData[targetId] = [];
33240             me.collectTargetData(anim, anim.duration, useCSS3);
33241
33242             
33243             anim.paused = true;
33244
33245             target = anim.target.target;
33246             
33247             if (anim.target.isComposite) {
33248                 target = anim.target.target.last();
33249             }
33250
33251             
33252             o = {};
33253             o[Ext.supports.CSS3TransitionEnd] = anim.lastFrame;
33254             o.scope = anim;
33255             o.single = true;
33256             target.on(o);
33257         }
33258         
33259         else if (elapsedTime >= anim.duration) {
33260             me.applyPendingAttrs(true);
33261             delete me.targetData[targetId];
33262             delete me.targetArr[targetId];
33263             anim.lastFrame();
33264         }
33265     },
33266
33267     
33268     collectTargetData: function(anim, elapsedTime, useCSS3) {
33269         var targetId = anim.target.getId(),
33270             targetData = this.targetData[targetId],
33271             data;
33272         
33273         if (!targetData) {
33274             targetData = this.targetData[targetId] = [];
33275             this.targetArr[targetId] = anim.target;
33276         }
33277
33278         data = {
33279             duration: anim.duration,
33280             easing: (useCSS3 && anim.reverse) ? anim.easingFn.reverse().toCSS3() : anim.easing,
33281             attrs: {}
33282         };
33283         Ext.apply(data.attrs, anim.runAnim(elapsedTime));
33284         targetData.push(data);
33285     },
33286
33287     
33288     applyPendingAttrs: function(isLastFrame) {
33289         var targetData = this.targetData,
33290             targetArr = this.targetArr,
33291             targetId;
33292         for (targetId in targetData) {
33293             if (targetData.hasOwnProperty(targetId)) {
33294                 targetArr[targetId].setAttr(targetData[targetId], false, isLastFrame);
33295             }
33296         }
33297     }
33298 });
33299
33300
33301 Ext.define('Ext.fx.Animator', {
33302
33303     
33304
33305     mixins: {
33306         observable: 'Ext.util.Observable'
33307     },
33308
33309     requires: ['Ext.fx.Manager'],
33310
33311     
33312
33313     isAnimator: true,
33314
33315     
33316     duration: 250,
33317
33318     
33319     delay: 0,
33320
33321     
33322     delayStart: 0,
33323
33324     
33325     dynamic: false,
33326
33327     
33328     easing: 'ease',
33329
33330     
33331     running: false,
33332
33333     
33334     paused: false,
33335
33336     
33337     damper: 1,
33338
33339     
33340     iterations: 1,
33341
33342     
33343     currentIteration: 0,
33344
33345     
33346     keyframeStep: 0,
33347
33348     
33349     animKeyFramesRE: /^(from|to|\d+%?)$/,
33350
33351     
33352
33353      
33354     constructor: function(config) {
33355         var me = this;
33356         config = Ext.apply(me, config || {});
33357         me.config = config;
33358         me.id = Ext.id(null, 'ext-animator-');
33359         me.addEvents(
33360             
33361             'beforeanimate',
33362             
33363             'keyframe',
33364             
33365             'afteranimate'
33366         );
33367         me.mixins.observable.constructor.call(me, config);
33368         me.timeline = [];
33369         me.createTimeline(me.keyframes);
33370         if (me.target) {
33371             me.applyAnimator(me.target);
33372             Ext.fx.Manager.addAnim(me);
33373         }
33374     },
33375
33376     
33377     sorter: function (a, b) {
33378         return a.pct - b.pct;
33379     },
33380
33381     
33382     createTimeline: function(keyframes) {
33383         var me = this,
33384             attrs = [],
33385             to = me.to || {},
33386             duration = me.duration,
33387             prevMs, ms, i, ln, pct, anim, nextAnim, attr;
33388
33389         for (pct in keyframes) {
33390             if (keyframes.hasOwnProperty(pct) && me.animKeyFramesRE.test(pct)) {
33391                 attr = {attrs: Ext.apply(keyframes[pct], to)};
33392                 
33393                 if (pct == "from") {
33394                     pct = 0;
33395                 }
33396                 else if (pct == "to") {
33397                     pct = 100;
33398                 }
33399                 
33400                 attr.pct = parseInt(pct, 10);
33401                 attrs.push(attr);
33402             }
33403         }
33404         
33405         Ext.Array.sort(attrs, me.sorter);
33406         
33407         
33408         
33409         
33410
33411         ln = attrs.length;
33412         for (i = 0; i < ln; i++) {
33413             prevMs = (attrs[i - 1]) ? duration * (attrs[i - 1].pct / 100) : 0;
33414             ms = duration * (attrs[i].pct / 100);
33415             me.timeline.push({
33416                 duration: ms - prevMs,
33417                 attrs: attrs[i].attrs
33418             });
33419         }
33420     },
33421
33422     
33423     applyAnimator: function(target) {
33424         var me = this,
33425             anims = [],
33426             timeline = me.timeline,
33427             reverse = me.reverse,
33428             ln = timeline.length,
33429             anim, easing, damper, initial, attrs, lastAttrs, i;
33430
33431         if (me.fireEvent('beforeanimate', me) !== false) {
33432             for (i = 0; i < ln; i++) {
33433                 anim = timeline[i];
33434                 attrs = anim.attrs;
33435                 easing = attrs.easing || me.easing;
33436                 damper = attrs.damper || me.damper;
33437                 delete attrs.easing;
33438                 delete attrs.damper;
33439                 anim = Ext.create('Ext.fx.Anim', {
33440                     target: target,
33441                     easing: easing,
33442                     damper: damper,
33443                     duration: anim.duration,
33444                     paused: true,
33445                     to: attrs
33446                 });
33447                 anims.push(anim);
33448             }
33449             me.animations = anims;
33450             me.target = anim.target;
33451             for (i = 0; i < ln - 1; i++) {
33452                 anim = anims[i];
33453                 anim.nextAnim = anims[i + 1];
33454                 anim.on('afteranimate', function() {
33455                     this.nextAnim.paused = false;
33456                 });
33457                 anim.on('afteranimate', function() {
33458                     this.fireEvent('keyframe', this, ++this.keyframeStep);
33459                 }, me);
33460             }
33461             anims[ln - 1].on('afteranimate', function() {
33462                 this.lastFrame();
33463             }, me);
33464         }
33465     },
33466
33467     
33468     start: function(startTime) {
33469         var me = this,
33470             delay = me.delay,
33471             delayStart = me.delayStart,
33472             delayDelta;
33473         if (delay) {
33474             if (!delayStart) {
33475                 me.delayStart = startTime;
33476                 return;
33477             }
33478             else {
33479                 delayDelta = startTime - delayStart;
33480                 if (delayDelta < delay) {
33481                     return;
33482                 }
33483                 else {
33484                     
33485                     startTime = new Date(delayStart.getTime() + delay);
33486                 }
33487             }
33488         }
33489         if (me.fireEvent('beforeanimate', me) !== false) {
33490             me.startTime = startTime;
33491             me.running = true;
33492             me.animations[me.keyframeStep].paused = false;
33493         }
33494     },
33495
33496     
33497     lastFrame: function() {
33498         var me = this,
33499             iter = me.iterations,
33500             iterCount = me.currentIteration;
33501
33502         iterCount++;
33503         if (iterCount < iter) {
33504             me.startTime = new Date();
33505             me.currentIteration = iterCount;
33506             me.keyframeStep = 0;
33507             me.applyAnimator(me.target);
33508             me.animations[me.keyframeStep].paused = false;
33509         }
33510         else {
33511             me.currentIteration = 0;
33512             me.end();
33513         }
33514     },
33515
33516     
33517     end: function() {
33518         var me = this;
33519         me.fireEvent('afteranimate', me, me.startTime, new Date() - me.startTime);
33520     }
33521 });
33522
33523 Ext.ns('Ext.fx');
33524
33525 Ext.require('Ext.fx.CubicBezier', function() {
33526     var math = Math,
33527         pi = math.PI,
33528         pow = math.pow,
33529         sin = math.sin,
33530         sqrt = math.sqrt,
33531         abs = math.abs,
33532         backInSeed = 1.70158;
33533     Ext.fx.Easing = {
33534         
33535         
33536         
33537         
33538         
33539         
33540         
33541         
33542     };
33543
33544     Ext.apply(Ext.fx.Easing, {
33545         linear: function(n) {
33546             return n;
33547         },
33548         ease: function(n) {
33549             var q = 0.07813 - n / 2,
33550                 alpha = -0.25,
33551                 Q = sqrt(0.0066 + q * q),
33552                 x = Q - q,
33553                 X = pow(abs(x), 1/3) * (x < 0 ? -1 : 1),
33554                 y = -Q - q,
33555                 Y = pow(abs(y), 1/3) * (y < 0 ? -1 : 1),
33556                 t = X + Y + 0.25;
33557             return pow(1 - t, 2) * 3 * t * 0.1 + (1 - t) * 3 * t * t + t * t * t;
33558         },
33559         easeIn: function (n) {
33560             return pow(n, 1.7);
33561         },
33562         easeOut: function (n) {
33563             return pow(n, 0.48);
33564         },
33565         easeInOut: function(n) {
33566             var q = 0.48 - n / 1.04,
33567                 Q = sqrt(0.1734 + q * q),
33568                 x = Q - q,
33569                 X = pow(abs(x), 1/3) * (x < 0 ? -1 : 1),
33570                 y = -Q - q,
33571                 Y = pow(abs(y), 1/3) * (y < 0 ? -1 : 1),
33572                 t = X + Y + 0.5;
33573             return (1 - t) * 3 * t * t + t * t * t;
33574         },
33575         backIn: function (n) {
33576             return n * n * ((backInSeed + 1) * n - backInSeed);
33577         },
33578         backOut: function (n) {
33579             n = n - 1;
33580             return n * n * ((backInSeed + 1) * n + backInSeed) + 1;
33581         },
33582         elasticIn: function (n) {
33583             if (n === 0 || n === 1) {
33584                 return n;
33585             }
33586             var p = 0.3,
33587                 s = p / 4;
33588             return pow(2, -10 * n) * sin((n - s) * (2 * pi) / p) + 1;
33589         },
33590         elasticOut: function (n) {
33591             return 1 - Ext.fx.Easing.elasticIn(1 - n);
33592         },
33593         bounceIn: function (n) {
33594             return 1 - Ext.fx.Easing.bounceOut(1 - n);
33595         },
33596         bounceOut: function (n) {
33597             var s = 7.5625,
33598                 p = 2.75,
33599                 l;
33600             if (n < (1 / p)) {
33601                 l = s * n * n;
33602             } else {
33603                 if (n < (2 / p)) {
33604                     n -= (1.5 / p);
33605                     l = s * n * n + 0.75;
33606                 } else {
33607                     if (n < (2.5 / p)) {
33608                         n -= (2.25 / p);
33609                         l = s * n * n + 0.9375;
33610                     } else {
33611                         n -= (2.625 / p);
33612                         l = s * n * n + 0.984375;
33613                     }
33614                 }
33615             }
33616             return l;
33617         }
33618     });
33619     Ext.apply(Ext.fx.Easing, {
33620         'back-in': Ext.fx.Easing.backIn,
33621         'back-out': Ext.fx.Easing.backOut,
33622         'ease-in': Ext.fx.Easing.easeIn,
33623         'ease-out': Ext.fx.Easing.easeOut,
33624         'elastic-in': Ext.fx.Easing.elasticIn,
33625         'elastic-out': Ext.fx.Easing.elasticIn,
33626         'bounce-in': Ext.fx.Easing.bounceIn,
33627         'bounce-out': Ext.fx.Easing.bounceOut,
33628         'ease-in-out': Ext.fx.Easing.easeInOut
33629     });
33630 });
33631
33632
33633 Ext.define('Ext.draw.Draw', {
33634     
33635
33636     singleton: true,
33637
33638     requires: ['Ext.draw.Color'],
33639
33640     
33641
33642     pathToStringRE: /,?([achlmqrstvxz]),?/gi,
33643     pathCommandRE: /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,
33644     pathValuesRE: /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,
33645     stopsRE: /^(\d+%?)$/,
33646     radian: Math.PI / 180,
33647
33648     availableAnimAttrs: {
33649         along: "along",
33650         blur: null,
33651         "clip-rect": "csv",
33652         cx: null,
33653         cy: null,
33654         fill: "color",
33655         "fill-opacity": null,
33656         "font-size": null,
33657         height: null,
33658         opacity: null,
33659         path: "path",
33660         r: null,
33661         rotation: "csv",
33662         rx: null,
33663         ry: null,
33664         scale: "csv",
33665         stroke: "color",
33666         "stroke-opacity": null,
33667         "stroke-width": null,
33668         translation: "csv",
33669         width: null,
33670         x: null,
33671         y: null
33672     },
33673
33674     is: function(o, type) {
33675         type = String(type).toLowerCase();
33676         return (type == "object" && o === Object(o)) ||
33677             (type == "undefined" && typeof o == type) ||
33678             (type == "null" && o === null) ||
33679             (type == "array" && Array.isArray && Array.isArray(o)) ||
33680             (Object.prototype.toString.call(o).toLowerCase().slice(8, -1)) == type;
33681     },
33682
33683     ellipsePath: function(sprite) {
33684         var attr = sprite.attr;
33685         return Ext.String.format("M{0},{1}A{2},{3},0,1,1,{0},{4}A{2},{3},0,1,1,{0},{1}z", attr.x, attr.y - attr.ry, attr.rx, attr.ry, attr.y + attr.ry);
33686     },
33687
33688     rectPath: function(sprite) {
33689         var attr = sprite.attr;
33690         if (attr.radius) {
33691             return Ext.String.format("M{0},{1}l{2},0a{3},{3},0,0,1,{3},{3}l0,{5}a{3},{3},0,0,1,{4},{3}l{6},0a{3},{3},0,0,1,{4},{4}l0,{7}a{3},{3},0,0,1,{3},{4}z", attr.x + attr.radius, attr.y, attr.width - attr.radius * 2, attr.radius, -attr.radius, attr.height - attr.radius * 2, attr.radius * 2 - attr.width, attr.radius * 2 - attr.height);
33692         }
33693         else {
33694             return Ext.String.format("M{0},{1}l{2},0,0,{3},{4},0z", attr.x, attr.y, attr.width, attr.height, -attr.width);
33695         }
33696     },
33697
33698     path2string: function () {
33699         return this.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1");
33700     },
33701
33702     parsePathString: function (pathString) {
33703         if (!pathString) {
33704             return null;
33705         }
33706         var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0},
33707             data = [],
33708             me = this;
33709         if (me.is(pathString, "array") && me.is(pathString[0], "array")) { 
33710             data = me.pathClone(pathString);
33711         }
33712         if (!data.length) {
33713             String(pathString).replace(me.pathCommandRE, function (a, b, c) {
33714                 var params = [],
33715                     name = b.toLowerCase();
33716                 c.replace(me.pathValuesRE, function (a, b) {
33717                     b && params.push(+b);
33718                 });
33719                 if (name == "m" && params.length > 2) {
33720                     data.push([b].concat(params.splice(0, 2)));
33721                     name = "l";
33722                     b = (b == "m") ? "l" : "L";
33723                 }
33724                 while (params.length >= paramCounts[name]) {
33725                     data.push([b].concat(params.splice(0, paramCounts[name])));
33726                     if (!paramCounts[name]) {
33727                         break;
33728                     }
33729                 }
33730             });
33731         }
33732         data.toString = me.path2string;
33733         return data;
33734     },
33735
33736     mapPath: function (path, matrix) {
33737         if (!matrix) {
33738             return path;
33739         }
33740         var x, y, i, ii, j, jj, pathi;
33741         path = this.path2curve(path);
33742         for (i = 0, ii = path.length; i < ii; i++) {
33743             pathi = path[i];
33744             for (j = 1, jj = pathi.length; j < jj-1; j += 2) {
33745                 x = matrix.x(pathi[j], pathi[j + 1]);
33746                 y = matrix.y(pathi[j], pathi[j + 1]);
33747                 pathi[j] = x;
33748                 pathi[j + 1] = y;
33749             }
33750         }
33751         return path;
33752     },
33753
33754     pathClone: function(pathArray) {
33755         var res = [],
33756             j,
33757             jj,
33758             i,
33759             ii;
33760         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { 
33761             pathArray = this.parsePathString(pathArray);
33762         }
33763         for (i = 0, ii = pathArray.length; i < ii; i++) {
33764             res[i] = [];
33765             for (j = 0, jj = pathArray[i].length; j < jj; j++) {
33766                 res[i][j] = pathArray[i][j];
33767             }
33768         }
33769         res.toString = this.path2string;
33770         return res;
33771     },
33772
33773     pathToAbsolute: function (pathArray) {
33774         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { 
33775             pathArray = this.parsePathString(pathArray);
33776         }
33777         var res = [],
33778             x = 0,
33779             y = 0,
33780             mx = 0,
33781             my = 0,
33782             start = 0,
33783             i,
33784             ii,
33785             r,
33786             pa,
33787             j,
33788             jj,
33789             k,
33790             kk;
33791         if (pathArray[0][0] == "M") {
33792             x = +pathArray[0][1];
33793             y = +pathArray[0][2];
33794             mx = x;
33795             my = y;
33796             start++;
33797             res[0] = ["M", x, y];
33798         }
33799         for (i = start, ii = pathArray.length; i < ii; i++) {
33800             r = res[i] = [];
33801             pa = pathArray[i];
33802             if (pa[0] != pa[0].toUpperCase()) {
33803                 r[0] = pa[0].toUpperCase();
33804                 switch (r[0]) {
33805                     case "A":
33806                         r[1] = pa[1];
33807                         r[2] = pa[2];
33808                         r[3] = pa[3];
33809                         r[4] = pa[4];
33810                         r[5] = pa[5];
33811                         r[6] = +(pa[6] + x);
33812                         r[7] = +(pa[7] + y);
33813                         break;
33814                     case "V":
33815                         r[1] = +pa[1] + y;
33816                         break;
33817                     case "H":
33818                         r[1] = +pa[1] + x;
33819                         break;
33820                     case "M":
33821                         mx = +pa[1] + x;
33822                         my = +pa[2] + y;
33823                     default:
33824                         for (j = 1, jj = pa.length; j < jj; j++) {
33825                             r[j] = +pa[j] + ((j % 2) ? x : y);
33826                         }
33827                 }
33828             } else {
33829                 for (k = 0, kk = pa.length; k < kk; k++) {
33830                     res[i][k] = pa[k];
33831                 }
33832             }
33833             switch (r[0]) {
33834                 case "Z":
33835                     x = mx;
33836                     y = my;
33837                     break;
33838                 case "H":
33839                     x = r[1];
33840                     break;
33841                 case "V":
33842                     y = r[1];
33843                     break;
33844                 case "M":
33845                     mx = res[i][res[i].length - 2];
33846                     my = res[i][res[i].length - 1];
33847                 default:
33848                     x = res[i][res[i].length - 2];
33849                     y = res[i][res[i].length - 1];
33850             }
33851         }
33852         res.toString = this.path2string;
33853         return res;
33854     },
33855
33856     pathToRelative: function (pathArray) {
33857         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) {
33858             pathArray = this.parsePathString(pathArray);
33859         }
33860         var res = [],
33861             x = 0,
33862             y = 0,
33863             mx = 0,
33864             my = 0,
33865             start = 0;
33866         if (pathArray[0][0] == "M") {
33867             x = pathArray[0][1];
33868             y = pathArray[0][2];
33869             mx = x;
33870             my = y;
33871             start++;
33872             res.push(["M", x, y]);
33873         }
33874         for (var i = start, ii = pathArray.length; i < ii; i++) {
33875             var r = res[i] = [],
33876                 pa = pathArray[i];
33877             if (pa[0] != pa[0].toLowerCase()) {
33878                 r[0] = pa[0].toLowerCase();
33879                 switch (r[0]) {
33880                     case "a":
33881                         r[1] = pa[1];
33882                         r[2] = pa[2];
33883                         r[3] = pa[3];
33884                         r[4] = pa[4];
33885                         r[5] = pa[5];
33886                         r[6] = +(pa[6] - x).toFixed(3);
33887                         r[7] = +(pa[7] - y).toFixed(3);
33888                         break;
33889                     case "v":
33890                         r[1] = +(pa[1] - y).toFixed(3);
33891                         break;
33892                     case "m":
33893                         mx = pa[1];
33894                         my = pa[2];
33895                     default:
33896                         for (var j = 1, jj = pa.length; j < jj; j++) {
33897                             r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
33898                         }
33899                 }
33900             } else {
33901                 r = res[i] = [];
33902                 if (pa[0] == "m") {
33903                     mx = pa[1] + x;
33904                     my = pa[2] + y;
33905                 }
33906                 for (var k = 0, kk = pa.length; k < kk; k++) {
33907                     res[i][k] = pa[k];
33908                 }
33909             }
33910             var len = res[i].length;
33911             switch (res[i][0]) {
33912                 case "z":
33913                     x = mx;
33914                     y = my;
33915                     break;
33916                 case "h":
33917                     x += +res[i][len - 1];
33918                     break;
33919                 case "v":
33920                     y += +res[i][len - 1];
33921                     break;
33922                 default:
33923                     x += +res[i][len - 2];
33924                     y += +res[i][len - 1];
33925             }
33926         }
33927         res.toString = this.path2string;
33928         return res;
33929     },
33930
33931     
33932     path2curve: function (path) {
33933         var me = this,
33934             points = me.pathToAbsolute(path),
33935             ln = points.length,
33936             attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
33937             i, seg, segLn, point;
33938             
33939         for (i = 0; i < ln; i++) {
33940             points[i] = me.command2curve(points[i], attrs);
33941             if (points[i].length > 7) {
33942                     points[i].shift();
33943                     point = points[i];
33944                     while (point.length) {
33945                         points.splice(i++, 0, ["C"].concat(point.splice(0, 6)));
33946                     }
33947                     points.splice(i, 1);
33948                     ln = points.length;
33949                 }
33950             seg = points[i];
33951             segLn = seg.length;
33952             attrs.x = seg[segLn - 2];
33953             attrs.y = seg[segLn - 1];
33954             attrs.bx = parseFloat(seg[segLn - 4]) || attrs.x;
33955             attrs.by = parseFloat(seg[segLn - 3]) || attrs.y;
33956         }
33957         return points;
33958     },
33959     
33960     interpolatePaths: function (path, path2) {
33961         var me = this,
33962             p = me.pathToAbsolute(path),
33963             p2 = me.pathToAbsolute(path2),
33964             attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
33965             attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
33966             fixArc = function (pp, i) {
33967                 if (pp[i].length > 7) {
33968                     pp[i].shift();
33969                     var pi = pp[i];
33970                     while (pi.length) {
33971                         pp.splice(i++, 0, ["C"].concat(pi.splice(0, 6)));
33972                     }
33973                     pp.splice(i, 1);
33974                     ii = Math.max(p.length, p2.length || 0);
33975                 }
33976             },
33977             fixM = function (path1, path2, a1, a2, i) {
33978                 if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
33979                     path2.splice(i, 0, ["M", a2.x, a2.y]);
33980                     a1.bx = 0;
33981                     a1.by = 0;
33982                     a1.x = path1[i][1];
33983                     a1.y = path1[i][2];
33984                     ii = Math.max(p.length, p2.length || 0);
33985                 }
33986             };
33987         for (var i = 0, ii = Math.max(p.length, p2.length || 0); i < ii; i++) {
33988             p[i] = me.command2curve(p[i], attrs);
33989             fixArc(p, i);
33990             (p2[i] = me.command2curve(p2[i], attrs2));
33991             fixArc(p2, i);
33992             fixM(p, p2, attrs, attrs2, i);
33993             fixM(p2, p, attrs2, attrs, i);
33994             var seg = p[i],
33995                 seg2 = p2[i],
33996                 seglen = seg.length,
33997                 seg2len = seg2.length;
33998             attrs.x = seg[seglen - 2];
33999             attrs.y = seg[seglen - 1];
34000             attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
34001             attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
34002             attrs2.bx = (parseFloat(seg2[seg2len - 4]) || attrs2.x);
34003             attrs2.by = (parseFloat(seg2[seg2len - 3]) || attrs2.y);
34004             attrs2.x = seg2[seg2len - 2];
34005             attrs2.y = seg2[seg2len - 1];
34006         }
34007         return [p, p2];
34008     },
34009     
34010     
34011     command2curve: function (pathCommand, d) {
34012         var me = this;
34013         if (!pathCommand) {
34014             return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
34015         }
34016         if (pathCommand[0] != "T" && pathCommand[0] != "Q") {
34017             d.qx = d.qy = null;
34018         }
34019         switch (pathCommand[0]) {
34020             case "M":
34021                 d.X = pathCommand[1];
34022                 d.Y = pathCommand[2];
34023                 break;
34024             case "A":
34025                 pathCommand = ["C"].concat(me.arc2curve.apply(me, [d.x, d.y].concat(pathCommand.slice(1))));
34026                 break;
34027             case "S":
34028                 pathCommand = ["C", d.x + (d.x - (d.bx || d.x)), d.y + (d.y - (d.by || d.y))].concat(pathCommand.slice(1));
34029                 break;
34030             case "T":
34031                 d.qx = d.x + (d.x - (d.qx || d.x));
34032                 d.qy = d.y + (d.y - (d.qy || d.y));
34033                 pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, d.qx, d.qy, pathCommand[1], pathCommand[2]));
34034                 break;
34035             case "Q":
34036                 d.qx = pathCommand[1];
34037                 d.qy = pathCommand[2];
34038                 pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[3], pathCommand[4]));
34039                 break;
34040             case "L":
34041                 pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[1], pathCommand[2]);
34042                 break;
34043             case "H":
34044                 pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], d.y, pathCommand[1], d.y);
34045                 break;
34046             case "V":
34047                 pathCommand = ["C"].concat(d.x, d.y, d.x, pathCommand[1], d.x, pathCommand[1]);
34048                 break;
34049             case "Z":
34050                 pathCommand = ["C"].concat(d.x, d.y, d.X, d.Y, d.X, d.Y);
34051                 break;
34052         }
34053         return pathCommand;
34054     },
34055
34056     quadratic2curve: function (x1, y1, ax, ay, x2, y2) {
34057         var _13 = 1 / 3,
34058             _23 = 2 / 3;
34059         return [
34060                 _13 * x1 + _23 * ax,
34061                 _13 * y1 + _23 * ay,
34062                 _13 * x2 + _23 * ax,
34063                 _13 * y2 + _23 * ay,
34064                 x2,
34065                 y2
34066             ];
34067     },
34068     
34069     rotate: function (x, y, rad) {
34070         var cos = Math.cos(rad),
34071             sin = Math.sin(rad),
34072             X = x * cos - y * sin,
34073             Y = x * sin + y * cos;
34074         return {x: X, y: Y};
34075     },
34076
34077     arc2curve: function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
34078         
34079         
34080         var me = this,
34081             PI = Math.PI,
34082             radian = me.radian,
34083             _120 = PI * 120 / 180,
34084             rad = radian * (+angle || 0),
34085             res = [],
34086             math = Math,
34087             mcos = math.cos,
34088             msin = math.sin,
34089             msqrt = math.sqrt,
34090             mabs = math.abs,
34091             masin = math.asin,
34092             xy, cos, sin, x, y, h, rx2, ry2, k, cx, cy, f1, f2, df, c1, s1, c2, s2,
34093             t, hx, hy, m1, m2, m3, m4, newres, i, ln, f2old, x2old, y2old;
34094         if (!recursive) {
34095             xy = me.rotate(x1, y1, -rad);
34096             x1 = xy.x;
34097             y1 = xy.y;
34098             xy = me.rotate(x2, y2, -rad);
34099             x2 = xy.x;
34100             y2 = xy.y;
34101             cos = mcos(radian * angle);
34102             sin = msin(radian * angle);
34103             x = (x1 - x2) / 2;
34104             y = (y1 - y2) / 2;
34105             h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
34106             if (h > 1) {
34107                 h = msqrt(h);
34108                 rx = h * rx;
34109                 ry = h * ry;
34110             }
34111             rx2 = rx * rx;
34112             ry2 = ry * ry;
34113             k = (large_arc_flag == sweep_flag ? -1 : 1) *
34114                     msqrt(mabs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)));
34115             cx = k * rx * y / ry + (x1 + x2) / 2;
34116             cy = k * -ry * x / rx + (y1 + y2) / 2;
34117             f1 = masin(((y1 - cy) / ry).toFixed(7));
34118             f2 = masin(((y2 - cy) / ry).toFixed(7));
34119
34120             f1 = x1 < cx ? PI - f1 : f1;
34121             f2 = x2 < cx ? PI - f2 : f2;
34122             if (f1 < 0) {
34123                 f1 = PI * 2 + f1;
34124             }
34125             if (f2 < 0) {
34126                 f2 = PI * 2 + f2;
34127             }
34128             if (sweep_flag && f1 > f2) {
34129                 f1 = f1 - PI * 2;
34130             }
34131             if (!sweep_flag && f2 > f1) {
34132                 f2 = f2 - PI * 2;
34133             }
34134         }
34135         else {
34136             f1 = recursive[0];
34137             f2 = recursive[1];
34138             cx = recursive[2];
34139             cy = recursive[3];
34140         }
34141         df = f2 - f1;
34142         if (mabs(df) > _120) {
34143             f2old = f2;
34144             x2old = x2;
34145             y2old = y2;
34146             f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
34147             x2 = cx + rx * mcos(f2);
34148             y2 = cy + ry * msin(f2);
34149             res = me.arc2curve(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
34150         }
34151         df = f2 - f1;
34152         c1 = mcos(f1);
34153         s1 = msin(f1);
34154         c2 = mcos(f2);
34155         s2 = msin(f2);
34156         t = math.tan(df / 4);
34157         hx = 4 / 3 * rx * t;
34158         hy = 4 / 3 * ry * t;
34159         m1 = [x1, y1];
34160         m2 = [x1 + hx * s1, y1 - hy * c1];
34161         m3 = [x2 + hx * s2, y2 - hy * c2];
34162         m4 = [x2, y2];
34163         m2[0] = 2 * m1[0] - m2[0];
34164         m2[1] = 2 * m1[1] - m2[1];
34165         if (recursive) {
34166             return [m2, m3, m4].concat(res);
34167         }
34168         else {
34169             res = [m2, m3, m4].concat(res).join().split(",");
34170             newres = [];
34171             ln = res.length;
34172             for (i = 0;  i < ln; i++) {
34173                 newres[i] = i % 2 ? me.rotate(res[i - 1], res[i], rad).y : me.rotate(res[i], res[i + 1], rad).x;
34174             }
34175             return newres;
34176         }
34177     },
34178     
34179     rotatePoint: function (x, y, alpha, cx, cy) {
34180         if (!alpha) {
34181             return {
34182                 x: x,
34183                 y: y
34184             };
34185         }
34186         cx = cx || 0;
34187         cy = cy || 0;
34188         x = x - cx;
34189         y = y - cy;
34190         alpha = alpha * this.radian;
34191         var cos = Math.cos(alpha),
34192             sin = Math.sin(alpha);
34193         return {
34194             x: x * cos - y * sin + cx,
34195             y: x * sin + y * cos + cy
34196         };
34197     },
34198
34199     rotateAndTranslatePath: function (sprite) {
34200         var alpha = sprite.rotation.degrees,
34201             cx = sprite.rotation.x,
34202             cy = sprite.rotation.y,
34203             dx = sprite.translation.x,
34204             dy = sprite.translation.y,
34205             path,
34206             i,
34207             p,
34208             xy,
34209             j,
34210             res = [];
34211         if (!alpha && !dx && !dy) {
34212             return this.pathToAbsolute(sprite.attr.path);
34213         }
34214         dx = dx || 0;
34215         dy = dy || 0;
34216         path = this.pathToAbsolute(sprite.attr.path);
34217         for (i = path.length; i--;) {
34218             p = res[i] = path[i].slice();
34219             if (p[0] == "A") {
34220                 xy = this.rotatePoint(p[6], p[7], alpha, cx, cy);
34221                 p[6] = xy.x + dx;
34222                 p[7] = xy.y + dy;
34223             } else {
34224                 j = 1;
34225                 while (p[j + 1] != null) {
34226                     xy = this.rotatePoint(p[j], p[j + 1], alpha, cx, cy);
34227                     p[j] = xy.x + dx;
34228                     p[j + 1] = xy.y + dy;
34229                     j += 2;
34230                 }
34231             }
34232         }
34233         return res;
34234     },
34235     
34236     pathDimensions: function (path) {
34237         if (!path || !(path + "")) {
34238             return {x: 0, y: 0, width: 0, height: 0};
34239         }
34240         path = this.path2curve(path);
34241         var x = 0, 
34242             y = 0,
34243             X = [],
34244             Y = [],
34245             p,
34246             i,
34247             ii,
34248             xmin,
34249             ymin,
34250             dim;
34251         for (i = 0, ii = path.length; i < ii; i++) {
34252             p = path[i];
34253             if (p[0] == "M") {
34254                 x = p[1];
34255                 y = p[2];
34256                 X.push(x);
34257                 Y.push(y);
34258             }
34259             else {
34260                 dim = this.curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
34261                 X = X.concat(dim.min.x, dim.max.x);
34262                 Y = Y.concat(dim.min.y, dim.max.y);
34263                 x = p[5];
34264                 y = p[6];
34265             }
34266         }
34267         xmin = Math.min.apply(0, X);
34268         ymin = Math.min.apply(0, Y);
34269         return {
34270             x: xmin,
34271             y: ymin,
34272             path: path,
34273             width: Math.max.apply(0, X) - xmin,
34274             height: Math.max.apply(0, Y) - ymin
34275         };
34276     },
34277     
34278     intersect: function(subjectPolygon, clipPolygon) {
34279         var cp1, cp2, s, e, point;
34280         var inside = function(p) {
34281             return (cp2[0]-cp1[0]) * (p[1]-cp1[1]) > (cp2[1]-cp1[1]) * (p[0]-cp1[0]);
34282         };
34283         var intersection = function() {
34284             var p = [];
34285             var dcx = cp1[0]-cp2[0],
34286                 dcy = cp1[1]-cp2[1],
34287                 dpx = s[0]-e[0],
34288                 dpy = s[1]-e[1],
34289                 n1 = cp1[0]*cp2[1] - cp1[1]*cp2[0],
34290                 n2 = s[0]*e[1] - s[1]*e[0],
34291                 n3 = 1 / (dcx*dpy - dcy*dpx);
34292
34293             p[0] = (n1*dpx - n2*dcx) * n3;
34294             p[1] = (n1*dpy - n2*dcy) * n3;
34295             return p;
34296         };
34297         var outputList = subjectPolygon;
34298         cp1 = clipPolygon[clipPolygon.length -1];
34299         for (var i = 0, l = clipPolygon.length; i < l; ++i) {
34300             cp2 = clipPolygon[i];
34301             var inputList = outputList;
34302             outputList = [];
34303             s = inputList[inputList.length -1];
34304             for (var j = 0, ln = inputList.length; j < ln; j++) {
34305                 e = inputList[j];
34306                 if (inside(e)) {
34307                     if (!inside(s)) {
34308                         outputList.push(intersection());
34309                     }
34310                     outputList.push(e);
34311                 } else if (inside(s)) {
34312                     outputList.push(intersection());
34313                 }
34314                 s = e;
34315             }
34316             cp1 = cp2;
34317         }
34318         return outputList;
34319     },
34320     
34321     curveDim: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
34322         var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
34323             b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
34324             c = p1x - c1x,
34325             t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a,
34326             t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a,
34327             y = [p1y, p2y],
34328             x = [p1x, p2x],
34329             dot;
34330         if (Math.abs(t1) > 1e12) {
34331             t1 = 0.5;
34332         }
34333         if (Math.abs(t2) > 1e12) {
34334             t2 = 0.5;
34335         }
34336         if (t1 > 0 && t1 < 1) {
34337             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
34338             x.push(dot.x);
34339             y.push(dot.y);
34340         }
34341         if (t2 > 0 && t2 < 1) {
34342             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
34343             x.push(dot.x);
34344             y.push(dot.y);
34345         }
34346         a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
34347         b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
34348         c = p1y - c1y;
34349         t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a;
34350         t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
34351         if (Math.abs(t1) > 1e12) {
34352             t1 = 0.5;
34353         }
34354         if (Math.abs(t2) > 1e12) {
34355             t2 = 0.5;
34356         }
34357         if (t1 > 0 && t1 < 1) {
34358             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
34359             x.push(dot.x);
34360             y.push(dot.y);
34361         }
34362         if (t2 > 0 && t2 < 1) {
34363             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
34364             x.push(dot.x);
34365             y.push(dot.y);
34366         }
34367         return {
34368             min: {x: Math.min.apply(0, x), y: Math.min.apply(0, y)},
34369             max: {x: Math.max.apply(0, x), y: Math.max.apply(0, y)}
34370         };
34371     },
34372
34373     getAnchors: function (p1x, p1y, p2x, p2y, p3x, p3y, value) {
34374         value = value || 4;
34375         var l = Math.min(Math.sqrt(Math.pow(p1x - p2x, 2) + Math.pow(p1y - p2y, 2)) / value, Math.sqrt(Math.pow(p3x - p2x, 2) + Math.pow(p3y - p2y, 2)) / value),
34376             a = Math.atan((p2x - p1x) / Math.abs(p2y - p1y)),
34377             b = Math.atan((p3x - p2x) / Math.abs(p2y - p3y)),
34378             pi = Math.PI;
34379         a = p1y < p2y ? pi - a : a;
34380         b = p3y < p2y ? pi - b : b;
34381         var alpha = pi / 2 - ((a + b) % (pi * 2)) / 2;
34382         alpha > pi / 2 && (alpha -= pi);
34383         var dx1 = l * Math.sin(alpha + a),
34384             dy1 = l * Math.cos(alpha + a),
34385             dx2 = l * Math.sin(alpha + b),
34386             dy2 = l * Math.cos(alpha + b),
34387             out = {
34388                 x1: p2x - dx1,
34389                 y1: p2y + dy1,
34390                 x2: p2x + dx2,
34391                 y2: p2y + dy2
34392             };
34393         return out;
34394     },
34395
34396     
34397     smooth: function (originalPath, value) {
34398         var path = this.path2curve(originalPath),
34399             newp = [path[0]],
34400             x = path[0][1],
34401             y = path[0][2],
34402             j,
34403             points,
34404             i = 1,
34405             ii = path.length,
34406             beg = 1,
34407             mx = x,
34408             my = y,
34409             cx = 0,
34410             cy = 0;
34411         for (; i < ii; i++) {
34412             var pathi = path[i],
34413                 pathil = pathi.length,
34414                 pathim = path[i - 1],
34415                 pathiml = pathim.length,
34416                 pathip = path[i + 1],
34417                 pathipl = pathip && pathip.length;
34418             if (pathi[0] == "M") {
34419                 mx = pathi[1];
34420                 my = pathi[2];
34421                 j = i + 1;
34422                 while (path[j][0] != "C") {
34423                     j++;
34424                 }
34425                 cx = path[j][5];
34426                 cy = path[j][6];
34427                 newp.push(["M", mx, my]);
34428                 beg = newp.length;
34429                 x = mx;
34430                 y = my;
34431                 continue;
34432             }
34433             if (pathi[pathil - 2] == mx && pathi[pathil - 1] == my && (!pathip || pathip[0] == "M")) {
34434                 var begl = newp[beg].length;
34435                 points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], mx, my, newp[beg][begl - 2], newp[beg][begl - 1], value);
34436                 newp[beg][1] = points.x2;
34437                 newp[beg][2] = points.y2;
34438             }
34439             else if (!pathip || pathip[0] == "M") {
34440                 points = {
34441                     x1: pathi[pathil - 2],
34442                     y1: pathi[pathil - 1]
34443                 };
34444             } else {
34445                 points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], pathi[pathil - 2], pathi[pathil - 1], pathip[pathipl - 2], pathip[pathipl - 1], value);
34446             }
34447             newp.push(["C", x, y, points.x1, points.y1, pathi[pathil - 2], pathi[pathil - 1]]);
34448             x = points.x2;
34449             y = points.y2;
34450         }
34451         return newp;
34452     },
34453
34454     findDotAtSegment: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
34455         var t1 = 1 - t;
34456         return {
34457             x: Math.pow(t1, 3) * p1x + Math.pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + Math.pow(t, 3) * p2x,
34458             y: Math.pow(t1, 3) * p1y + Math.pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + Math.pow(t, 3) * p2y
34459         };
34460     },
34461
34462     snapEnds: function (from, to, stepsMax) {
34463         var step = (to - from) / stepsMax,
34464             level = Math.floor(Math.log(step) / Math.LN10) + 1,
34465             m = Math.pow(10, level),
34466             cur,
34467             modulo = Math.round((step % m) * Math.pow(10, 2 - level)),
34468             interval = [[0, 15], [20, 4], [30, 2], [40, 4], [50, 9], [60, 4], [70, 2], [80, 4], [100, 15]],
34469             stepCount = 0,
34470             value,
34471             weight,
34472             i,
34473             topValue,
34474             topWeight = 1e9,
34475             ln = interval.length;
34476         cur = from = Math.floor(from / m) * m;
34477         for (i = 0; i < ln; i++) {
34478             value = interval[i][0];
34479             weight = (value - modulo) < 0 ? 1e6 : (value - modulo) / interval[i][1];
34480             if (weight < topWeight) {
34481                 topValue = value;
34482                 topWeight = weight;
34483             }
34484         }
34485         step = Math.floor(step * Math.pow(10, -level)) * Math.pow(10, level) + topValue * Math.pow(10, level - 2);
34486         while (cur < to) {
34487             cur += step;
34488             stepCount++;
34489         }
34490         to = +cur.toFixed(10);
34491         return {
34492             from: from,
34493             to: to,
34494             power: level,
34495             step: step,
34496             steps: stepCount
34497         };
34498     },
34499
34500     sorter: function (a, b) {
34501         return a.offset - b.offset;
34502     },
34503
34504     rad: function(degrees) {
34505         return degrees % 360 * Math.PI / 180;
34506     },
34507
34508     degrees: function(radian) {
34509         return radian * 180 / Math.PI % 360;
34510     },
34511
34512     withinBox: function(x, y, bbox) {
34513         bbox = bbox || {};
34514         return (x >= bbox.x && x <= (bbox.x + bbox.width) && y >= bbox.y && y <= (bbox.y + bbox.height));
34515     },
34516
34517     parseGradient: function(gradient) {
34518         var me = this,
34519             type = gradient.type || 'linear',
34520             angle = gradient.angle || 0,
34521             radian = me.radian,
34522             stops = gradient.stops,
34523             stopsArr = [],
34524             stop,
34525             vector,
34526             max,
34527             stopObj;
34528
34529         if (type == 'linear') {
34530             vector = [0, 0, Math.cos(angle * radian), Math.sin(angle * radian)];
34531             max = 1 / (Math.max(Math.abs(vector[2]), Math.abs(vector[3])) || 1);
34532             vector[2] *= max;
34533             vector[3] *= max;
34534             if (vector[2] < 0) {
34535                 vector[0] = -vector[2];
34536                 vector[2] = 0;
34537             }
34538             if (vector[3] < 0) {
34539                 vector[1] = -vector[3];
34540                 vector[3] = 0;
34541             }
34542         }
34543
34544         for (stop in stops) {
34545             if (stops.hasOwnProperty(stop) && me.stopsRE.test(stop)) {
34546                 stopObj = {
34547                     offset: parseInt(stop, 10),
34548                     color: Ext.draw.Color.toHex(stops[stop].color) || '#ffffff',
34549                     opacity: stops[stop].opacity || 1
34550                 };
34551                 stopsArr.push(stopObj);
34552             }
34553         }
34554         
34555         Ext.Array.sort(stopsArr, me.sorter);
34556         if (type == 'linear') {
34557             return {
34558                 id: gradient.id,
34559                 type: type,
34560                 vector: vector,
34561                 stops: stopsArr
34562             };
34563         }
34564         else {
34565             return {
34566                 id: gradient.id,
34567                 type: type,
34568                 centerX: gradient.centerX,
34569                 centerY: gradient.centerY,
34570                 focalX: gradient.focalX,
34571                 focalY: gradient.focalY,
34572                 radius: gradient.radius,
34573                 vector: vector,
34574                 stops: stopsArr
34575             };
34576         }
34577     }
34578 });
34579
34580
34581 Ext.define('Ext.fx.PropertyHandler', {
34582
34583     
34584
34585     requires: ['Ext.draw.Draw'],
34586
34587     statics: {
34588         defaultHandler: {
34589             pixelDefaults: ['width', 'height', 'top', 'left'],
34590             unitRE: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/,
34591
34592             computeDelta: function(from, end, damper, initial, attr) {
34593                 damper = (typeof damper == 'number') ? damper : 1;
34594                 var match = this.unitRE.exec(from),
34595                     start, units;
34596                 if (match) {
34597                     from = match[1];
34598                     units = match[2];
34599                     if (!units && Ext.Array.contains(this.pixelDefaults, attr)) {
34600                         units = 'px';
34601                     }
34602                 }
34603                 from = +from || 0;
34604
34605                 match = this.unitRE.exec(end);
34606                 if (match) {
34607                     end = match[1];
34608                     units = match[2] || units;
34609                 }
34610                 end = +end || 0;
34611                 start = (initial != null) ? initial : from;
34612                 return {
34613                     from: from,
34614                     delta: (end - start) * damper,
34615                     units: units
34616                 };
34617             },
34618
34619             get: function(from, end, damper, initialFrom, attr) {
34620                 var ln = from.length,
34621                     out = [],
34622                     i, initial, res, j, len;
34623                 for (i = 0; i < ln; i++) {
34624                     if (initialFrom) {
34625                         initial = initialFrom[i][1].from;
34626                     }
34627                     if (Ext.isArray(from[i][1]) && Ext.isArray(end)) {
34628                         res = [];
34629                         j = 0;
34630                         len = from[i][1].length;
34631                         for (; j < len; j++) {
34632                             res.push(this.computeDelta(from[i][1][j], end[j], damper, initial, attr));
34633                         }
34634                         out.push([from[i][0], res]);
34635                     }
34636                     else {
34637                         out.push([from[i][0], this.computeDelta(from[i][1], end, damper, initial, attr)]);
34638                     }
34639                 }
34640                 return out;
34641             },
34642
34643             set: function(values, easing) {
34644                 var ln = values.length,
34645                     out = [],
34646                     i, val, res, len, j;
34647                 for (i = 0; i < ln; i++) {
34648                     val  = values[i][1];
34649                     if (Ext.isArray(val)) {
34650                         res = [];
34651                         j = 0;
34652                         len = val.length;
34653                         for (; j < len; j++) {
34654                             res.push(val[j].from + (val[j].delta * easing) + (val[j].units || 0));
34655                         }
34656                         out.push([values[i][0], res]);
34657                     } else {
34658                         out.push([values[i][0], val.from + (val.delta * easing) + (val.units || 0)]);
34659                     }
34660                 }
34661                 return out;
34662             }
34663         },
34664         color: {
34665             rgbRE: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,
34666             hexRE: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,
34667             hex3RE: /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i,
34668
34669             parseColor : function(color, damper) {
34670                 damper = (typeof damper == 'number') ? damper : 1;
34671                 var base,
34672                     out = false,
34673                     match;
34674
34675                 Ext.each([this.hexRE, this.rgbRE, this.hex3RE], function(re, idx) {
34676                     base = (idx % 2 == 0) ? 16 : 10;
34677                     match = re.exec(color);
34678                     if (match && match.length == 4) {
34679                         if (idx == 2) {
34680                             match[1] += match[1];
34681                             match[2] += match[2];
34682                             match[3] += match[3];
34683                         }
34684                         out = {
34685                             red: parseInt(match[1], base),
34686                             green: parseInt(match[2], base),
34687                             blue: parseInt(match[3], base)
34688                         };
34689                         return false;
34690                     }
34691                 });
34692                 return out || color;
34693             },
34694
34695             computeDelta: function(from, end, damper, initial) {
34696                 from = this.parseColor(from);
34697                 end = this.parseColor(end, damper);
34698                 var start = initial ? initial : from,
34699                     tfrom = typeof start,
34700                     tend = typeof end;
34701                 
34702                 if (tfrom == 'string' ||  tfrom == 'undefined' 
34703                   || tend == 'string' || tend == 'undefined') {
34704                     return end || start;
34705                 }
34706                 return {
34707                     from:  from,
34708                     delta: {
34709                         red: Math.round((end.red - start.red) * damper),
34710                         green: Math.round((end.green - start.green) * damper),
34711                         blue: Math.round((end.blue - start.blue) * damper)
34712                     }
34713                 };
34714             },
34715
34716             get: function(start, end, damper, initialFrom) {
34717                 var ln = start.length,
34718                     out = [],
34719                     i, initial;
34720                 for (i = 0; i < ln; i++) {
34721                     if (initialFrom) {
34722                         initial = initialFrom[i][1].from;
34723                     }
34724                     out.push([start[i][0], this.computeDelta(start[i][1], end, damper, initial)]);
34725                 }
34726                 return out;
34727             },
34728
34729             set: function(values, easing) {
34730                 var ln = values.length,
34731                     out = [],
34732                     i, val, parsedString, from, delta;
34733                 for (i = 0; i < ln; i++) {
34734                     val = values[i][1];
34735                     if (val) {
34736                         from = val.from;
34737                         delta = val.delta;
34738                         
34739                         val = (typeof val == 'object' && 'red' in val)? 
34740                                 'rgb(' + val.red + ', ' + val.green + ', ' + val.blue + ')' : val;
34741                         val = (typeof val == 'object' && val.length)? val[0] : val;
34742                         if (typeof val == 'undefined') {
34743                             return [];
34744                         }
34745                         parsedString = typeof val == 'string'? val :
34746                             'rgb(' + [
34747                                   (from.red + Math.round(delta.red * easing)) % 256,
34748                                   (from.green + Math.round(delta.green * easing)) % 256,
34749                                   (from.blue + Math.round(delta.blue * easing)) % 256
34750                               ].join(',') + ')';
34751                         out.push([
34752                             values[i][0],
34753                             parsedString
34754                         ]);
34755                     }
34756                 }
34757                 return out;
34758             }
34759         },
34760         object: {
34761             interpolate: function(prop, damper) {
34762                 damper = (typeof damper == 'number') ? damper : 1;
34763                 var out = {},
34764                     p;
34765                 for(p in prop) {
34766                     out[p] = parseInt(prop[p], 10) * damper;
34767                 }
34768                 return out;
34769             },
34770
34771             computeDelta: function(from, end, damper, initial) {
34772                 from = this.interpolate(from);
34773                 end = this.interpolate(end, damper);
34774                 var start = initial ? initial : from,
34775                     delta = {},
34776                     p;
34777
34778                 for(p in end) {
34779                     delta[p] = end[p] - start[p];
34780                 }
34781                 return {
34782                     from:  from,
34783                     delta: delta
34784                 };
34785             },
34786
34787             get: function(start, end, damper, initialFrom) {
34788                 var ln = start.length,
34789                     out = [],
34790                     i, initial;
34791                 for (i = 0; i < ln; i++) {
34792                     if (initialFrom) {
34793                         initial = initialFrom[i][1].from;
34794                     }
34795                     out.push([start[i][0], this.computeDelta(start[i][1], end, damper, initial)]);
34796                 }
34797                 return out;
34798             },
34799
34800             set: function(values, easing) {
34801                 var ln = values.length,
34802                     out = [],
34803                     outObject = {},
34804                     i, from, delta, val, p;
34805                 for (i = 0; i < ln; i++) {
34806                     val  = values[i][1];
34807                     from = val.from;
34808                     delta = val.delta;
34809                     for (p in from) {
34810                         outObject[p] = Math.round(from[p] + delta[p] * easing);
34811                     }
34812                     out.push([
34813                         values[i][0],
34814                         outObject
34815                     ]);
34816                 }
34817                 return out;
34818             }
34819         },
34820
34821         path: {
34822             computeDelta: function(from, end, damper, initial) {
34823                 damper = (typeof damper == 'number') ? damper : 1;
34824                 var start;
34825                 from = +from || 0;
34826                 end = +end || 0;
34827                 start = (initial != null) ? initial : from;
34828                 return {
34829                     from: from,
34830                     delta: (end - start) * damper
34831                 };
34832             },
34833
34834             forcePath: function(path) {
34835                 if (!Ext.isArray(path) && !Ext.isArray(path[0])) {
34836                     path = Ext.draw.Draw.parsePathString(path);
34837                 }
34838                 return path;
34839             },
34840
34841             get: function(start, end, damper, initialFrom) {
34842                 var endPath = this.forcePath(end),
34843                     out = [],
34844                     startLn = start.length,
34845                     startPathLn, pointsLn, i, deltaPath, initial, j, k, path, startPath;
34846                 for (i = 0; i < startLn; i++) {
34847                     startPath = this.forcePath(start[i][1]);
34848
34849                     deltaPath = Ext.draw.Draw.interpolatePaths(startPath, endPath);
34850                     startPath = deltaPath[0];
34851                     endPath = deltaPath[1];
34852
34853                     startPathLn = startPath.length;
34854                     path = [];
34855                     for (j = 0; j < startPathLn; j++) {
34856                         deltaPath = [startPath[j][0]];
34857                         pointsLn = startPath[j].length;
34858                         for (k = 1; k < pointsLn; k++) {
34859                             initial = initialFrom && initialFrom[0][1][j][k].from;
34860                             deltaPath.push(this.computeDelta(startPath[j][k], endPath[j][k], damper, initial));
34861                         }
34862                         path.push(deltaPath);
34863                     }
34864                     out.push([start[i][0], path]);
34865                 }
34866                 return out;
34867             },
34868
34869             set: function(values, easing) {
34870                 var ln = values.length,
34871                     out = [],
34872                     i, j, k, newPath, calcPath, deltaPath, deltaPathLn, pointsLn;
34873                 for (i = 0; i < ln; i++) {
34874                     deltaPath = values[i][1];
34875                     newPath = [];
34876                     deltaPathLn = deltaPath.length;
34877                     for (j = 0; j < deltaPathLn; j++) {
34878                         calcPath = [deltaPath[j][0]];
34879                         pointsLn = deltaPath[j].length;
34880                         for (k = 1; k < pointsLn; k++) {
34881                             calcPath.push(deltaPath[j][k].from + deltaPath[j][k].delta * easing);
34882                         }
34883                         newPath.push(calcPath.join(','));
34884                     }
34885                     out.push([values[i][0], newPath.join(',')]);
34886                 }
34887                 return out;
34888             }
34889         }
34890         
34891     }
34892 }, function() {
34893     Ext.each([
34894         'outlineColor',
34895         'backgroundColor',
34896         'borderColor',
34897         'borderTopColor',
34898         'borderRightColor', 
34899         'borderBottomColor', 
34900         'borderLeftColor',
34901         'fill',
34902         'stroke'
34903     ], function(prop) {
34904         this[prop] = this.color;
34905     }, this);
34906 });
34907
34908 Ext.define('Ext.fx.Anim', {
34909
34910     
34911
34912     mixins: {
34913         observable: 'Ext.util.Observable'
34914     },
34915
34916     requires: ['Ext.fx.Manager', 'Ext.fx.Animator', 'Ext.fx.Easing', 'Ext.fx.CubicBezier', 'Ext.fx.PropertyHandler'],
34917
34918     
34919
34920     isAnimation: true,
34921     
34922     duration: 250,
34923
34924     
34925     delay: 0,
34926
34927     
34928     delayStart: 0,
34929
34930     
34931     dynamic: false,
34932
34933     
34934     easing: 'ease',
34935
34936      
34937
34938     
34939     damper: 1,
34940
34941     
34942     bezierRE: /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
34943
34944     
34945     reverse: false,
34946
34947     
34948     running: false,
34949
34950     
34951     paused: false,
34952
34953     
34954     iterations: 1,
34955
34956     
34957     alternate: false,
34958
34959     
34960     currentIteration: 0,
34961
34962     
34963     startTime: 0,
34964
34965     
34966
34967     
34968
34969     
34970
34971     
34972
34973     
34974     constructor: function(config) {
34975         var me = this;
34976         config = config || {};
34977         
34978         if (config.keyframes) {
34979             return Ext.create('Ext.fx.Animator', config);
34980         }
34981         config = Ext.apply(me, config);
34982         if (me.from === undefined) {
34983             me.from = {};
34984         }
34985         me.propHandlers = {};
34986         me.config = config;
34987         me.target = Ext.fx.Manager.createTarget(me.target);
34988         me.easingFn = Ext.fx.Easing[me.easing];
34989         me.target.dynamic = me.dynamic;
34990
34991         
34992         if (!me.easingFn) {
34993             me.easingFn = String(me.easing).match(me.bezierRE);
34994             if (me.easingFn && me.easingFn.length == 5) {
34995                 var curve = me.easingFn;
34996                 me.easingFn = Ext.fx.cubicBezier(+curve[1], +curve[2], +curve[3], +curve[4]);
34997             }
34998         }
34999         me.id = Ext.id(null, 'ext-anim-');
35000         Ext.fx.Manager.addAnim(me);
35001         me.addEvents(
35002             
35003             'beforeanimate',
35004              
35005             'afteranimate',
35006              
35007             'lastframe'
35008         );
35009         me.mixins.observable.constructor.call(me, config);
35010         if (config.callback) {
35011             me.on('afteranimate', config.callback, config.scope);
35012         }
35013         return me;
35014     },
35015
35016     
35017     setAttr: function(attr, value) {
35018         return Ext.fx.Manager.items.get(this.id).setAttr(this.target, attr, value);
35019     },
35020
35021     
35022     initAttrs: function() {
35023         var me = this,
35024             from = me.from,
35025             to = me.to,
35026             initialFrom = me.initialFrom || {},
35027             out = {},
35028             start, end, propHandler, attr;
35029
35030         for (attr in to) {
35031             if (to.hasOwnProperty(attr)) {
35032                 start = me.target.getAttr(attr, from[attr]);
35033                 end = to[attr];
35034                 
35035                 if (!Ext.fx.PropertyHandler[attr]) {
35036                     if (Ext.isObject(end)) {
35037                         propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.object;
35038                     } else {
35039                         propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.defaultHandler;
35040                     }
35041                 }
35042                 
35043                 else {
35044                     propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler[attr];
35045                 }
35046                 out[attr] = propHandler.get(start, end, me.damper, initialFrom[attr], attr);
35047             }
35048         }
35049         me.currentAttrs = out;
35050     },
35051
35052     
35053     start: function(startTime) {
35054         var me = this,
35055             delay = me.delay,
35056             delayStart = me.delayStart,
35057             delayDelta;
35058         if (delay) {
35059             if (!delayStart) {
35060                 me.delayStart = startTime;
35061                 return;
35062             }
35063             else {
35064                 delayDelta = startTime - delayStart;
35065                 if (delayDelta < delay) {
35066                     return;
35067                 }
35068                 else {
35069                     
35070                     startTime = new Date(delayStart.getTime() + delay);
35071                 }
35072             }
35073         }
35074         if (me.fireEvent('beforeanimate', me) !== false) {
35075             me.startTime = startTime;
35076             if (!me.paused && !me.currentAttrs) {
35077                 me.initAttrs();
35078             }
35079             me.running = true;
35080         }
35081     },
35082
35083     
35084     runAnim: function(elapsedTime) {
35085         var me = this,
35086             attrs = me.currentAttrs,
35087             duration = me.duration,
35088             easingFn = me.easingFn,
35089             propHandlers = me.propHandlers,
35090             ret = {},
35091             easing, values, attr, lastFrame;
35092
35093         if (elapsedTime >= duration) {
35094             elapsedTime = duration;
35095             lastFrame = true;
35096         }
35097         if (me.reverse) {
35098             elapsedTime = duration - elapsedTime;
35099         }
35100
35101         for (attr in attrs) {
35102             if (attrs.hasOwnProperty(attr)) {
35103                 values = attrs[attr];
35104                 easing = lastFrame ? 1 : easingFn(elapsedTime / duration);
35105                 ret[attr] = propHandlers[attr].set(values, easing);
35106             }
35107         }
35108         return ret;
35109     },
35110
35111     
35112     lastFrame: function() {
35113         var me = this,
35114             iter = me.iterations,
35115             iterCount = me.currentIteration;
35116
35117         iterCount++;
35118         if (iterCount < iter) {
35119             if (me.alternate) {
35120                 me.reverse = !me.reverse;
35121             }
35122             me.startTime = new Date();
35123             me.currentIteration = iterCount;
35124             
35125             me.paused = false;
35126         }
35127         else {
35128             me.currentIteration = 0;
35129             me.end();
35130             me.fireEvent('lastframe', me, me.startTime);
35131         }
35132     },
35133
35134     
35135     end: function() {
35136         var me = this;
35137         me.startTime = 0;
35138         me.paused = false;
35139         me.running = false;
35140         Ext.fx.Manager.removeAnim(me);
35141         me.fireEvent('afteranimate', me, me.startTime);
35142     }
35143 });
35144
35145 Ext.enableFx = true;
35146
35147
35148
35149
35150
35151
35152 Ext.define('Ext.dd.DragDrop', {
35153     requires: ['Ext.dd.DragDropManager'],
35154     constructor: function(id, sGroup, config) {
35155         if(id) {
35156             this.init(id, sGroup, config);
35157         }
35158     },
35159     
35160     
35161
35162     
35163     id: null,
35164
35165     
35166     config: null,
35167
35168     
35169     dragElId: null,
35170
35171     
35172     handleElId: null,
35173
35174     
35175     invalidHandleTypes: null,
35176
35177     
35178     invalidHandleIds: null,
35179
35180     
35181     invalidHandleClasses: null,
35182
35183     
35184     startPageX: 0,
35185
35186     
35187     startPageY: 0,
35188
35189     
35190     groups: null,
35191
35192     
35193     locked: false,
35194
35195     
35196     lock: function() {
35197         this.locked = true;
35198     },
35199
35200     
35201     moveOnly: false,
35202
35203     
35204     unlock: function() {
35205         this.locked = false;
35206     },
35207
35208     
35209     isTarget: true,
35210
35211     
35212     padding: null,
35213
35214     
35215     _domRef: null,
35216
35217     
35218     __ygDragDrop: true,
35219
35220     
35221     constrainX: false,
35222
35223     
35224     constrainY: false,
35225
35226     
35227     minX: 0,
35228
35229     
35230     maxX: 0,
35231
35232     
35233     minY: 0,
35234
35235     
35236     maxY: 0,
35237
35238     
35239     maintainOffset: false,
35240
35241     
35242     xTicks: null,
35243
35244     
35245     yTicks: null,
35246
35247     
35248     primaryButtonOnly: true,
35249
35250     
35251     available: false,
35252
35253     
35254     hasOuterHandles: false,
35255
35256     
35257     b4StartDrag: function(x, y) { },
35258
35259     
35260     startDrag: function(x, y) {  },
35261
35262     
35263     b4Drag: function(e) { },
35264
35265     
35266     onDrag: function(e) {  },
35267
35268     
35269     onDragEnter: function(e, id) {  },
35270
35271     
35272     b4DragOver: function(e) { },
35273
35274     
35275     onDragOver: function(e, id) {  },
35276
35277     
35278     b4DragOut: function(e) { },
35279
35280     
35281     onDragOut: function(e, id) {  },
35282
35283     
35284     b4DragDrop: function(e) { },
35285
35286     
35287     onDragDrop: function(e, id) {  },
35288
35289     
35290     onInvalidDrop: function(e) {  },
35291
35292     
35293     b4EndDrag: function(e) { },
35294
35295     
35296     endDrag: function(e) {  },
35297
35298     
35299     b4MouseDown: function(e) {  },
35300
35301     
35302     onMouseDown: function(e) {  },
35303
35304     
35305     onMouseUp: function(e) {  },
35306
35307     
35308     onAvailable: function () {
35309     },
35310
35311     
35312     defaultPadding: {
35313         left: 0,
35314         right: 0,
35315         top: 0,
35316         bottom: 0
35317     },
35318
35319     
35320     constrainTo : function(constrainTo, pad, inContent){
35321         if(Ext.isNumber(pad)){
35322             pad = {left: pad, right:pad, top:pad, bottom:pad};
35323         }
35324         pad = pad || this.defaultPadding;
35325         var b = Ext.get(this.getEl()).getBox(),
35326             ce = Ext.get(constrainTo),
35327             s = ce.getScroll(),
35328             c, 
35329             cd = ce.dom;
35330         if(cd == document.body){
35331             c = { x: s.left, y: s.top, width: Ext.core.Element.getViewWidth(), height: Ext.core.Element.getViewHeight()};
35332         }else{
35333             var xy = ce.getXY();
35334             c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
35335         }
35336
35337
35338         var topSpace = b.y - c.y,
35339             leftSpace = b.x - c.x;
35340
35341         this.resetConstraints();
35342         this.setXConstraint(leftSpace - (pad.left||0), 
35343                 c.width - leftSpace - b.width - (pad.right||0), 
35344                                 this.xTickSize
35345         );
35346         this.setYConstraint(topSpace - (pad.top||0), 
35347                 c.height - topSpace - b.height - (pad.bottom||0), 
35348                                 this.yTickSize
35349         );
35350     },
35351
35352     
35353     getEl: function() {
35354         if (!this._domRef) {
35355             this._domRef = Ext.getDom(this.id);
35356         }
35357
35358         return this._domRef;
35359     },
35360
35361     
35362     getDragEl: function() {
35363         return Ext.getDom(this.dragElId);
35364     },
35365
35366     
35367     init: function(id, sGroup, config) {
35368         this.initTarget(id, sGroup, config);
35369         Ext.EventManager.on(this.id, "mousedown", this.handleMouseDown, this);
35370         
35371     },
35372
35373     
35374     initTarget: function(id, sGroup, config) {
35375
35376         
35377         this.config = config || {};
35378
35379         
35380         this.DDMInstance = Ext.dd.DragDropManager;
35381         
35382         this.groups = {};
35383
35384         
35385         
35386         if (typeof id !== "string") {
35387             id = Ext.id(id);
35388         }
35389
35390         
35391         this.id = id;
35392
35393         
35394         this.addToGroup((sGroup) ? sGroup : "default");
35395
35396         
35397         
35398         this.handleElId = id;
35399
35400         
35401         this.setDragElId(id);
35402
35403         
35404         this.invalidHandleTypes = { A: "A" };
35405         this.invalidHandleIds = {};
35406         this.invalidHandleClasses = [];
35407
35408         this.applyConfig();
35409
35410         this.handleOnAvailable();
35411     },
35412
35413     
35414     applyConfig: function() {
35415
35416         
35417         
35418         this.padding           = this.config.padding || [0, 0, 0, 0];
35419         this.isTarget          = (this.config.isTarget !== false);
35420         this.maintainOffset    = (this.config.maintainOffset);
35421         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
35422
35423     },
35424
35425     
35426     handleOnAvailable: function() {
35427         this.available = true;
35428         this.resetConstraints();
35429         this.onAvailable();
35430     },
35431
35432      
35433     setPadding: function(iTop, iRight, iBot, iLeft) {
35434         
35435         if (!iRight && 0 !== iRight) {
35436             this.padding = [iTop, iTop, iTop, iTop];
35437         } else if (!iBot && 0 !== iBot) {
35438             this.padding = [iTop, iRight, iTop, iRight];
35439         } else {
35440             this.padding = [iTop, iRight, iBot, iLeft];
35441         }
35442     },
35443
35444     
35445     setInitPosition: function(diffX, diffY) {
35446         var el = this.getEl();
35447
35448         if (!this.DDMInstance.verifyEl(el)) {
35449             return;
35450         }
35451
35452         var dx = diffX || 0;
35453         var dy = diffY || 0;
35454
35455         var p = Ext.core.Element.getXY( el );
35456
35457         this.initPageX = p[0] - dx;
35458         this.initPageY = p[1] - dy;
35459
35460         this.lastPageX = p[0];
35461         this.lastPageY = p[1];
35462
35463         this.setStartPosition(p);
35464     },
35465
35466     
35467     setStartPosition: function(pos) {
35468         var p = pos || Ext.core.Element.getXY( this.getEl() );
35469         this.deltaSetXY = null;
35470
35471         this.startPageX = p[0];
35472         this.startPageY = p[1];
35473     },
35474
35475     
35476     addToGroup: function(sGroup) {
35477         this.groups[sGroup] = true;
35478         this.DDMInstance.regDragDrop(this, sGroup);
35479     },
35480
35481     
35482     removeFromGroup: function(sGroup) {
35483         if (this.groups[sGroup]) {
35484             delete this.groups[sGroup];
35485         }
35486
35487         this.DDMInstance.removeDDFromGroup(this, sGroup);
35488     },
35489
35490     
35491     setDragElId: function(id) {
35492         this.dragElId = id;
35493     },
35494
35495     
35496     setHandleElId: function(id) {
35497         if (typeof id !== "string") {
35498             id = Ext.id(id);
35499         }
35500         this.handleElId = id;
35501         this.DDMInstance.regHandle(this.id, id);
35502     },
35503
35504     
35505     setOuterHandleElId: function(id) {
35506         if (typeof id !== "string") {
35507             id = Ext.id(id);
35508         }
35509         Ext.EventManager.on(id, "mousedown", this.handleMouseDown, this);
35510         this.setHandleElId(id);
35511
35512         this.hasOuterHandles = true;
35513     },
35514
35515     
35516     unreg: function() {
35517         Ext.EventManager.un(this.id, "mousedown", this.handleMouseDown, this);
35518         this._domRef = null;
35519         this.DDMInstance._remove(this);
35520     },
35521
35522     destroy : function(){
35523         this.unreg();
35524     },
35525
35526     
35527     isLocked: function() {
35528         return (this.DDMInstance.isLocked() || this.locked);
35529     },
35530
35531     
35532     handleMouseDown: function(e, oDD){
35533         if (this.primaryButtonOnly && e.button != 0) {
35534             return;
35535         }
35536
35537         if (this.isLocked()) {
35538             return;
35539         }
35540
35541         this.DDMInstance.refreshCache(this.groups);
35542
35543         var pt = e.getPoint();
35544         if (!this.hasOuterHandles && !this.DDMInstance.isOverTarget(pt, this) )  {
35545         } else {
35546             if (this.clickValidator(e)) {
35547                 
35548                 this.setStartPosition();
35549                 this.b4MouseDown(e);
35550                 this.onMouseDown(e);
35551
35552                 this.DDMInstance.handleMouseDown(e, this);
35553
35554                 this.DDMInstance.stopEvent(e);
35555             } else {
35556
35557
35558             }
35559         }
35560     },
35561
35562     clickValidator: function(e) {
35563         var target = e.getTarget();
35564         return ( this.isValidHandleChild(target) &&
35565                     (this.id == this.handleElId ||
35566                         this.DDMInstance.handleWasClicked(target, this.id)) );
35567     },
35568
35569     
35570     addInvalidHandleType: function(tagName) {
35571         var type = tagName.toUpperCase();
35572         this.invalidHandleTypes[type] = type;
35573     },
35574
35575     
35576     addInvalidHandleId: function(id) {
35577         if (typeof id !== "string") {
35578             id = Ext.id(id);
35579         }
35580         this.invalidHandleIds[id] = id;
35581     },
35582
35583     
35584     addInvalidHandleClass: function(cssClass) {
35585         this.invalidHandleClasses.push(cssClass);
35586     },
35587
35588     
35589     removeInvalidHandleType: function(tagName) {
35590         var type = tagName.toUpperCase();
35591         
35592         delete this.invalidHandleTypes[type];
35593     },
35594
35595     
35596     removeInvalidHandleId: function(id) {
35597         if (typeof id !== "string") {
35598             id = Ext.id(id);
35599         }
35600         delete this.invalidHandleIds[id];
35601     },
35602
35603     
35604     removeInvalidHandleClass: function(cssClass) {
35605         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
35606             if (this.invalidHandleClasses[i] == cssClass) {
35607                 delete this.invalidHandleClasses[i];
35608             }
35609         }
35610     },
35611
35612     
35613     isValidHandleChild: function(node) {
35614
35615         var valid = true;
35616         
35617         var nodeName;
35618         try {
35619             nodeName = node.nodeName.toUpperCase();
35620         } catch(e) {
35621             nodeName = node.nodeName;
35622         }
35623         valid = valid && !this.invalidHandleTypes[nodeName];
35624         valid = valid && !this.invalidHandleIds[node.id];
35625
35626         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
35627             valid = !Ext.fly(node).hasCls(this.invalidHandleClasses[i]);
35628         }
35629
35630
35631         return valid;
35632
35633     },
35634
35635     
35636     setXTicks: function(iStartX, iTickSize) {
35637         this.xTicks = [];
35638         this.xTickSize = iTickSize;
35639
35640         var tickMap = {};
35641
35642         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
35643             if (!tickMap[i]) {
35644                 this.xTicks[this.xTicks.length] = i;
35645                 tickMap[i] = true;
35646             }
35647         }
35648
35649         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
35650             if (!tickMap[i]) {
35651                 this.xTicks[this.xTicks.length] = i;
35652                 tickMap[i] = true;
35653             }
35654         }
35655
35656         Ext.Array.sort(this.xTicks, this.DDMInstance.numericSort);
35657     },
35658
35659     
35660     setYTicks: function(iStartY, iTickSize) {
35661         this.yTicks = [];
35662         this.yTickSize = iTickSize;
35663
35664         var tickMap = {};
35665
35666         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
35667             if (!tickMap[i]) {
35668                 this.yTicks[this.yTicks.length] = i;
35669                 tickMap[i] = true;
35670             }
35671         }
35672
35673         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
35674             if (!tickMap[i]) {
35675                 this.yTicks[this.yTicks.length] = i;
35676                 tickMap[i] = true;
35677             }
35678         }
35679
35680         Ext.Array.sort(this.yTicks, this.DDMInstance.numericSort);
35681     },
35682
35683     
35684     setXConstraint: function(iLeft, iRight, iTickSize) {
35685         this.leftConstraint = iLeft;
35686         this.rightConstraint = iRight;
35687
35688         this.minX = this.initPageX - iLeft;
35689         this.maxX = this.initPageX + iRight;
35690         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
35691
35692         this.constrainX = true;
35693     },
35694
35695     
35696     clearConstraints: function() {
35697         this.constrainX = false;
35698         this.constrainY = false;
35699         this.clearTicks();
35700     },
35701
35702     
35703     clearTicks: function() {
35704         this.xTicks = null;
35705         this.yTicks = null;
35706         this.xTickSize = 0;
35707         this.yTickSize = 0;
35708     },
35709
35710     
35711     setYConstraint: function(iUp, iDown, iTickSize) {
35712         this.topConstraint = iUp;
35713         this.bottomConstraint = iDown;
35714
35715         this.minY = this.initPageY - iUp;
35716         this.maxY = this.initPageY + iDown;
35717         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
35718
35719         this.constrainY = true;
35720
35721     },
35722
35723     
35724     resetConstraints: function() {
35725         
35726         if (this.initPageX || this.initPageX === 0) {
35727             
35728             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
35729             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
35730
35731             this.setInitPosition(dx, dy);
35732
35733         
35734         } else {
35735             this.setInitPosition();
35736         }
35737
35738         if (this.constrainX) {
35739             this.setXConstraint( this.leftConstraint,
35740                                  this.rightConstraint,
35741                                  this.xTickSize        );
35742         }
35743
35744         if (this.constrainY) {
35745             this.setYConstraint( this.topConstraint,
35746                                  this.bottomConstraint,
35747                                  this.yTickSize         );
35748         }
35749     },
35750
35751     
35752     getTick: function(val, tickArray) {
35753         if (!tickArray) {
35754             
35755             
35756             return val;
35757         } else if (tickArray[0] >= val) {
35758             
35759             
35760             return tickArray[0];
35761         } else {
35762             for (var i=0, len=tickArray.length; i<len; ++i) {
35763                 var next = i + 1;
35764                 if (tickArray[next] && tickArray[next] >= val) {
35765                     var diff1 = val - tickArray[i];
35766                     var diff2 = tickArray[next] - val;
35767                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];
35768                 }
35769             }
35770
35771             
35772             
35773             return tickArray[tickArray.length - 1];
35774         }
35775     },
35776
35777     
35778     toString: function() {
35779         return ("DragDrop " + this.id);
35780     }
35781
35782 });
35783
35784
35785
35786
35787
35788 Ext.define('Ext.dd.DD', {
35789     extend: 'Ext.dd.DragDrop',
35790     requires: ['Ext.dd.DragDropManager'],
35791     constructor: function(id, sGroup, config) {
35792         if (id) {
35793             this.init(id, sGroup, config);
35794         }
35795     },
35796
35797     
35798     scroll: true,
35799
35800     
35801     autoOffset: function(iPageX, iPageY) {
35802         var x = iPageX - this.startPageX;
35803         var y = iPageY - this.startPageY;
35804         this.setDelta(x, y);
35805     },
35806
35807     
35808     setDelta: function(iDeltaX, iDeltaY) {
35809         this.deltaX = iDeltaX;
35810         this.deltaY = iDeltaY;
35811     },
35812
35813     
35814     setDragElPos: function(iPageX, iPageY) {
35815         
35816         
35817
35818         var el = this.getDragEl();
35819         this.alignElWithMouse(el, iPageX, iPageY);
35820     },
35821
35822     
35823     alignElWithMouse: function(el, iPageX, iPageY) {
35824         var oCoord = this.getTargetCoord(iPageX, iPageY),
35825             fly = el.dom ? el : Ext.fly(el, '_dd'),
35826             elSize = fly.getSize(),
35827             EL = Ext.core.Element,
35828             vpSize;
35829
35830         if (!this.deltaSetXY) {
35831             vpSize = this.cachedViewportSize = { width: EL.getDocumentWidth(), height: EL.getDocumentHeight() };
35832             var aCoord = [
35833                 Math.max(0, Math.min(oCoord.x, vpSize.width - elSize.width)),
35834                 Math.max(0, Math.min(oCoord.y, vpSize.height - elSize.height))
35835             ];
35836             fly.setXY(aCoord);
35837             var newLeft = fly.getLeft(true);
35838             var newTop  = fly.getTop(true);
35839             this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
35840         } else {
35841             vpSize = this.cachedViewportSize;
35842             fly.setLeftTop(
35843                 Math.max(0, Math.min(oCoord.x + this.deltaSetXY[0], vpSize.width - elSize.width)),
35844                 Math.max(0, Math.min(oCoord.y + this.deltaSetXY[1], vpSize.height - elSize.height))
35845             );
35846         }
35847
35848         this.cachePosition(oCoord.x, oCoord.y);
35849         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
35850         return oCoord;
35851     },
35852
35853     
35854     cachePosition: function(iPageX, iPageY) {
35855         if (iPageX) {
35856             this.lastPageX = iPageX;
35857             this.lastPageY = iPageY;
35858         } else {
35859             var aCoord = Ext.core.Element.getXY(this.getEl());
35860             this.lastPageX = aCoord[0];
35861             this.lastPageY = aCoord[1];
35862         }
35863     },
35864
35865     
35866     autoScroll: function(x, y, h, w) {
35867
35868         if (this.scroll) {
35869             
35870             var clientH = Ext.core.Element.getViewHeight();
35871
35872             
35873             var clientW = Ext.core.Element.getViewWidth();
35874
35875             
35876             var st = this.DDMInstance.getScrollTop();
35877
35878             
35879             var sl = this.DDMInstance.getScrollLeft();
35880
35881             
35882             var bot = h + y;
35883
35884             
35885             var right = w + x;
35886
35887             
35888             
35889             
35890             var toBot = (clientH + st - y - this.deltaY);
35891
35892             
35893             var toRight = (clientW + sl - x - this.deltaX);
35894
35895
35896             
35897             
35898             var thresh = 40;
35899
35900             
35901             
35902             
35903             var scrAmt = (document.all) ? 80 : 30;
35904
35905             
35906             
35907             if ( bot > clientH && toBot < thresh ) {
35908                 window.scrollTo(sl, st + scrAmt);
35909             }
35910
35911             
35912             
35913             if ( y < st && st > 0 && y - st < thresh ) {
35914                 window.scrollTo(sl, st - scrAmt);
35915             }
35916
35917             
35918             
35919             if ( right > clientW && toRight < thresh ) {
35920                 window.scrollTo(sl + scrAmt, st);
35921             }
35922
35923             
35924             
35925             if ( x < sl && sl > 0 && x - sl < thresh ) {
35926                 window.scrollTo(sl - scrAmt, st);
35927             }
35928         }
35929     },
35930
35931     
35932     getTargetCoord: function(iPageX, iPageY) {
35933         var x = iPageX - this.deltaX;
35934         var y = iPageY - this.deltaY;
35935
35936         if (this.constrainX) {
35937             if (x < this.minX) {
35938                 x = this.minX;
35939             }
35940             if (x > this.maxX) {
35941                 x = this.maxX;
35942             }
35943         }
35944
35945         if (this.constrainY) {
35946             if (y < this.minY) {
35947                 y = this.minY;
35948             }
35949             if (y > this.maxY) {
35950                 y = this.maxY;
35951             }
35952         }
35953
35954         x = this.getTick(x, this.xTicks);
35955         y = this.getTick(y, this.yTicks);
35956
35957
35958         return {x: x, y: y};
35959     },
35960
35961     
35962     applyConfig: function() {
35963         this.callParent();
35964         this.scroll = (this.config.scroll !== false);
35965     },
35966
35967     
35968     b4MouseDown: function(e) {
35969         
35970         this.autoOffset(e.getPageX(), e.getPageY());
35971     },
35972
35973     
35974     b4Drag: function(e) {
35975         this.setDragElPos(e.getPageX(), e.getPageY());
35976     },
35977
35978     toString: function() {
35979         return ("DD " + this.id);
35980     }
35981
35982     
35983     
35984     
35985     
35986
35987 });
35988
35989
35990
35991
35992 Ext.define('Ext.dd.DDProxy', {
35993     extend: 'Ext.dd.DD',
35994
35995     statics: {
35996         
35997         dragElId: "ygddfdiv"
35998     },
35999
36000     constructor: function(id, sGroup, config) {
36001         if (id) {
36002             this.init(id, sGroup, config);
36003             this.initFrame();
36004         }
36005     },
36006
36007     
36008     resizeFrame: true,
36009
36010     
36011     centerFrame: false,
36012
36013     
36014     createFrame: function() {
36015         var self = this;
36016         var body = document.body;
36017
36018         if (!body || !body.firstChild) {
36019             setTimeout( function() { self.createFrame(); }, 50 );
36020             return;
36021         }
36022
36023         var div = this.getDragEl();
36024
36025         if (!div) {
36026             div    = document.createElement("div");
36027             div.id = this.dragElId;
36028             var s  = div.style;
36029
36030             s.position   = "absolute";
36031             s.visibility = "hidden";
36032             s.cursor     = "move";
36033             s.border     = "2px solid #aaa";
36034             s.zIndex     = 999;
36035
36036             
36037             
36038             
36039             body.insertBefore(div, body.firstChild);
36040         }
36041     },
36042
36043     
36044     initFrame: function() {
36045         this.createFrame();
36046     },
36047
36048     applyConfig: function() {
36049         this.callParent();
36050
36051         this.resizeFrame = (this.config.resizeFrame !== false);
36052         this.centerFrame = (this.config.centerFrame);
36053         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
36054     },
36055
36056     
36057     showFrame: function(iPageX, iPageY) {
36058         var el = this.getEl();
36059         var dragEl = this.getDragEl();
36060         var s = dragEl.style;
36061
36062         this._resizeProxy();
36063
36064         if (this.centerFrame) {
36065             this.setDelta( Math.round(parseInt(s.width,  10)/2),
36066                            Math.round(parseInt(s.height, 10)/2) );
36067         }
36068
36069         this.setDragElPos(iPageX, iPageY);
36070
36071         Ext.fly(dragEl).show();
36072     },
36073
36074     
36075     _resizeProxy: function() {
36076         if (this.resizeFrame) {
36077             var el = this.getEl();
36078             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
36079         }
36080     },
36081
36082     
36083     b4MouseDown: function(e) {
36084         var x = e.getPageX();
36085         var y = e.getPageY();
36086         this.autoOffset(x, y);
36087         this.setDragElPos(x, y);
36088     },
36089
36090     
36091     b4StartDrag: function(x, y) {
36092         
36093         this.showFrame(x, y);
36094     },
36095
36096     
36097     b4EndDrag: function(e) {
36098         Ext.fly(this.getDragEl()).hide();
36099     },
36100
36101     
36102     
36103     
36104     endDrag: function(e) {
36105
36106         var lel = this.getEl();
36107         var del = this.getDragEl();
36108
36109         
36110         del.style.visibility = "";
36111
36112         this.beforeMove();
36113         
36114         
36115         lel.style.visibility = "hidden";
36116         Ext.dd.DDM.moveToEl(lel, del);
36117         del.style.visibility = "hidden";
36118         lel.style.visibility = "";
36119
36120         this.afterDrag();
36121     },
36122
36123     beforeMove : function(){
36124
36125     },
36126
36127     afterDrag : function(){
36128
36129     },
36130
36131     toString: function() {
36132         return ("DDProxy " + this.id);
36133     }
36134
36135 });
36136
36137
36138 Ext.define('Ext.dd.DragSource', {
36139     extend: 'Ext.dd.DDProxy',
36140     requires: [
36141         'Ext.dd.StatusProxy',
36142         'Ext.dd.DragDropManager'
36143     ],
36144
36145     
36146
36147     
36148
36149     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
36150     
36151     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
36152
36153     
36154     animRepair: true,
36155
36156     
36157     repairHighlightColor: 'c3daf9',
36158
36159     constructor: function(el, config) {
36160         this.el = Ext.get(el);
36161         if(!this.dragData){
36162             this.dragData = {};
36163         }
36164
36165         Ext.apply(this, config);
36166
36167         if(!this.proxy){
36168             this.proxy = Ext.create('Ext.dd.StatusProxy', {
36169                 animRepair: this.animRepair
36170             });
36171         }
36172         this.callParent([this.el.dom, this.ddGroup || this.group,
36173               {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true}]);
36174
36175         this.dragging = false;
36176     },
36177
36178     
36179     getDragData : function(e){
36180         return this.dragData;
36181     },
36182
36183     
36184     onDragEnter : function(e, id){
36185         var target = Ext.dd.DragDropManager.getDDById(id);
36186         this.cachedTarget = target;
36187         if (this.beforeDragEnter(target, e, id) !== false) {
36188             if (target.isNotifyTarget) {
36189                 var status = target.notifyEnter(this, e, this.dragData);
36190                 this.proxy.setStatus(status);
36191             } else {
36192                 this.proxy.setStatus(this.dropAllowed);
36193             }
36194
36195             if (this.afterDragEnter) {
36196                 
36197                 this.afterDragEnter(target, e, id);
36198             }
36199         }
36200     },
36201
36202     
36203     beforeDragEnter: function(target, e, id) {
36204         return true;
36205     },
36206
36207     
36208     alignElWithMouse: function() {
36209         this.callParent(arguments);
36210         this.proxy.sync();
36211     },
36212
36213     
36214     onDragOver: function(e, id) {
36215         var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
36216         if (this.beforeDragOver(target, e, id) !== false) {
36217             if(target.isNotifyTarget){
36218                 var status = target.notifyOver(this, e, this.dragData);
36219                 this.proxy.setStatus(status);
36220             }
36221
36222             if (this.afterDragOver) {
36223                 
36224                 this.afterDragOver(target, e, id);
36225             }
36226         }
36227     },
36228
36229     
36230     beforeDragOver: function(target, e, id) {
36231         return true;
36232     },
36233
36234     
36235     onDragOut: function(e, id) {
36236         var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
36237         if (this.beforeDragOut(target, e, id) !== false) {
36238             if (target.isNotifyTarget) {
36239                 target.notifyOut(this, e, this.dragData);
36240             }
36241             this.proxy.reset();
36242             if (this.afterDragOut) {
36243                 
36244                 this.afterDragOut(target, e, id);
36245             }
36246         }
36247         this.cachedTarget = null;
36248     },
36249
36250     
36251     beforeDragOut: function(target, e, id){
36252         return true;
36253     },
36254
36255     
36256     onDragDrop: function(e, id){
36257         var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
36258         if (this.beforeDragDrop(target, e, id) !== false) {
36259             if (target.isNotifyTarget) {
36260                 if (target.notifyDrop(this, e, this.dragData) !== false) { 
36261                     this.onValidDrop(target, e, id);
36262                 } else {
36263                     this.onInvalidDrop(target, e, id);
36264                 }
36265             } else {
36266                 this.onValidDrop(target, e, id);
36267             }
36268
36269             if (this.afterDragDrop) {
36270                 
36271                 this.afterDragDrop(target, e, id);
36272             }
36273         }
36274         delete this.cachedTarget;
36275     },
36276
36277     
36278     beforeDragDrop: function(target, e, id){
36279         return true;
36280     },
36281
36282     
36283     onValidDrop: function(target, e, id){
36284         this.hideProxy();
36285         if(this.afterValidDrop){
36286             
36287             this.afterValidDrop(target, e, id);
36288         }
36289     },
36290
36291     
36292     getRepairXY: function(e, data){
36293         return this.el.getXY();
36294     },
36295
36296     
36297     onInvalidDrop: function(target, e, id) {
36298         this.beforeInvalidDrop(target, e, id);
36299         if (this.cachedTarget) {
36300             if(this.cachedTarget.isNotifyTarget){
36301                 this.cachedTarget.notifyOut(this, e, this.dragData);
36302             }
36303             this.cacheTarget = null;
36304         }
36305         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
36306
36307         if (this.afterInvalidDrop) {
36308             
36309             this.afterInvalidDrop(e, id);
36310         }
36311     },
36312
36313     
36314     afterRepair: function() {
36315         var me = this;
36316         if (Ext.enableFx) {
36317             me.el.highlight(me.repairHighlightColor);
36318         }
36319         me.dragging = false;
36320     },
36321
36322     
36323     beforeInvalidDrop: function(target, e, id) {
36324         return true;
36325     },
36326
36327     
36328     handleMouseDown: function(e) {
36329         if (this.dragging) {
36330             return;
36331         }
36332         var data = this.getDragData(e);
36333         if (data && this.onBeforeDrag(data, e) !== false) {
36334             this.dragData = data;
36335             this.proxy.stop();
36336             this.callParent(arguments);
36337         }
36338     },
36339
36340     
36341     onBeforeDrag: function(data, e){
36342         return true;
36343     },
36344
36345     
36346     onStartDrag: Ext.emptyFn,
36347
36348     
36349     startDrag: function(x, y) {
36350         this.proxy.reset();
36351         this.dragging = true;
36352         this.proxy.update("");
36353         this.onInitDrag(x, y);
36354         this.proxy.show();
36355     },
36356
36357     
36358     onInitDrag: function(x, y) {
36359         var clone = this.el.dom.cloneNode(true);
36360         clone.id = Ext.id(); 
36361         this.proxy.update(clone);
36362         this.onStartDrag(x, y);
36363         return true;
36364     },
36365
36366     
36367     getProxy: function() {
36368         return this.proxy;
36369     },
36370
36371     
36372     hideProxy: function() {
36373         this.proxy.hide();
36374         this.proxy.reset(true);
36375         this.dragging = false;
36376     },
36377
36378     
36379     triggerCacheRefresh: function() {
36380         Ext.dd.DDM.refreshCache(this.groups);
36381     },
36382
36383     
36384     b4EndDrag: function(e) {
36385     },
36386
36387     
36388     endDrag : function(e){
36389         this.onEndDrag(this.dragData, e);
36390     },
36391
36392     
36393     onEndDrag : function(data, e){
36394     },
36395
36396     
36397     autoOffset : function(x, y) {
36398         this.setDelta(-12, -20);
36399     },
36400
36401     destroy: function(){
36402         this.callParent();
36403         Ext.destroy(this.proxy);
36404     }
36405 });
36406
36407
36408 Ext.define('Ext.panel.DD', {
36409     extend: 'Ext.dd.DragSource',
36410     requires: ['Ext.panel.Proxy'],
36411
36412     constructor : function(panel, cfg){
36413         this.panel = panel;
36414         this.dragData = {panel: panel};
36415         this.proxy = Ext.create('Ext.panel.Proxy', panel, cfg);
36416
36417         this.callParent([panel.el, cfg]);
36418
36419         Ext.defer(function() {
36420             var header = panel.header,
36421                 el = panel.body;
36422
36423             if(header){
36424                 this.setHandleElId(header.id);
36425                 el = header.el;
36426             }
36427             el.setStyle('cursor', 'move');
36428             this.scroll = false;
36429         }, 200, this);
36430     },
36431
36432     showFrame: Ext.emptyFn,
36433     startDrag: Ext.emptyFn,
36434     b4StartDrag: function(x, y) {
36435         this.proxy.show();
36436     },
36437     b4MouseDown: function(e) {
36438         var x = e.getPageX(),
36439             y = e.getPageY();
36440         this.autoOffset(x, y);
36441     },
36442     onInitDrag : function(x, y){
36443         this.onStartDrag(x, y);
36444         return true;
36445     },
36446     createFrame : Ext.emptyFn,
36447     getDragEl : function(e){
36448         return this.proxy.ghost.el.dom;
36449     },
36450     endDrag : function(e){
36451         this.proxy.hide();
36452         this.panel.saveState();
36453     },
36454
36455     autoOffset : function(x, y) {
36456         x -= this.startPageX;
36457         y -= this.startPageY;
36458         this.setDelta(x, y);
36459     }
36460 });
36461
36462
36463 Ext.define('Ext.layout.component.Dock', {
36464
36465     
36466
36467     alias: ['layout.dock'],
36468
36469     extend: 'Ext.layout.component.AbstractDock'
36470
36471     
36472
36473 });
36474
36475 Ext.define('Ext.panel.Panel', {
36476     extend: 'Ext.panel.AbstractPanel',
36477     requires: [
36478         'Ext.panel.Header',
36479         'Ext.fx.Anim',
36480         'Ext.util.KeyMap',
36481         'Ext.panel.DD',
36482         'Ext.XTemplate',
36483         'Ext.layout.component.Dock'
36484     ],
36485     alias: 'widget.panel',
36486     alternateClassName: 'Ext.Panel',
36487
36488     
36489     collapsedCls: 'collapsed',
36490
36491     
36492     animCollapse: Ext.enableFx,
36493
36494     
36495     minButtonWidth: 75,
36496
36497     
36498     collapsed: false,
36499
36500     
36501     collapseFirst: true,
36502
36503     
36504     hideCollapseTool: false,
36505
36506     
36507     titleCollapse: false,
36508
36509     
36510
36511     
36512
36513     
36514     floatable: true,
36515
36516     
36517     collapsible: false,
36518
36519     
36520
36521     
36522     closable: false,
36523
36524     
36525     closeAction: 'destroy',
36526
36527     
36528
36529     
36530     preventHeader: false,
36531
36532      
36533     headerPosition: 'top',
36534
36535      
36536     frame: false,
36537
36538     
36539     frameHeader: true,
36540
36541     
36542
36543
36544     initComponent: function() {
36545         var me = this,
36546             cls;
36547
36548         me.addEvents(
36549         
36550             'titlechange',
36551         
36552             'iconchange'
36553         );
36554
36555         if (me.unstyled) {
36556             me.setUI('plain');
36557         }
36558
36559         if (me.frame) {
36560             me.setUI('default-framed');
36561         }
36562
36563         me.callParent();
36564
36565         me.collapseDirection = me.collapseDirection || me.headerPosition || Ext.Component.DIRECTION_TOP;
36566
36567         
36568         me.bridgeToolbars();
36569     },
36570
36571     setBorder: function(border) {
36572         
36573         
36574         
36575         
36576         
36577         
36578         
36579         
36580         
36581         
36582         
36583         
36584         
36585         
36586         
36587         
36588         this.callParent(arguments);
36589     },
36590
36591     beforeDestroy: function() {
36592         Ext.destroy(
36593             this.ghostPanel,
36594             this.dd
36595         );
36596         this.callParent();
36597     },
36598
36599     initAria: function() {
36600         this.callParent();
36601         this.initHeaderAria();
36602     },
36603
36604     initHeaderAria: function() {
36605         var me = this,
36606             el = me.el,
36607             header = me.header;
36608         if (el && header) {
36609             el.dom.setAttribute('aria-labelledby', header.titleCmp.id);
36610         }
36611     },
36612
36613     getHeader: function() {
36614         return this.header;
36615     },
36616
36617     
36618     setTitle: function(newTitle) {
36619         var me = this,
36620         oldTitle = this.title;
36621
36622         me.title = newTitle;
36623         if (me.header) {
36624             me.header.setTitle(newTitle);
36625         } else {
36626             me.updateHeader();
36627         }
36628
36629         if (me.reExpander) {
36630             me.reExpander.setTitle(newTitle);
36631         }
36632         me.fireEvent('titlechange', me, newTitle, oldTitle);
36633     },
36634
36635     
36636     setIconCls: function(newIconCls) {
36637         var me = this,
36638             oldIconCls = me.iconCls;
36639
36640         me.iconCls = newIconCls;
36641         var header = me.header;
36642         if (header) {
36643             header.setIconCls(newIconCls);
36644         }
36645         me.fireEvent('iconchange', me, newIconCls, oldIconCls);
36646     },
36647
36648     bridgeToolbars: function() {
36649         var me = this,
36650             fbar,
36651             fbarDefaults,
36652             minButtonWidth = me.minButtonWidth;
36653
36654         function initToolbar (toolbar, pos) {
36655             if (Ext.isArray(toolbar)) {
36656                 toolbar = {
36657                     xtype: 'toolbar',
36658                     items: toolbar
36659                 };
36660             }
36661             else if (!toolbar.xtype) {
36662                 toolbar.xtype = 'toolbar';
36663             }
36664             toolbar.dock = pos;
36665             if (pos == 'left' || pos == 'right') {
36666                 toolbar.vertical = true;
36667             }
36668             return toolbar;
36669         }
36670
36671         
36672
36673         
36674         if (me.tbar) {
36675             me.addDocked(initToolbar(me.tbar, 'top'));
36676             me.tbar = null;
36677         }
36678
36679         
36680         if (me.bbar) {
36681             me.addDocked(initToolbar(me.bbar, 'bottom'));
36682             me.bbar = null;
36683         }
36684
36685         
36686         if (me.buttons) {
36687             me.fbar = me.buttons;
36688             me.buttons = null;
36689         }
36690
36691         
36692         if (me.fbar) {
36693             fbar = initToolbar(me.fbar, 'bottom');
36694             fbar.ui = 'footer';
36695
36696             
36697             if (minButtonWidth) {
36698                 fbarDefaults = fbar.defaults;
36699                 fbar.defaults = function(config) {
36700                     var defaults = fbarDefaults || {};
36701                     if ((!config.xtype || config.xtype === 'button' || (config.isComponent && config.isXType('button'))) &&
36702                             !('minWidth' in defaults)) {
36703                         defaults = Ext.apply({minWidth: minButtonWidth}, defaults);
36704                     }
36705                     return defaults;
36706                 };
36707             }
36708
36709             fbar = me.addDocked(fbar)[0];
36710             fbar.insert(0, {
36711                 flex: 1,
36712                 xtype: 'component',
36713                 focusable: false
36714             });
36715             me.fbar = null;
36716         }
36717
36718         
36719         if (me.lbar) {
36720             me.addDocked(initToolbar(me.lbar, 'left'));
36721             me.lbar = null;
36722         }
36723
36724         
36725         if (me.rbar) {
36726             me.addDocked(initToolbar(me.rbar, 'right'));
36727             me.rbar = null;
36728         }
36729     },
36730
36731     
36732     initTools: function() {
36733         var me = this;
36734
36735         me.tools = me.tools || [];
36736
36737         
36738         
36739         if (me.collapsible && !(me.hideCollapseTool || me.header === false)) {
36740             me.collapseDirection = me.collapseDirection || me.headerPosition || 'top';
36741             me.collapseTool = me.expandTool = me.createComponent({
36742                 xtype: 'tool',
36743                 type: 'collapse-' + me.collapseDirection,
36744                 expandType: me.getOppositeDirection(me.collapseDirection),
36745                 handler: me.toggleCollapse,
36746                 scope: me
36747             });
36748
36749             
36750             if (me.collapseFirst) {
36751                 me.tools.unshift(me.collapseTool);
36752             }
36753         }
36754
36755         
36756         me.addTools();
36757
36758         
36759         if (me.closable) {
36760             me.addClsWithUI('closable');
36761             me.addTool({
36762                 type: 'close',
36763                 handler: Ext.Function.bind(me.close, this, [])
36764             });
36765         }
36766
36767         
36768         if (me.collapseTool && !me.collapseFirst) {
36769             me.tools.push(me.collapseTool);
36770         }
36771     },
36772
36773     
36774     addTools: Ext.emptyFn,
36775
36776     
36777     close: function() {
36778         if (this.fireEvent('beforeclose', this) !== false) {
36779             this.doClose();
36780         }
36781     },
36782
36783     
36784     doClose: function() {
36785         this.fireEvent('close', this);
36786         this[this.closeAction]();
36787     },
36788
36789     onRender: function(ct, position) {
36790         var me = this,
36791             topContainer;
36792
36793         
36794         
36795         me.initTools();
36796
36797         
36798         me.updateHeader();
36799
36800         
36801         
36802         if (me.collapsed) {
36803             me.collapsed = false;
36804             topContainer = me.findLayoutController();
36805             if (!me.hidden && topContainer) {
36806                 topContainer.on({
36807                     afterlayout: function() {
36808                         me.collapse(null, false, true);
36809                     },
36810                     single: true
36811                 });
36812             } else {
36813                 me.afterComponentLayout = function() {
36814                     delete me.afterComponentLayout;
36815                     Ext.getClass(me).prototype.afterComponentLayout.apply(me, arguments);
36816                     me.collapse(null, false, true);
36817                 };
36818             }
36819         }
36820
36821         
36822         me.callParent(arguments);
36823     },
36824
36825     
36826     updateHeader: function(force) {
36827         var me = this,
36828             header = me.header,
36829             title = me.title,
36830             tools = me.tools;
36831
36832         if (!me.preventHeader && (force || title || (tools && tools.length))) {
36833             if (!header) {
36834                 header = me.header = Ext.create('Ext.panel.Header', {
36835                     title       : title,
36836                     orientation : (me.headerPosition == 'left' || me.headerPosition == 'right') ? 'vertical' : 'horizontal',
36837                     dock        : me.headerPosition || 'top',
36838                     textCls     : me.headerTextCls,
36839                     iconCls     : me.iconCls,
36840                     baseCls     : me.baseCls + '-header',
36841                     tools       : tools,
36842                     ui          : me.ui,
36843                     indicateDrag: me.draggable,
36844                     border      : me.border,
36845                     frame       : me.frame && me.frameHeader,
36846                     ignoreParentFrame : me.frame || me.overlapHeader,
36847                     ignoreBorderManagement: me.frame || me.ignoreHeaderBorderManagement,
36848                     listeners   : me.collapsible && me.titleCollapse ? {
36849                         click: me.toggleCollapse,
36850                         scope: me
36851                     } : null
36852                 });
36853                 me.addDocked(header, 0);
36854
36855                 
36856                 
36857                 me.tools = header.tools;
36858             }
36859             header.show();
36860             me.initHeaderAria();
36861         } else if (header) {
36862             header.hide();
36863         }
36864     },
36865
36866     
36867     setUI: function(ui) {
36868         var me = this;
36869
36870         me.callParent(arguments);
36871
36872         if (me.header) {
36873             me.header.setUI(ui);
36874         }
36875     },
36876
36877     
36878     getContentTarget: function() {
36879         return this.body;
36880     },
36881
36882     getTargetEl: function() {
36883         return this.body || this.frameBody || this.el;
36884     },
36885
36886     addTool: function(tool) {
36887         this.tools.push(tool);
36888         var header = this.header;
36889         if (header) {
36890             header.addTool(tool);
36891         }
36892         this.updateHeader();
36893     },
36894
36895     getOppositeDirection: function(d) {
36896         var c = Ext.Component;
36897         switch (d) {
36898             case c.DIRECTION_TOP:
36899                 return c.DIRECTION_BOTTOM;
36900             case c.DIRECTION_RIGHT:
36901                 return c.DIRECTION_LEFT;
36902             case c.DIRECTION_BOTTOM:
36903                 return c.DIRECTION_TOP;
36904             case c.DIRECTION_LEFT:
36905                 return c.DIRECTION_RIGHT;
36906         }
36907     },
36908
36909     
36910     collapse: function(direction, animate,  internal) {
36911         var me = this,
36912             c = Ext.Component,
36913             height = me.getHeight(),
36914             width = me.getWidth(),
36915             frameInfo,
36916             newSize = 0,
36917             dockedItems = me.dockedItems.items,
36918             dockedItemCount = dockedItems.length,
36919             i = 0,
36920             comp,
36921             pos,
36922             anim = {
36923                 from: {
36924                     height: height,
36925                     width: width
36926                 },
36927                 to: {
36928                     height: height,
36929                     width: width
36930                 },
36931                 listeners: {
36932                     afteranimate: me.afterCollapse,
36933                     scope: me
36934                 },
36935                 duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration)
36936             },
36937             reExpander,
36938             reExpanderOrientation,
36939             reExpanderDock,
36940             getDimension,
36941             setDimension,
36942             collapseDimension;
36943
36944         if (!direction) {
36945             direction = me.collapseDirection;
36946         }
36947
36948         
36949         if (internal) {
36950             animate = false;
36951         } else if (me.collapsed || me.fireEvent('beforecollapse', me, direction, animate) === false) {
36952             return false;
36953         }
36954
36955         reExpanderDock = direction;
36956         me.expandDirection = me.getOppositeDirection(direction);
36957
36958         
36959         me.hiddenDocked = [];
36960
36961         switch (direction) {
36962             case c.DIRECTION_TOP:
36963             case c.DIRECTION_BOTTOM:
36964                 me.expandedSize = me.getHeight();
36965                 reExpanderOrientation = 'horizontal';
36966                 collapseDimension = 'height';
36967                 getDimension = 'getHeight';
36968                 setDimension = 'setHeight';
36969
36970                 
36971                 
36972                 
36973                 for (; i < dockedItemCount; i++) {
36974                     comp = dockedItems[i];
36975                     if (comp.isVisible()) {
36976                         if (comp.isHeader && (!comp.dock || comp.dock == 'top' || comp.dock == 'bottom')) {
36977                             reExpander = comp;
36978                         } else {
36979                             me.hiddenDocked.push(comp);
36980                         }
36981                     }
36982                 }
36983
36984                 if (direction == Ext.Component.DIRECTION_BOTTOM) {
36985                     pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
36986                     anim.from.top = pos;
36987                 }
36988                 break;
36989
36990             case c.DIRECTION_LEFT:
36991             case c.DIRECTION_RIGHT:
36992                 me.expandedSize = me.getWidth();
36993                 reExpanderOrientation = 'vertical';
36994                 collapseDimension = 'width';
36995                 getDimension = 'getWidth';
36996                 setDimension = 'setWidth';
36997
36998                 
36999                 
37000                 
37001                 for (; i < dockedItemCount; i++) {
37002                     comp = dockedItems[i];
37003                     if (comp.isVisible()) {
37004                         if (comp.isHeader && (comp.dock == 'left' || comp.dock == 'right')) {
37005                             reExpander = comp;
37006                         } else {
37007                             me.hiddenDocked.push(comp);
37008                         }
37009                     }
37010                 }
37011
37012                 if (direction == Ext.Component.DIRECTION_RIGHT) {
37013                     pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
37014                     anim.from.left = pos;
37015                 }
37016                 break;
37017
37018             default:
37019                 throw('Panel collapse must be passed a valid Component collapse direction');
37020         }
37021
37022         
37023         
37024         me.setAutoScroll(false);
37025         me.suspendLayout = true;
37026         me.body.setVisibilityMode(Ext.core.Element.DISPLAY);
37027
37028         
37029         if (animate && me.collapseTool) {
37030             me.collapseTool.disable();
37031         }
37032
37033         
37034         me.addClsWithUI(me.collapsedCls);
37035         
37036         
37037         
37038
37039         
37040         if (reExpander) {
37041             
37042             reExpander.addClsWithUI(me.collapsedCls);
37043             reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
37044             if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
37045                 reExpander.addClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
37046             }
37047
37048             frameInfo = reExpander.getFrameInfo();
37049                         
37050             
37051             newSize = reExpander[getDimension]() + (frameInfo ? frameInfo[direction] : 0);
37052
37053             
37054             reExpander.removeClsWithUI(me.collapsedCls);
37055             reExpander.removeClsWithUI(me.collapsedCls + '-' + reExpander.dock);              
37056             if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
37057                 reExpander.removeClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
37058             }
37059         }
37060         
37061         else {
37062             reExpander = {
37063                 hideMode: 'offsets',
37064                 temporary: true,
37065                 title: me.title,
37066                 orientation: reExpanderOrientation,
37067                 dock: reExpanderDock,
37068                 textCls: me.headerTextCls,
37069                 iconCls: me.iconCls,
37070                 baseCls: me.baseCls + '-header',
37071                 ui: me.ui,
37072                 frame: me.frame && me.frameHeader,
37073                 ignoreParentFrame: me.frame || me.overlapHeader,
37074                 indicateDrag: me.draggable,
37075                 cls: me.baseCls + '-collapsed-placeholder ' + ' ' + Ext.baseCSSPrefix + 'docked ' + me.baseCls + '-' + me.ui + '-collapsed',
37076                 renderTo: me.el
37077             };
37078             reExpander[(reExpander.orientation == 'horizontal') ? 'tools' : 'items'] = [{
37079                 xtype: 'tool',
37080                 type: 'expand-' + me.expandDirection,
37081                 handler: me.toggleCollapse,
37082                 scope: me
37083             }];
37084
37085             
37086             
37087             reExpander = me.reExpander = Ext.create('Ext.panel.Header', reExpander);
37088             newSize = reExpander[getDimension]() + ((reExpander.frame) ? reExpander.frameSize[direction] : 0);
37089             reExpander.hide();
37090
37091             
37092             me.insertDocked(0, reExpander);
37093         }
37094
37095         me.reExpander = reExpander;
37096         me.reExpander.addClsWithUI(me.collapsedCls);
37097         me.reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
37098         if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
37099             me.reExpander.addClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
37100         }
37101
37102         
37103         if (direction == Ext.Component.DIRECTION_RIGHT) {
37104             anim.to.left = pos + (width - newSize);
37105         } else if (direction == Ext.Component.DIRECTION_BOTTOM) {
37106             anim.to.top = pos + (height - newSize);
37107         }
37108
37109         
37110         anim.to[collapseDimension] = newSize;
37111
37112         
37113         me.savedFlex = me.flex;
37114         me.savedMinWidth = me.minWidth;
37115         me.savedMinHeight = me.minHeight;
37116         me.minWidth = 0;
37117         me.minHeight = 0;
37118         delete me.flex;
37119
37120         if (animate) {
37121             me.animate(anim);
37122         } else {
37123             me.setSize(anim.to.width, anim.to.height);
37124             if (Ext.isDefined(anim.to.left) || Ext.isDefined(anim.to.top)) {
37125                 me.setPosition(anim.to.left, anim.to.top);
37126             }
37127             me.afterCollapse(false, internal);
37128         }
37129         return me;
37130     },
37131
37132     afterCollapse: function(animated, internal) {
37133         var me = this,
37134             i = 0,
37135             l = me.hiddenDocked.length;
37136
37137         me.minWidth = me.savedMinWidth;
37138         me.minHeight = me.savedMinHeight;
37139
37140         me.body.hide();
37141         for (; i < l; i++) {
37142             me.hiddenDocked[i].hide();
37143         }
37144         if (me.reExpander) {
37145             me.reExpander.updateFrame();
37146             me.reExpander.show();
37147         }
37148         me.collapsed = true;
37149
37150         if (!internal) {
37151             me.doComponentLayout();
37152         }
37153
37154         if (me.resizer) {
37155             me.resizer.disable();
37156         }
37157
37158         
37159         if (me.collapseTool) {
37160             me.collapseTool.setType('expand-' + me.expandDirection);
37161         }
37162         if (!internal) {
37163             me.fireEvent('collapse', me);
37164         }
37165
37166         
37167         if (animated && me.collapseTool) {
37168             me.collapseTool.enable();
37169         }
37170     },
37171
37172     
37173     expand: function(animate) {
37174         if (!this.collapsed || this.fireEvent('beforeexpand', this, animate) === false) {
37175             return false;
37176         }
37177         var me = this,
37178             i = 0,
37179             l = me.hiddenDocked.length,
37180             direction = me.expandDirection,
37181             height = me.getHeight(),
37182             width = me.getWidth(),
37183             pos, anim, satisfyJSLint;
37184
37185         
37186         if (animate && me.collapseTool) {
37187             me.collapseTool.disable();
37188         }
37189
37190         
37191         
37192         for (; i < l; i++) {
37193             me.hiddenDocked[i].hidden = false;
37194             me.hiddenDocked[i].el.show();
37195         }
37196         if (me.reExpander) {
37197             if (me.reExpander.temporary) {
37198                 me.reExpander.hide();
37199             } else {
37200                 me.reExpander.removeClsWithUI(me.collapsedCls);
37201                 me.reExpander.removeClsWithUI(me.collapsedCls + '-' + me.reExpander.dock);
37202                 if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
37203                     me.reExpander.removeClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
37204                 }
37205                 me.reExpander.updateFrame();
37206             }
37207         }
37208
37209         
37210         if (me.collapseTool) {
37211             me.collapseTool.setType('collapse-' + me.collapseDirection);
37212         }
37213
37214         
37215         me.collapsed = false;
37216
37217         
37218         me.body.show();
37219
37220         
37221         me.removeClsWithUI(me.collapsedCls);
37222         
37223         
37224         
37225
37226         anim = {
37227             to: {
37228             },
37229             from: {
37230                 height: height,
37231                 width: width
37232             },
37233             listeners: {
37234                 afteranimate: me.afterExpand,
37235                 scope: me
37236             }
37237         };
37238
37239         if ((direction == Ext.Component.DIRECTION_TOP) || (direction == Ext.Component.DIRECTION_BOTTOM)) {
37240
37241             
37242             if (me.autoHeight) {
37243                 me.setCalculatedSize(me.width, null);
37244                 anim.to.height = me.getHeight();
37245
37246                 
37247                 me.setCalculatedSize(me.width, anim.from.height);
37248             }
37249             
37250             
37251             else if (me.savedFlex) {
37252                 me.flex = me.savedFlex;
37253                 anim.to.height = me.ownerCt.layout.calculateChildBox(me).height;
37254                 delete me.flex;
37255             }
37256             
37257             else {
37258                 anim.to.height = me.expandedSize;
37259             }
37260
37261             
37262             if (direction == Ext.Component.DIRECTION_TOP) {
37263                 pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
37264                 anim.from.top = pos;
37265                 anim.to.top = pos - (anim.to.height - height);
37266             }
37267         } else if ((direction == Ext.Component.DIRECTION_LEFT) || (direction == Ext.Component.DIRECTION_RIGHT)) {
37268
37269             
37270             if (me.autoWidth) {
37271                 me.setCalculatedSize(null, me.height);
37272                 anim.to.width = me.getWidth();
37273
37274                 
37275                 me.setCalculatedSize(anim.from.width, me.height);
37276             }
37277             
37278             
37279             else if (me.savedFlex) {
37280                 me.flex = me.savedFlex;
37281                 anim.to.width = me.ownerCt.layout.calculateChildBox(me).width;
37282                 delete me.flex;
37283             }
37284             
37285             else {
37286                 anim.to.width = me.expandedSize;
37287             }
37288
37289             
37290             if (direction == Ext.Component.DIRECTION_LEFT) {
37291                 pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
37292                 anim.from.left = pos;
37293                 anim.to.left = pos - (anim.to.width - width);
37294             }
37295         }
37296
37297         if (animate) {
37298             me.animate(anim);
37299         } else {
37300             me.setSize(anim.to.width, anim.to.height);
37301             if (anim.to.x) {
37302                 me.setLeft(anim.to.x);
37303             }
37304             if (anim.to.y) {
37305                 me.setTop(anim.to.y);
37306             }
37307             me.afterExpand(false);
37308         }
37309
37310         return me;
37311     },
37312
37313     afterExpand: function(animated) {
37314         var me = this;
37315         me.setAutoScroll(me.initialConfig.autoScroll);
37316
37317         
37318         if (me.savedFlex) {
37319             me.flex = me.savedFlex;
37320             delete me.savedFlex;
37321             delete me.width;
37322             delete me.height;
37323         }
37324
37325         
37326         delete me.suspendLayout;
37327         if (animated && me.ownerCt) {
37328             me.ownerCt.doLayout();
37329         }
37330
37331         if (me.resizer) {
37332             me.resizer.enable();
37333         }
37334
37335         me.fireEvent('expand', me);
37336
37337         
37338         if (animated && me.collapseTool) {
37339             me.collapseTool.enable();
37340         }
37341     },
37342
37343     
37344     toggleCollapse: function() {
37345         if (this.collapsed) {
37346             this.expand(this.animCollapse);
37347         } else {
37348             this.collapse(this.collapseDirection, this.animCollapse);
37349         }
37350         return this;
37351     },
37352
37353     
37354     getKeyMap : function(){
37355         if(!this.keyMap){
37356             this.keyMap = Ext.create('Ext.util.KeyMap', this.el, this.keys);
37357         }
37358         return this.keyMap;
37359     },
37360
37361     
37362     initDraggable : function(){
37363         
37364         this.dd = Ext.create('Ext.panel.DD', this, Ext.isBoolean(this.draggable) ? null : this.draggable);
37365     },
37366
37367     
37368     ghostTools : function() {
37369         var tools = [],
37370             origTools = this.initialConfig.tools;
37371
37372         if (origTools) {
37373             Ext.each(origTools, function(tool) {
37374                 
37375                 
37376                 
37377                 
37378                 tools.push({
37379                     type: tool.type
37380                 });
37381             });
37382         }
37383         else {
37384             tools = [{
37385                 type: 'placeholder'
37386             }];
37387         }
37388         return tools;
37389     },
37390
37391     
37392     ghost: function(cls) {
37393         var me = this,
37394             ghostPanel = me.ghostPanel,
37395             box = me.getBox();
37396
37397         if (!ghostPanel) {
37398             ghostPanel = Ext.create('Ext.panel.Panel', {
37399                 renderTo: document.body,
37400                 floating: {
37401                     shadow: false
37402                 },
37403                 frame: Ext.supports.CSS3BorderRadius ? me.frame : false,
37404                 title: me.title,
37405                 overlapHeader: me.overlapHeader,
37406                 headerPosition: me.headerPosition,
37407                 width: me.getWidth(),
37408                 height: me.getHeight(),
37409                 iconCls: me.iconCls,
37410                 baseCls: me.baseCls,
37411                 tools: me.ghostTools(),
37412                 cls: me.baseCls + '-ghost ' + (cls ||'')
37413             });
37414             me.ghostPanel = ghostPanel;
37415         }
37416         ghostPanel.floatParent = me.floatParent;
37417         if (me.floating) {
37418             ghostPanel.setZIndex(Ext.Number.from(me.el.getStyle('zIndex'), 0));
37419         } else {
37420             ghostPanel.toFront();
37421         }
37422         ghostPanel.el.show();
37423         ghostPanel.setPosition(box.x, box.y);
37424         ghostPanel.setSize(box.width, box.height);
37425         me.el.hide();
37426         if (me.floatingItems) {
37427             me.floatingItems.hide();
37428         }
37429         return ghostPanel;
37430     },
37431
37432     
37433     unghost: function(show, matchPosition) {
37434         var me = this;
37435         if (!me.ghostPanel) {
37436             return;
37437         }
37438         if (show !== false) {
37439             me.el.show();
37440             if (matchPosition !== false) {
37441                 me.setPosition(me.ghostPanel.getPosition());
37442             }
37443             if (me.floatingItems) {
37444                 me.floatingItems.show();
37445             }
37446             Ext.defer(me.focus, 10, me);
37447         }
37448         me.ghostPanel.el.hide();
37449     },
37450
37451     initResizable: function(resizable) {
37452         if (this.collapsed) {
37453             resizable.disabled = true;
37454         }
37455         this.callParent([resizable]);
37456     }
37457 });
37458
37459
37460
37461 Ext.define('Ext.layout.component.Tip', {
37462
37463     
37464
37465     alias: ['layout.tip'],
37466
37467     extend: 'Ext.layout.component.Dock',
37468
37469     
37470
37471     type: 'tip',
37472     
37473     onLayout: function(width, height) {
37474         var me = this,
37475             owner = me.owner,
37476             el = owner.el,
37477             minWidth,
37478             maxWidth,
37479             naturalWidth,
37480             constrainedWidth,
37481             xy = el.getXY();
37482
37483         
37484         el.setXY([-9999,-9999]);
37485
37486         
37487         this.callParent(arguments);
37488
37489         
37490         if (!Ext.isNumber(width)) {
37491             minWidth = owner.minWidth;
37492             maxWidth = owner.maxWidth;
37493             
37494             if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
37495                 constrainedWidth = me.doAutoWidth();
37496             } else {
37497                 naturalWidth = el.getWidth();
37498             }
37499             if (naturalWidth < minWidth) {
37500                 constrainedWidth = minWidth;
37501             }
37502             else if (naturalWidth > maxWidth) {
37503                 constrainedWidth = maxWidth;
37504             }
37505             if (constrainedWidth) {
37506                 this.callParent([constrainedWidth, height]);
37507             }
37508         }
37509
37510         
37511         el.setXY(xy);
37512     },
37513     
37514     doAutoWidth: function(){
37515         var me = this,
37516             owner = me.owner,
37517             body = owner.body,
37518             width = body.getTextWidth();
37519             
37520         if (owner.header) {
37521             width = Math.max(width, owner.header.getWidth());
37522         }
37523         if (!Ext.isDefined(me.frameWidth)) {
37524             me.frameWidth = owner.el.getWidth() - body.getWidth();
37525         }
37526         width += me.frameWidth + body.getPadding('lr');
37527         return width;
37528     }
37529 });
37530
37531
37532 Ext.define('Ext.tip.Tip', {
37533     extend: 'Ext.panel.Panel',
37534     requires: [ 'Ext.layout.component.Tip' ],
37535     alternateClassName: 'Ext.Tip',
37536     
37537     
37538     
37539     minWidth : 40,
37540     
37541     maxWidth : 300,
37542     
37543     shadow : "sides",
37544
37545     
37546     defaultAlign : "tl-bl?",
37547     
37548     constrainPosition : true,
37549
37550     
37551     frame: false,
37552
37553     
37554     autoRender: true,
37555     hidden: true,
37556     baseCls: Ext.baseCSSPrefix + 'tip',
37557     floating: {
37558         shadow: true,
37559         shim: true,
37560         constrain: true
37561     },
37562     focusOnToFront: false,
37563     componentLayout: 'tip',
37564
37565     closeAction: 'hide',
37566
37567     ariaRole: 'tooltip',
37568
37569     initComponent: function() {
37570         this.callParent(arguments);
37571
37572         
37573         this.constrain = this.constrain || this.constrainPosition;
37574     },
37575
37576     
37577     showAt : function(xy){
37578         var me = this;
37579         this.callParent();
37580         
37581         if (me.isVisible()) {
37582             me.setPagePosition(xy[0], xy[1]);
37583             if (me.constrainPosition || me.constrain) {
37584                 me.doConstrain();
37585             }
37586             me.toFront(true);
37587         }
37588     },
37589
37590     
37591     showBy : function(el, pos) {
37592         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
37593     },
37594
37595     
37596     initDraggable : function(){
37597         var me = this;
37598         me.draggable = {
37599             el: me.getDragEl(),
37600             delegate: me.header.el,
37601             constrain: me,
37602             constrainTo: me.el.dom.parentNode
37603         };
37604         
37605         Ext.Component.prototype.initDraggable.call(me);
37606     },
37607
37608     
37609     ghost: undefined,
37610     unghost: undefined
37611 });
37612
37613
37614 Ext.define('Ext.tip.ToolTip', {
37615     extend: 'Ext.tip.Tip',
37616     alias: 'widget.tooltip',
37617     alternateClassName: 'Ext.ToolTip',
37618     
37619     
37620     
37621     
37622     showDelay: 500,
37623     
37624     hideDelay: 200,
37625     
37626     dismissDelay: 5000,
37627     
37628     
37629     trackMouse: false,
37630     
37631     
37632     anchorToTarget: true,
37633     
37634     anchorOffset: 0,
37635     
37636
37637     
37638     targetCounter: 0,
37639     quickShowInterval: 250,
37640
37641     
37642     initComponent: function() {
37643         var me = this;
37644         me.callParent(arguments);
37645         me.lastActive = new Date();
37646         me.setTarget(me.target);
37647         me.origAnchor = me.anchor;
37648     },
37649
37650     
37651     onRender: function(ct, position) {
37652         var me = this;
37653         me.callParent(arguments);
37654         me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition();
37655         me.anchorEl = me.el.createChild({
37656             cls: Ext.baseCSSPrefix + 'tip-anchor ' + me.anchorCls
37657         });
37658     },
37659
37660     
37661     afterRender: function() {
37662         var me = this,
37663             zIndex;
37664
37665         me.callParent(arguments);
37666         zIndex = parseInt(me.el.getZIndex(), 10) || 0;
37667         me.anchorEl.setStyle('z-index', zIndex + 1).setVisibilityMode(Ext.core.Element.DISPLAY);
37668     },
37669
37670     
37671     setTarget: function(target) {
37672         var me = this,
37673             t = Ext.get(target),
37674             tg;
37675
37676         if (me.target) {
37677             tg = Ext.get(me.target);
37678             me.mun(tg, 'mouseover', me.onTargetOver, me);
37679             me.mun(tg, 'mouseout', me.onTargetOut, me);
37680             me.mun(tg, 'mousemove', me.onMouseMove, me);
37681         }
37682         
37683         me.target = t;
37684         if (t) {
37685             
37686             me.mon(t, {
37687                 
37688                 
37689                 freezeEvent: true,
37690
37691                 mouseover: me.onTargetOver,
37692                 mouseout: me.onTargetOut,
37693                 mousemove: me.onMouseMove,
37694                 scope: me
37695             });
37696         }
37697         if (me.anchor) {
37698             me.anchorTarget = me.target;
37699         }
37700     },
37701
37702     
37703     onMouseMove: function(e) {
37704         var me = this,
37705             t = me.delegate ? e.getTarget(me.delegate) : me.triggerElement = true,
37706             xy;
37707         if (t) {
37708             me.targetXY = e.getXY();
37709             if (t === me.triggerElement) {
37710                 if (!me.hidden && me.trackMouse) {
37711                     xy = me.getTargetXY();
37712                     if (me.constrainPosition) {
37713                         xy = me.el.adjustForConstraints(xy, me.el.dom.parentNode);
37714                     }
37715                     me.setPagePosition(xy);
37716                 }
37717             } else {
37718                 me.hide();
37719                 me.lastActive = new Date(0);
37720                 me.onTargetOver(e);
37721             }
37722         } else if ((!me.closable && me.isVisible()) && me.autoHide !== false) {
37723             me.hide();
37724         }
37725     },
37726
37727     
37728     getTargetXY: function() {
37729         var me = this,
37730             mouseOffset;
37731         if (me.delegate) {
37732             me.anchorTarget = me.triggerElement;
37733         }
37734         if (me.anchor) {
37735             me.targetCounter++;
37736                 var offsets = me.getOffsets(),
37737                     xy = (me.anchorToTarget && !me.trackMouse) ? me.el.getAlignToXY(me.anchorTarget, me.getAnchorAlign()) : me.targetXY,
37738                     dw = Ext.core.Element.getViewWidth() - 5,
37739                     dh = Ext.core.Element.getViewHeight() - 5,
37740                     de = document.documentElement,
37741                     bd = document.body,
37742                     scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
37743                     scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
37744                     axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
37745                     sz = me.getSize(),
37746                     constrainPosition = me.constrainPosition;
37747
37748             me.anchorEl.removeCls(me.anchorCls);
37749
37750             if (me.targetCounter < 2 && constrainPosition) {
37751                 if (axy[0] < scrollX) {
37752                     if (me.anchorToTarget) {
37753                         me.defaultAlign = 'l-r';
37754                         if (me.mouseOffset) {
37755                             me.mouseOffset[0] *= -1;
37756                         }
37757                     }
37758                     me.anchor = 'left';
37759                     return me.getTargetXY();
37760                 }
37761                 if (axy[0] + sz.width > dw) {
37762                     if (me.anchorToTarget) {
37763                         me.defaultAlign = 'r-l';
37764                         if (me.mouseOffset) {
37765                             me.mouseOffset[0] *= -1;
37766                         }
37767                     }
37768                     me.anchor = 'right';
37769                     return me.getTargetXY();
37770                 }
37771                 if (axy[1] < scrollY) {
37772                     if (me.anchorToTarget) {
37773                         me.defaultAlign = 't-b';
37774                         if (me.mouseOffset) {
37775                             me.mouseOffset[1] *= -1;
37776                         }
37777                     }
37778                     me.anchor = 'top';
37779                     return me.getTargetXY();
37780                 }
37781                 if (axy[1] + sz.height > dh) {
37782                     if (me.anchorToTarget) {
37783                         me.defaultAlign = 'b-t';
37784                         if (me.mouseOffset) {
37785                             me.mouseOffset[1] *= -1;
37786                         }
37787                     }
37788                     me.anchor = 'bottom';
37789                     return me.getTargetXY();
37790                 }
37791             }
37792
37793             me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition();
37794             me.anchorEl.addCls(me.anchorCls);
37795             me.targetCounter = 0;
37796             return axy;
37797         } else {
37798             mouseOffset = me.getMouseOffset();
37799             return (me.targetXY) ? [me.targetXY[0] + mouseOffset[0], me.targetXY[1] + mouseOffset[1]] : mouseOffset;
37800         }
37801     },
37802
37803     getMouseOffset: function() {
37804         var me = this,
37805         offset = me.anchor ? [0, 0] : [15, 18];
37806         if (me.mouseOffset) {
37807             offset[0] += me.mouseOffset[0];
37808             offset[1] += me.mouseOffset[1];
37809         }
37810         return offset;
37811     },
37812
37813     
37814     getAnchorPosition: function() {
37815         var me = this,
37816             m;
37817         if (me.anchor) {
37818             me.tipAnchor = me.anchor.charAt(0);
37819         } else {
37820             m = me.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
37821             if (!m) {
37822                 Ext.Error.raise('The AnchorTip.defaultAlign value "' + me.defaultAlign + '" is invalid.');
37823             }
37824             me.tipAnchor = m[1].charAt(0);
37825         }
37826
37827         switch (me.tipAnchor) {
37828         case 't':
37829             return 'top';
37830         case 'b':
37831             return 'bottom';
37832         case 'r':
37833             return 'right';
37834         }
37835         return 'left';
37836     },
37837
37838     
37839     getAnchorAlign: function() {
37840         switch (this.anchor) {
37841         case 'top':
37842             return 'tl-bl';
37843         case 'left':
37844             return 'tl-tr';
37845         case 'right':
37846             return 'tr-tl';
37847         default:
37848             return 'bl-tl';
37849         }
37850     },
37851
37852     
37853     getOffsets: function() {
37854         var me = this,
37855             mouseOffset,
37856             offsets,
37857             ap = me.getAnchorPosition().charAt(0);
37858         if (me.anchorToTarget && !me.trackMouse) {
37859             switch (ap) {
37860             case 't':
37861                 offsets = [0, 9];
37862                 break;
37863             case 'b':
37864                 offsets = [0, -13];
37865                 break;
37866             case 'r':
37867                 offsets = [ - 13, 0];
37868                 break;
37869             default:
37870                 offsets = [9, 0];
37871                 break;
37872             }
37873         } else {
37874             switch (ap) {
37875             case 't':
37876                 offsets = [ - 15 - me.anchorOffset, 30];
37877                 break;
37878             case 'b':
37879                 offsets = [ - 19 - me.anchorOffset, -13 - me.el.dom.offsetHeight];
37880                 break;
37881             case 'r':
37882                 offsets = [ - 15 - me.el.dom.offsetWidth, -13 - me.anchorOffset];
37883                 break;
37884             default:
37885                 offsets = [25, -13 - me.anchorOffset];
37886                 break;
37887             }
37888         }
37889         mouseOffset = me.getMouseOffset();
37890         offsets[0] += mouseOffset[0];
37891         offsets[1] += mouseOffset[1];
37892
37893         return offsets;
37894     },
37895
37896     
37897     onTargetOver: function(e) {
37898         var me = this,
37899             t;
37900
37901         if (me.disabled || e.within(me.target.dom, true)) {
37902             return;
37903         }
37904         t = e.getTarget(me.delegate);
37905         if (t) {
37906             me.triggerElement = t;
37907             me.clearTimer('hide');
37908             me.targetXY = e.getXY();
37909             me.delayShow();
37910         }
37911     },
37912
37913     
37914     delayShow: function() {
37915         var me = this;
37916         if (me.hidden && !me.showTimer) {
37917             if (Ext.Date.getElapsed(me.lastActive) < me.quickShowInterval) {
37918                 me.show();
37919             } else {
37920                 me.showTimer = Ext.defer(me.show, me.showDelay, me);
37921             }
37922         }
37923         else if (!me.hidden && me.autoHide !== false) {
37924             me.show();
37925         }
37926     },
37927
37928     
37929     onTargetOut: function(e) {
37930         var me = this;
37931         if (me.disabled || e.within(me.target.dom, true)) {
37932             return;
37933         }
37934         me.clearTimer('show');
37935         if (me.autoHide !== false) {
37936             me.delayHide();
37937         }
37938     },
37939
37940     
37941     delayHide: function() {
37942         var me = this;
37943         if (!me.hidden && !me.hideTimer) {
37944             me.hideTimer = Ext.defer(me.hide, me.hideDelay, me);
37945         }
37946     },
37947
37948     
37949     hide: function() {
37950         var me = this;
37951         me.clearTimer('dismiss');
37952         me.lastActive = new Date();
37953         if (me.anchorEl) {
37954             me.anchorEl.hide();
37955         }
37956         me.callParent(arguments);
37957         delete me.triggerElement;
37958     },
37959
37960     
37961     show: function() {
37962         var me = this;
37963
37964         
37965         
37966         this.callParent();
37967         if (this.hidden === false) {
37968             me.setPagePosition(-10000, -10000);
37969
37970             if (me.anchor) {
37971                 me.anchor = me.origAnchor;
37972             }
37973             me.showAt(me.getTargetXY());
37974
37975             if (me.anchor) {
37976                 me.syncAnchor();
37977                 me.anchorEl.show();
37978             } else {
37979                 me.anchorEl.hide();
37980             }
37981         }
37982     },
37983
37984     
37985     showAt: function(xy) {
37986         var me = this;
37987         me.lastActive = new Date();
37988         me.clearTimers();
37989
37990         
37991         if (!me.isVisible()) {
37992             this.callParent(arguments);
37993         }
37994
37995         
37996         if (me.isVisible()) {
37997             me.setPagePosition(xy[0], xy[1]);
37998             if (me.constrainPosition || me.constrain) {
37999                 me.doConstrain();
38000             }
38001             me.toFront(true);
38002         }
38003
38004         if (me.dismissDelay && me.autoHide !== false) {
38005             me.dismissTimer = Ext.defer(me.hide, me.dismissDelay, me);
38006         }
38007         if (me.anchor) {
38008             me.syncAnchor();
38009             if (!me.anchorEl.isVisible()) {
38010                 me.anchorEl.show();
38011             }
38012         } else {
38013             me.anchorEl.hide();
38014         }
38015     },
38016
38017     
38018     syncAnchor: function() {
38019         var me = this,
38020             anchorPos,
38021             targetPos,
38022             offset;
38023         switch (me.tipAnchor.charAt(0)) {
38024         case 't':
38025             anchorPos = 'b';
38026             targetPos = 'tl';
38027             offset = [20 + me.anchorOffset, 1];
38028             break;
38029         case 'r':
38030             anchorPos = 'l';
38031             targetPos = 'tr';
38032             offset = [ - 1, 12 + me.anchorOffset];
38033             break;
38034         case 'b':
38035             anchorPos = 't';
38036             targetPos = 'bl';
38037             offset = [20 + me.anchorOffset, -1];
38038             break;
38039         default:
38040             anchorPos = 'r';
38041             targetPos = 'tl';
38042             offset = [1, 12 + me.anchorOffset];
38043             break;
38044         }
38045         me.anchorEl.alignTo(me.el, anchorPos + '-' + targetPos, offset);
38046     },
38047
38048     
38049     setPagePosition: function(x, y) {
38050         var me = this;
38051         me.callParent(arguments);
38052         if (me.anchor) {
38053             me.syncAnchor();
38054         }
38055     },
38056
38057     
38058     clearTimer: function(name) {
38059         name = name + 'Timer';
38060         clearTimeout(this[name]);
38061         delete this[name];
38062     },
38063
38064     
38065     clearTimers: function() {
38066         var me = this;
38067         me.clearTimer('show');
38068         me.clearTimer('dismiss');
38069         me.clearTimer('hide');
38070     },
38071
38072     
38073     onShow: function() {
38074         var me = this;
38075         me.callParent();
38076         me.mon(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me);
38077     },
38078
38079     
38080     onHide: function() {
38081         var me = this;
38082         me.callParent();
38083         me.mun(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me);
38084     },
38085
38086     
38087     onDocMouseDown: function(e) {
38088         var me = this;
38089         if (me.autoHide !== true && !me.closable && !e.within(me.el.dom)) {
38090             me.disable();
38091             Ext.defer(me.doEnable, 100, me);
38092         }
38093     },
38094
38095     
38096     doEnable: function() {
38097         if (!this.isDestroyed) {
38098             this.enable();
38099         }
38100     },
38101
38102     
38103     onDisable: function() {
38104         this.callParent();
38105         this.clearTimers();
38106         this.hide();
38107     },
38108
38109     beforeDestroy: function() {
38110         var me = this;
38111         me.clearTimers();
38112         Ext.destroy(me.anchorEl);
38113         delete me.anchorEl;
38114         delete me.target;
38115         delete me.anchorTarget;
38116         delete me.triggerElement;
38117         me.callParent();
38118     },
38119
38120     
38121     onDestroy: function() {
38122         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
38123         this.callParent();
38124     }
38125 });
38126
38127
38128 Ext.define('Ext.tip.QuickTip', {
38129     extend: 'Ext.tip.ToolTip',
38130     alternateClassName: 'Ext.QuickTip',
38131     
38132     
38133     interceptTitles : false,
38134
38135     
38136     title: '&#160;',
38137
38138     
38139     tagConfig : {
38140         namespace : "data-",
38141         attribute : "qtip",
38142         width : "qwidth",
38143         target : "target",
38144         title : "qtitle",
38145         hide : "hide",
38146         cls : "qclass",
38147         align : "qalign",
38148         anchor : "anchor"
38149     },
38150
38151     
38152     initComponent : function(){
38153         var me = this;
38154         
38155         me.target = me.target || Ext.getDoc();
38156         me.targets = me.targets || {};
38157         me.callParent();
38158     },
38159
38160     
38161     register : function(config){
38162         var configs = Ext.isArray(config) ? config : arguments,
38163             i = 0,
38164             len = configs.length,
38165             target, j, targetLen;
38166             
38167         for (; i < len; i++) {
38168             config = configs[i];
38169             target = config.target;
38170             if (target) {
38171                 if (Ext.isArray(target)) {
38172                     for (j = 0, targetLen = target.length; j < targetLen; j++) {
38173                         this.targets[Ext.id(target[j])] = config;
38174                     }
38175                 } else{
38176                     this.targets[Ext.id(target)] = config;
38177                 }
38178             }
38179         }
38180     },
38181
38182     
38183     unregister : function(el){
38184         delete this.targets[Ext.id(el)];
38185     },
38186     
38187     
38188     cancelShow: function(el){
38189         var me = this,
38190             activeTarget = me.activeTarget;
38191             
38192         el = Ext.get(el).dom;
38193         if (me.isVisible()) {
38194             if (activeTarget && activeTarget.el == el) {
38195                 me.hide();
38196             }
38197         } else if (activeTarget && activeTarget.el == el) {
38198             me.clearTimer('show');
38199         }
38200     },
38201     
38202     getTipCfg: function(e) {
38203         var t = e.getTarget(),
38204             ttp, 
38205             cfg;
38206         
38207         if(this.interceptTitles && t.title && Ext.isString(t.title)){
38208             ttp = t.title;
38209             t.qtip = ttp;
38210             t.removeAttribute("title");
38211             e.preventDefault();
38212         } 
38213         else {            
38214             cfg = this.tagConfig;
38215             t = e.getTarget('[' + cfg.namespace + cfg.attribute + ']');
38216             if (t) {
38217                 ttp = t.getAttribute(cfg.namespace + cfg.attribute);
38218             }
38219         }
38220         return ttp;
38221     },
38222
38223     
38224     onTargetOver : function(e){
38225         var me = this,
38226             target = e.getTarget(),
38227             elTarget,
38228             cfg,
38229             ns,
38230             ttp,
38231             autoHide;
38232         
38233         if (me.disabled) {
38234             return;
38235         }
38236
38237         
38238         
38239         
38240         me.targetXY = e.getXY();
38241
38242         if(!target || target.nodeType !== 1 || target == document || target == document.body){
38243             return;
38244         }
38245         
38246         if (me.activeTarget && ((target == me.activeTarget.el) || Ext.fly(me.activeTarget.el).contains(target))) {
38247             me.clearTimer('hide');
38248             me.show();
38249             return;
38250         }
38251         
38252         if (target) {
38253             Ext.Object.each(me.targets, function(key, value) {
38254                 var targetEl = Ext.fly(value.target);
38255                 if (targetEl && (targetEl.dom === target || targetEl.contains(target))) {
38256                     elTarget = targetEl.dom;
38257                     return false;
38258                 }
38259             });
38260             if (elTarget) {
38261                 me.activeTarget = me.targets[elTarget.id];
38262                 me.activeTarget.el = target;
38263                 me.anchor = me.activeTarget.anchor;
38264                 if (me.anchor) {
38265                     me.anchorTarget = target;
38266                 }
38267                 me.delayShow();
38268                 return;
38269             }
38270         }
38271
38272         elTarget = Ext.get(target);
38273         cfg = me.tagConfig;
38274         ns = cfg.namespace; 
38275         ttp = me.getTipCfg(e);
38276         
38277         if (ttp) {
38278             autoHide = elTarget.getAttribute(ns + cfg.hide);
38279                  
38280             me.activeTarget = {
38281                 el: target,
38282                 text: ttp,
38283                 width: +elTarget.getAttribute(ns + cfg.width) || null,
38284                 autoHide: autoHide != "user" && autoHide !== 'false',
38285                 title: elTarget.getAttribute(ns + cfg.title),
38286                 cls: elTarget.getAttribute(ns + cfg.cls),
38287                 align: elTarget.getAttribute(ns + cfg.align)
38288                 
38289             };
38290             me.anchor = elTarget.getAttribute(ns + cfg.anchor);
38291             if (me.anchor) {
38292                 me.anchorTarget = target;
38293             }
38294             me.delayShow();
38295         }
38296     },
38297
38298     
38299     onTargetOut : function(e){
38300         var me = this;
38301         
38302         
38303         if (me.activeTarget && e.within(me.activeTarget.el) && !me.getTipCfg(e)) {
38304             return;
38305         }
38306
38307         me.clearTimer('show');
38308         if (me.autoHide !== false) {
38309             me.delayHide();
38310         }
38311     },
38312
38313     
38314     showAt : function(xy){
38315         var me = this,
38316             target = me.activeTarget;
38317         
38318         if (target) {
38319             if (!me.rendered) {
38320                 me.render(Ext.getBody());
38321                 me.activeTarget = target;
38322             }
38323             if (target.title) {
38324                 me.setTitle(target.title || '');
38325                 me.header.show();
38326             } else {
38327                 me.header.hide();
38328             }
38329             me.body.update(target.text);
38330             me.autoHide = target.autoHide;
38331             me.dismissDelay = target.dismissDelay || me.dismissDelay;
38332             if (me.lastCls) {
38333                 me.el.removeCls(me.lastCls);
38334                 delete me.lastCls;
38335             }
38336             if (target.cls) {
38337                 me.el.addCls(target.cls);
38338                 me.lastCls = target.cls;
38339             }
38340
38341             me.setWidth(target.width);
38342             
38343             if (me.anchor) {
38344                 me.constrainPosition = false;
38345             } else if (target.align) { 
38346                 xy = me.el.getAlignToXY(target.el, target.align);
38347                 me.constrainPosition = false;
38348             }else{
38349                 me.constrainPosition = true;
38350             }
38351         }
38352         me.callParent([xy]);
38353     },
38354
38355     
38356     hide: function(){
38357         delete this.activeTarget;
38358         this.callParent();
38359     }
38360 });
38361
38362
38363 Ext.define('Ext.tip.QuickTipManager', function() {
38364     var tip,
38365         disabled = false;
38366
38367     return {
38368         requires: ['Ext.tip.QuickTip'],
38369         singleton: true,
38370         alternateClassName: 'Ext.QuickTips',
38371         
38372         init : function(autoRender){
38373             if (!tip) {
38374                 if (!Ext.isReady) {
38375                     Ext.onReady(function(){
38376                         Ext.tip.QuickTipManager.init(autoRender);
38377                     });
38378                     return;
38379                 }
38380                 tip = Ext.create('Ext.tip.QuickTip', {
38381                     disabled: disabled,
38382                     renderTo: autoRender !== false ? document.body : undefined
38383                 });
38384             }
38385         },
38386
38387         
38388         destroy: function() {
38389             if (tip) {
38390                 var undef;
38391                 tip.destroy();
38392                 tip = undef;
38393             }
38394         },
38395
38396         
38397         ddDisable : function(){
38398             
38399             if(tip && !disabled){
38400                 tip.disable();
38401             }
38402         },
38403
38404         
38405         ddEnable : function(){
38406             
38407             if(tip && !disabled){
38408                 tip.enable();
38409             }
38410         },
38411
38412         
38413         enable : function(){
38414             if(tip){
38415                 tip.enable();
38416             }
38417             disabled = false;
38418         },
38419
38420         
38421         disable : function(){
38422             if(tip){
38423                 tip.disable();
38424             }
38425             disabled = true;
38426         },
38427
38428         
38429         isEnabled : function(){
38430             return tip !== undefined && !tip.disabled;
38431         },
38432
38433         
38434         getQuickTip : function(){
38435             return tip;
38436         },
38437
38438         
38439         register : function(){
38440             tip.register.apply(tip, arguments);
38441         },
38442
38443         
38444         unregister : function(){
38445             tip.unregister.apply(tip, arguments);
38446         },
38447
38448         
38449         tips : function(){
38450             tip.register.apply(tip, arguments);
38451         }
38452     };
38453 }());
38454
38455 Ext.define('Ext.app.Application', {
38456     extend: 'Ext.app.Controller',
38457
38458     requires: [
38459         'Ext.ModelManager',
38460         'Ext.data.Model',
38461         'Ext.data.StoreManager',
38462         'Ext.tip.QuickTipManager',
38463         'Ext.ComponentManager',
38464         'Ext.app.EventBus'
38465     ],
38466
38467     
38468
38469     
38470     scope: undefined,
38471
38472     
38473     enableQuickTips: true,
38474
38475     
38476
38477     
38478     appFolder: 'app',
38479
38480     
38481     autoCreateViewport: true,
38482
38483     constructor: function(config) {
38484         config = config || {};
38485         Ext.apply(this, config);
38486
38487         var requires = config.requires || [];
38488
38489         Ext.Loader.setPath(this.name, this.appFolder);
38490
38491         if (this.paths) {
38492             Ext.Object.each(this.paths, function(key, value) {
38493                 Ext.Loader.setPath(key, value);
38494             });
38495         }
38496
38497         this.callParent(arguments);
38498
38499         this.eventbus = Ext.create('Ext.app.EventBus');
38500
38501         var controllers = this.controllers,
38502             ln = controllers.length,
38503             i, controller;
38504
38505         this.controllers = Ext.create('Ext.util.MixedCollection');
38506
38507         if (this.autoCreateViewport) {
38508             requires.push(this.getModuleClassName('Viewport', 'view'));
38509         }
38510
38511         for (i = 0; i < ln; i++) {
38512             requires.push(this.getModuleClassName(controllers[i], 'controller'));
38513         }
38514
38515         Ext.require(requires);
38516
38517         Ext.onReady(function() {
38518             for (i = 0; i < ln; i++) {
38519                 controller = this.getController(controllers[i]);
38520                 controller.init(this);
38521             }
38522
38523             this.onBeforeLaunch.call(this);
38524         }, this);
38525     },
38526
38527     control: function(selectors, listeners, controller) {
38528         this.eventbus.control(selectors, listeners, controller);
38529     },
38530
38531     
38532     launch: Ext.emptyFn,
38533
38534     
38535     onBeforeLaunch: function() {
38536         if (this.enableQuickTips) {
38537             Ext.tip.QuickTipManager.init();
38538         }
38539
38540         if (this.autoCreateViewport) {
38541             this.getView('Viewport').create();
38542         }
38543
38544         this.launch.call(this.scope || this);
38545         this.launched = true;
38546         this.fireEvent('launch', this);
38547
38548         this.controllers.each(function(controller) {
38549             controller.onLaunch(this);
38550         }, this);
38551     },
38552
38553     getModuleClassName: function(name, type) {
38554         var namespace = Ext.Loader.getPrefix(name);
38555
38556         if (namespace.length > 0 && namespace !== name) {
38557             return name;
38558         }
38559
38560         return this.name + '.' + type + '.' + name;
38561     },
38562
38563     getController: function(name) {
38564         var controller = this.controllers.get(name);
38565
38566         if (!controller) {
38567             controller = Ext.create(this.getModuleClassName(name, 'controller'), {
38568                 application: this,
38569                 id: name
38570             });
38571
38572             this.controllers.add(controller);
38573         }
38574
38575         return controller;
38576     },
38577
38578     getStore: function(name) {
38579         var store = Ext.StoreManager.get(name);
38580
38581         if (!store) {
38582             store = Ext.create(this.getModuleClassName(name, 'store'), {
38583                 storeId: name
38584             });
38585         }
38586
38587         return store;
38588     },
38589
38590     getModel: function(model) {
38591         model = this.getModuleClassName(model, 'model');
38592
38593         return Ext.ModelManager.getModel(model);
38594     },
38595
38596     getView: function(view) {
38597         view = this.getModuleClassName(view, 'view');
38598
38599         return Ext.ClassManager.get(view);
38600     }
38601 });
38602
38603
38604 Ext.define('Ext.chart.Callout', {
38605
38606     
38607
38608     
38609
38610     constructor: function(config) {
38611         if (config.callouts) {
38612             config.callouts.styles = Ext.applyIf(config.callouts.styles || {}, {
38613                 color: "#000",
38614                 font: "11px Helvetica, sans-serif"
38615             });
38616             this.callouts = Ext.apply(this.callouts || {}, config.callouts);
38617             this.calloutsArray = [];
38618         }
38619     },
38620
38621     renderCallouts: function() {
38622         if (!this.callouts) {
38623             return;
38624         }
38625
38626         var me = this,
38627             items = me.items,
38628             animate = me.chart.animate,
38629             config = me.callouts,
38630             styles = config.styles,
38631             group = me.calloutsArray,
38632             store = me.chart.store,
38633             len = store.getCount(),
38634             ratio = items.length / len,
38635             previouslyPlacedCallouts = [],
38636             i,
38637             count,
38638             j,
38639             p;
38640             
38641         for (i = 0, count = 0; i < len; i++) {
38642             for (j = 0; j < ratio; j++) {
38643                 var item = items[count],
38644                     label = group[count],
38645                     storeItem = store.getAt(i),
38646                     display;
38647                 
38648                 display = config.filter(storeItem);
38649                 
38650                 if (!display && !label) {
38651                     count++;
38652                     continue;               
38653                 }
38654                 
38655                 if (!label) {
38656                     group[count] = label = me.onCreateCallout(storeItem, item, i, display, j, count);
38657                 }
38658                 for (p in label) {
38659                     if (label[p] && label[p].setAttributes) {
38660                         label[p].setAttributes(styles, true);
38661                     }
38662                 }
38663                 if (!display) {
38664                     for (p in label) {
38665                         if (label[p]) {
38666                             if (label[p].setAttributes) {
38667                                 label[p].setAttributes({
38668                                     hidden: true
38669                                 }, true);
38670                             } else if(label[p].setVisible) {
38671                                 label[p].setVisible(false);
38672                             }
38673                         }
38674                     }
38675                 }
38676                 config.renderer(label, storeItem);
38677                 me.onPlaceCallout(label, storeItem, item, i, display, animate,
38678                                   j, count, previouslyPlacedCallouts);
38679                 previouslyPlacedCallouts.push(label);
38680                 count++;
38681             }
38682         }
38683         this.hideCallouts(count);
38684     },
38685
38686     onCreateCallout: function(storeItem, item, i, display) {
38687         var me = this,
38688             group = me.calloutsGroup,
38689             config = me.callouts,
38690             styles = config.styles,
38691             width = styles.width,
38692             height = styles.height,
38693             chart = me.chart,
38694             surface = chart.surface,
38695             calloutObj = {
38696                 
38697                 
38698                 lines: false
38699             };
38700
38701         calloutObj.lines = surface.add(Ext.apply({},
38702         {
38703             type: 'path',
38704             path: 'M0,0',
38705             stroke: me.getLegendColor() || '#555'
38706         },
38707         styles));
38708
38709         if (config.items) {
38710             calloutObj.panel = Ext.create('widget.panel', {
38711                 style: "position: absolute;",    
38712                 width: width,
38713                 height: height,
38714                 items: config.items,
38715                 renderTo: chart.el
38716             });
38717         }
38718
38719         return calloutObj;
38720     },
38721
38722     hideCallouts: function(index) {
38723         var calloutsArray = this.calloutsArray,
38724             len = calloutsArray.length,
38725             co,
38726             p;
38727         while (len-->index) {
38728             co = calloutsArray[len];
38729             for (p in co) {
38730                 if (co[p]) {
38731                     co[p].hide(true);
38732                 }
38733             }
38734         }
38735     }
38736 });
38737
38738
38739 Ext.define('Ext.draw.CompositeSprite', {
38740
38741     
38742
38743     extend: 'Ext.util.MixedCollection',
38744     mixins: {
38745         animate: 'Ext.util.Animate'
38746     },
38747
38748     
38749     isCompositeSprite: true,
38750     constructor: function(config) {
38751         var me = this;
38752         
38753         config = config || {};
38754         Ext.apply(me, config);
38755
38756         me.addEvents(
38757             'mousedown',
38758             'mouseup',
38759             'mouseover',
38760             'mouseout',
38761             'click'
38762         );
38763         me.id = Ext.id(null, 'ext-sprite-group-');
38764         me.callParent();
38765     },
38766
38767     
38768     onClick: function(e) {
38769         this.fireEvent('click', e);
38770     },
38771
38772     
38773     onMouseUp: function(e) {
38774         this.fireEvent('mouseup', e);
38775     },
38776
38777     
38778     onMouseDown: function(e) {
38779         this.fireEvent('mousedown', e);
38780     },
38781
38782     
38783     onMouseOver: function(e) {
38784         this.fireEvent('mouseover', e);
38785     },
38786
38787     
38788     onMouseOut: function(e) {
38789         this.fireEvent('mouseout', e);
38790     },
38791
38792     attachEvents: function(o) {
38793         var me = this;
38794         
38795         o.on({
38796             scope: me,
38797             mousedown: me.onMouseDown,
38798             mouseup: me.onMouseUp,
38799             mouseover: me.onMouseOver,
38800             mouseout: me.onMouseOut,
38801             click: me.onClick
38802         });
38803     },
38804
38805     
38806     add: function(key, o) {
38807         var result = this.callParent(arguments);
38808         this.attachEvents(result);
38809         return result;
38810     },
38811
38812     insert: function(index, key, o) {
38813         return this.callParent(arguments);
38814     },
38815
38816     
38817     remove: function(o) {
38818         var me = this;
38819         
38820         o.un({
38821             scope: me,
38822             mousedown: me.onMouseDown,
38823             mouseup: me.onMouseUp,
38824             mouseover: me.onMouseOver,
38825             mouseout: me.onMouseOut,
38826             click: me.onClick
38827         });
38828         me.callParent(arguments);
38829     },
38830     
38831     
38832     getBBox: function() {
38833         var i = 0,
38834             sprite,
38835             bb,
38836             items = this.items,
38837             len = this.length,
38838             infinity = Infinity,
38839             minX = infinity,
38840             maxHeight = -infinity,
38841             minY = infinity,
38842             maxWidth = -infinity,
38843             maxWidthBBox, maxHeightBBox;
38844         
38845         for (; i < len; i++) {
38846             sprite = items[i];
38847             if (sprite.el) {
38848                 bb = sprite.getBBox();
38849                 minX = Math.min(minX, bb.x);
38850                 minY = Math.min(minY, bb.y);
38851                 maxHeight = Math.max(maxHeight, bb.height + bb.y);
38852                 maxWidth = Math.max(maxWidth, bb.width + bb.x);
38853             }
38854         }
38855         
38856         return {
38857             x: minX,
38858             y: minY,
38859             height: maxHeight - minY,
38860             width: maxWidth - minX
38861         };
38862     },
38863
38864     
38865     setAttributes: function(attrs, redraw) {
38866         var i = 0,
38867             items = this.items,
38868             len = this.length;
38869             
38870         for (; i < len; i++) {
38871             items[i].setAttributes(attrs, redraw);
38872         }
38873         return this;
38874     },
38875
38876     
38877     hide: function(attrs) {
38878         var i = 0,
38879             items = this.items,
38880             len = this.length;
38881             
38882         for (; i < len; i++) {
38883             items[i].hide();
38884         }
38885         return this;
38886     },
38887
38888     
38889     show: function(attrs) {
38890         var i = 0,
38891             items = this.items,
38892             len = this.length;
38893             
38894         for (; i < len; i++) {
38895             items[i].show();
38896         }
38897         return this;
38898     },
38899
38900     redraw: function() {
38901         var me = this,
38902             i = 0,
38903             items = me.items,
38904             surface = me.getSurface(),
38905             len = me.length;
38906         
38907         if (surface) {
38908             for (; i < len; i++) {
38909                 surface.renderItem(items[i]);
38910             }
38911         }
38912         return me;
38913     },
38914
38915     setStyle: function(obj) {
38916         var i = 0,
38917             items = this.items,
38918             len = this.length,
38919             item, el;
38920             
38921         for (; i < len; i++) {
38922             item = items[i];
38923             el = item.el;
38924             if (el) {
38925                 el.setStyle(obj);
38926             }
38927         }
38928     },
38929
38930     addCls: function(obj) {
38931         var i = 0,
38932             items = this.items,
38933             surface = this.getSurface(),
38934             len = this.length;
38935         
38936         if (surface) {
38937             for (; i < len; i++) {
38938                 surface.addCls(items[i], obj);
38939             }
38940         }
38941     },
38942
38943     removeCls: function(obj) {
38944         var i = 0,
38945             items = this.items,
38946             surface = this.getSurface(),
38947             len = this.length;
38948         
38949         if (surface) {
38950             for (; i < len; i++) {
38951                 surface.removeCls(items[i], obj);
38952             }
38953         }
38954     },
38955     
38956     
38957     getSurface: function(){
38958         var first = this.first();
38959         if (first) {
38960             return first.surface;
38961         }
38962         return null;
38963     },
38964     
38965     
38966     destroy: function(){
38967         var me = this,
38968             surface = me.getSurface(),
38969             item;
38970             
38971         if (surface) {
38972             while (me.getCount() > 0) {
38973                 item = me.first();
38974                 me.remove(item);
38975                 surface.remove(item);
38976             }
38977         }
38978         me.clearListeners();
38979     }
38980 });
38981
38982
38983
38984 Ext.define('Ext.layout.component.Draw', {
38985
38986     
38987
38988     alias: 'layout.draw',
38989
38990     extend: 'Ext.layout.component.Auto',
38991
38992     
38993
38994     type: 'draw',
38995
38996     onLayout : function(width, height) {
38997         this.owner.surface.setSize(width, height);
38998         this.callParent(arguments);
38999     }
39000 });
39001
39002 Ext.define('Ext.chart.theme.Theme', {
39003
39004     
39005
39006     requires: ['Ext.draw.Color'],
39007
39008     
39009
39010     theme: 'Base',
39011     themeAttrs: false,
39012     
39013     initTheme: function(theme) {
39014         var me = this,
39015             themes = Ext.chart.theme,
39016             key, gradients;
39017         if (theme) {
39018             theme = theme.split(':');
39019             for (key in themes) {
39020                 if (key == theme[0]) {
39021                     gradients = theme[1] == 'gradients';
39022                     me.themeAttrs = new themes[key]({
39023                         useGradients: gradients
39024                     });
39025                     if (gradients) {
39026                         me.gradients = me.themeAttrs.gradients;
39027                     }
39028                     if (me.themeAttrs.background) {
39029                         me.background = me.themeAttrs.background;
39030                     }
39031                     return;
39032                 }
39033             }
39034             Ext.Error.raise('No theme found named "' + theme + '"');
39035         }
39036     }
39037 }, 
39038
39039 function() {
39040    
39041
39042 (function() {
39043     Ext.chart.theme = function(config, base) {
39044         config = config || {};
39045         var i = 0, l, colors, color,
39046             seriesThemes, markerThemes,
39047             seriesTheme, markerTheme, 
39048             key, gradients = [],
39049             midColor, midL;
39050         
39051         if (config.baseColor) {
39052             midColor = Ext.draw.Color.fromString(config.baseColor);
39053             midL = midColor.getHSL()[2];
39054             if (midL < 0.15) {
39055                 midColor = midColor.getLighter(0.3);
39056             } else if (midL < 0.3) {
39057                 midColor = midColor.getLighter(0.15);
39058             } else if (midL > 0.85) {
39059                 midColor = midColor.getDarker(0.3);
39060             } else if (midL > 0.7) {
39061                 midColor = midColor.getDarker(0.15);
39062             }
39063             config.colors = [ midColor.getDarker(0.3).toString(),
39064                               midColor.getDarker(0.15).toString(),
39065                               midColor.toString(),
39066                               midColor.getLighter(0.15).toString(),
39067                               midColor.getLighter(0.3).toString()];
39068
39069             delete config.baseColor;
39070         }
39071         if (config.colors) {
39072             colors = config.colors.slice();
39073             markerThemes = base.markerThemes;
39074             seriesThemes = base.seriesThemes;
39075             l = colors.length;
39076             base.colors = colors;
39077             for (; i < l; i++) {
39078                 color = colors[i];
39079                 markerTheme = markerThemes[i] || {};
39080                 seriesTheme = seriesThemes[i] || {};
39081                 markerTheme.fill = seriesTheme.fill = markerTheme.stroke = seriesTheme.stroke = color;
39082                 markerThemes[i] = markerTheme;
39083                 seriesThemes[i] = seriesTheme;
39084             }
39085             base.markerThemes = markerThemes.slice(0, l);
39086             base.seriesThemes = seriesThemes.slice(0, l);
39087         
39088         }
39089         for (key in base) {
39090             if (key in config) {
39091                 if (Ext.isObject(config[key]) && Ext.isObject(base[key])) {
39092                     Ext.apply(base[key], config[key]);
39093                 } else {
39094                     base[key] = config[key];
39095                 }
39096             }
39097         }
39098         if (config.useGradients) {
39099             colors = base.colors || (function () {
39100                 var ans = [];
39101                 for (i = 0, seriesThemes = base.seriesThemes, l = seriesThemes.length; i < l; i++) {
39102                     ans.push(seriesThemes[i].fill || seriesThemes[i].stroke);
39103                 }
39104                 return ans;
39105             })();
39106             for (i = 0, l = colors.length; i < l; i++) {
39107                 midColor = Ext.draw.Color.fromString(colors[i]);
39108                 if (midColor) {
39109                     color = midColor.getDarker(0.1).toString();
39110                     midColor = midColor.toString();
39111                     key = 'theme-' + midColor.substr(1) + '-' + color.substr(1);
39112                     gradients.push({
39113                         id: key,
39114                         angle: 45,
39115                         stops: {
39116                             0: {
39117                                 color: midColor.toString()
39118                             },
39119                             100: {
39120                                 color: color.toString()
39121                             }
39122                         }
39123                     });
39124                     colors[i] = 'url(#' + key + ')'; 
39125                 }
39126             }
39127             base.gradients = gradients;
39128             base.colors = colors;
39129         }
39130         
39131         Ext.apply(this, base);
39132     };
39133 })();
39134 });
39135
39136
39137 Ext.define('Ext.chart.Mask', {
39138     constructor: function(config) {
39139         var me = this;
39140
39141         me.addEvents('select');
39142
39143         if (config) {
39144             Ext.apply(me, config);
39145         }
39146         if (me.mask) {
39147             me.on('afterrender', function() {
39148                 
39149                 var comp = Ext.create('Ext.chart.MaskLayer', {
39150                     renderTo: me.el
39151                 });
39152                 comp.el.on({
39153                     'mousemove': function(e) {
39154                         me.onMouseMove(e);
39155                     },
39156                     'mouseup': function(e) {
39157                         me.resized(e);
39158                     }
39159                 });
39160                 
39161                 var resizeHandler = Ext.create('Ext.resizer.Resizer', {
39162                     el: comp.el,
39163                     handles: 'all',
39164                     pinned: true
39165                 });
39166                 resizeHandler.on({
39167                     'resize': function(e) {
39168                         me.resized(e);    
39169                     }    
39170                 });
39171                 comp.initDraggable();
39172                 me.maskType = me.mask;
39173                 me.mask = comp;
39174                 me.maskSprite = me.surface.add({
39175                     type: 'path',
39176                     path: ['M', 0, 0],
39177                     zIndex: 1001,
39178                     opacity: 0.7,
39179                     hidden: true,
39180                     stroke: '#444'
39181                 });
39182             }, me, { single: true });
39183         }
39184     },
39185     
39186     resized: function(e) {
39187         var me = this,
39188             bbox = me.bbox || me.chartBBox,
39189             x = bbox.x,
39190             y = bbox.y,
39191             width = bbox.width,
39192             height = bbox.height,
39193             box = me.mask.getBox(true),
39194             max = Math.max,
39195             min = Math.min,
39196             staticX = box.x - x,
39197             staticY = box.y - y;
39198         
39199         staticX = max(staticX, x);
39200         staticY = max(staticY, y);
39201         staticX = min(staticX, width);
39202         staticY = min(staticY, height);
39203         box.x = staticX;
39204         box.y = staticY;
39205         me.fireEvent('select', me, box);
39206     },
39207
39208     onMouseUp: function(e) {
39209         var me = this,
39210             bbox = me.bbox || me.chartBBox,
39211             sel = me.maskSelection;
39212         me.maskMouseDown = false;
39213         me.mouseDown = false;
39214         if (me.mouseMoved) {
39215             me.onMouseMove(e);
39216             me.mouseMoved = false;
39217             me.fireEvent('select', me, {
39218                 x: sel.x - bbox.x,
39219                 y: sel.y - bbox.y,
39220                 width: sel.width,
39221                 height: sel.height
39222             });
39223         }
39224     },
39225
39226     onMouseDown: function(e) {
39227         var me = this;
39228         me.mouseDown = true;
39229         me.mouseMoved = false;
39230         me.maskMouseDown = {
39231             x: e.getPageX() - me.el.getX(),
39232             y: e.getPageY() - me.el.getY()
39233         };
39234     },
39235
39236     onMouseMove: function(e) {
39237         var me = this,
39238             mask = me.maskType,
39239             bbox = me.bbox || me.chartBBox,
39240             x = bbox.x,
39241             y = bbox.y,
39242             math = Math,
39243             floor = math.floor,
39244             abs = math.abs,
39245             min = math.min,
39246             max = math.max,
39247             height = floor(y + bbox.height),
39248             width = floor(x + bbox.width),
39249             posX = e.getPageX(),
39250             posY = e.getPageY(),
39251             staticX = posX - me.el.getX(),
39252             staticY = posY - me.el.getY(),
39253             maskMouseDown = me.maskMouseDown,
39254             path;
39255         
39256         me.mouseMoved = me.mouseDown;
39257         staticX = max(staticX, x);
39258         staticY = max(staticY, y);
39259         staticX = min(staticX, width);
39260         staticY = min(staticY, height);
39261         if (maskMouseDown && me.mouseDown) {
39262             if (mask == 'horizontal') {
39263                 staticY = y;
39264                 maskMouseDown.y = height;
39265                 posY = me.el.getY() + bbox.height + me.insetPadding;
39266             }
39267             else if (mask == 'vertical') {
39268                 staticX = x;
39269                 maskMouseDown.x = width;
39270             }
39271             width = maskMouseDown.x - staticX;
39272             height = maskMouseDown.y - staticY;
39273             path = ['M', staticX, staticY, 'l', width, 0, 0, height, -width, 0, 'z'];
39274             me.maskSelection = {
39275                 x: width > 0 ? staticX : staticX + width,
39276                 y: height > 0 ? staticY : staticY + height,
39277                 width: abs(width),
39278                 height: abs(height)
39279             };
39280             me.mask.updateBox({
39281                 x: posX - abs(width),
39282                 y: posY - abs(height),
39283                 width: abs(width),
39284                 height: abs(height)
39285             });
39286             me.mask.show();
39287             me.maskSprite.setAttributes({
39288                 hidden: true    
39289             }, true);
39290         }
39291         else {
39292             if (mask == 'horizontal') {
39293                 path = ['M', staticX, y, 'L', staticX, height];
39294             }
39295             else if (mask == 'vertical') {
39296                 path = ['M', x, staticY, 'L', width, staticY];
39297             }
39298             else {
39299                 path = ['M', staticX, y, 'L', staticX, height, 'M', x, staticY, 'L', width, staticY];
39300             }
39301             me.maskSprite.setAttributes({
39302                 path: path,
39303                 fill: me.maskMouseDown ? me.maskSprite.stroke : false,
39304                 'stroke-width': mask === true ? 1 : 3,
39305                 hidden: false
39306             }, true);
39307         }
39308     },
39309
39310     onMouseLeave: function(e) {
39311         var me = this;
39312         me.mouseMoved = false;
39313         me.mouseDown = false;
39314         me.maskMouseDown = false;
39315         me.mask.hide();
39316         me.maskSprite.hide(true);
39317     }
39318 });
39319     
39320
39321 Ext.define('Ext.chart.Navigation', {
39322
39323     constructor: function() {
39324         this.originalStore = this.store;
39325     },
39326     
39327     
39328     setZoom: function(zoomConfig) {
39329         var me = this,
39330             store = me.substore || me.store,
39331             bbox = me.chartBBox,
39332             len = store.getCount(),
39333             from = (zoomConfig.x / bbox.width * len) >> 0,
39334             to = Math.ceil(((zoomConfig.x + zoomConfig.width) / bbox.width * len)),
39335             recFieldsLen, recFields = [], curField, json = [], obj;
39336         
39337         store.each(function(rec, i) {
39338             if (i < from || i > to) {
39339                 return;
39340             }
39341             obj = {};
39342             
39343             if (!recFields.length) {
39344                 rec.fields.each(function(f) {
39345                     recFields.push(f.name);
39346                 });
39347                 recFieldsLen = recFields.length;
39348             }
39349             
39350             for (i = 0; i < recFieldsLen; i++) {
39351                 curField = recFields[i];
39352                 obj[curField] = rec.get(curField);
39353             }
39354             json.push(obj);
39355         });
39356         me.store = me.substore = Ext.create('Ext.data.JsonStore', {
39357             fields: recFields,
39358             data: json
39359         });
39360         me.redraw(true);
39361     },
39362
39363     restoreZoom: function() {
39364         this.store = this.substore = this.originalStore;
39365         this.redraw(true);
39366     }
39367     
39368 });
39369
39370 Ext.define('Ext.chart.Shape', {
39371
39372     
39373
39374     singleton: true,
39375
39376     
39377
39378     circle: function (surface, opts) {
39379         return surface.add(Ext.apply({
39380             type: 'circle',
39381             x: opts.x,
39382             y: opts.y,
39383             stroke: null,
39384             radius: opts.radius
39385         }, opts));
39386     },
39387     line: function (surface, opts) {
39388         return surface.add(Ext.apply({
39389             type: 'rect',
39390             x: opts.x - opts.radius,
39391             y: opts.y - opts.radius,
39392             height: 2 * opts.radius,
39393             width: 2 * opts.radius / 5
39394         }, opts));
39395     },
39396     square: function (surface, opts) {
39397         return surface.add(Ext.applyIf({
39398             type: 'rect',
39399             x: opts.x - opts.radius,
39400             y: opts.y - opts.radius,
39401             height: 2 * opts.radius,
39402             width: 2 * opts.radius,
39403             radius: null
39404         }, opts));
39405     },
39406     triangle: function (surface, opts) {
39407         opts.radius *= 1.75;
39408         return surface.add(Ext.apply({
39409             type: 'path',
39410             stroke: null,
39411             path: "M".concat(opts.x, ",", opts.y, "m0-", opts.radius * 0.58, "l", opts.radius * 0.5, ",", opts.radius * 0.87, "-", opts.radius, ",0z")
39412         }, opts));
39413     },
39414     diamond: function (surface, opts) {
39415         var r = opts.radius;
39416         r *= 1.5;
39417         return surface.add(Ext.apply({
39418             type: 'path',
39419             stroke: null,
39420             path: ["M", opts.x, opts.y - r, "l", r, r, -r, r, -r, -r, r, -r, "z"]
39421         }, opts));
39422     },
39423     cross: function (surface, opts) {
39424         var r = opts.radius;
39425         r = r / 1.7;
39426         return surface.add(Ext.apply({
39427             type: 'path',
39428             stroke: null,
39429             path: "M".concat(opts.x - r, ",", opts.y, "l", [-r, -r, r, -r, r, r, r, -r, r, r, -r, r, r, r, -r, r, -r, -r, -r, r, -r, -r, "z"])
39430         }, opts));
39431     },
39432     plus: function (surface, opts) {
39433         var r = opts.radius / 1.3;
39434         return surface.add(Ext.apply({
39435             type: 'path',
39436             stroke: null,
39437             path: "M".concat(opts.x - r / 2, ",", opts.y - r / 2, "l", [0, -r, r, 0, 0, r, r, 0, 0, r, -r, 0, 0, r, -r, 0, 0, -r, -r, 0, 0, -r, "z"])
39438         }, opts));
39439     },
39440     arrow: function (surface, opts) {
39441         var r = opts.radius;
39442         return surface.add(Ext.apply({
39443             type: 'path',
39444             path: "M".concat(opts.x - r * 0.7, ",", opts.y - r * 0.4, "l", [r * 0.6, 0, 0, -r * 0.4, r, r * 0.8, -r, r * 0.8, 0, -r * 0.4, -r * 0.6, 0], "z")
39445         }, opts));
39446     },
39447     drop: function (surface, x, y, text, size, angle) {
39448         size = size || 30;
39449         angle = angle || 0;
39450         surface.add({
39451             type: 'path',
39452             path: ['M', x, y, 'l', size, 0, 'A', size * 0.4, size * 0.4, 0, 1, 0, x + size * 0.7, y - size * 0.7, 'z'],
39453             fill: '#000',
39454             stroke: 'none',
39455             rotate: {
39456                 degrees: 22.5 - angle,
39457                 x: x,
39458                 y: y
39459             }
39460         });
39461         angle = (angle + 90) * Math.PI / 180;
39462         surface.add({
39463             type: 'text',
39464             x: x + size * Math.sin(angle) - 10, 
39465             y: y + size * Math.cos(angle) + 5,
39466             text:  text,
39467             'font-size': size * 12 / 40,
39468             stroke: 'none',
39469             fill: '#fff'
39470         });
39471     }
39472 });
39473
39474 Ext.define('Ext.draw.Surface', {
39475
39476     
39477
39478     mixins: {
39479         observable: 'Ext.util.Observable'
39480     },
39481
39482     requires: ['Ext.draw.CompositeSprite'],
39483     uses: ['Ext.draw.engine.Svg', 'Ext.draw.engine.Vml'],
39484
39485     separatorRe: /[, ]+/,
39486
39487     statics: {
39488         
39489         create: function(config, enginePriority) {
39490             enginePriority = enginePriority || ['Svg', 'Vml'];
39491
39492             var i = 0,
39493                 len = enginePriority.length,
39494                 surfaceClass;
39495
39496             for (; i < len; i++) {
39497                 if (Ext.supports[enginePriority[i]]) {
39498                     return Ext.create('Ext.draw.engine.' + enginePriority[i], config);
39499                 }
39500             }
39501             return false;
39502         }
39503     },
39504
39505     
39506
39507     
39508     availableAttrs: {
39509         blur: 0,
39510         "clip-rect": "0 0 1e9 1e9",
39511         cursor: "default",
39512         cx: 0,
39513         cy: 0,
39514         'dominant-baseline': 'auto',
39515         fill: "none",
39516         "fill-opacity": 1,
39517         font: '10px "Arial"',
39518         "font-family": '"Arial"',
39519         "font-size": "10",
39520         "font-style": "normal",
39521         "font-weight": 400,
39522         gradient: "",
39523         height: 0,
39524         hidden: false,
39525         href: "http://sencha.com/",
39526         opacity: 1,
39527         path: "M0,0",
39528         radius: 0,
39529         rx: 0,
39530         ry: 0,
39531         scale: "1 1",
39532         src: "",
39533         stroke: "#000",
39534         "stroke-dasharray": "",
39535         "stroke-linecap": "butt",
39536         "stroke-linejoin": "butt",
39537         "stroke-miterlimit": 0,
39538         "stroke-opacity": 1,
39539         "stroke-width": 1,
39540         target: "_blank",
39541         text: "",
39542         "text-anchor": "middle",
39543         title: "Ext Draw",
39544         width: 0,
39545         x: 0,
39546         y: 0,
39547         zIndex: 0
39548     },
39549
39550  
39551  
39552     container: undefined,
39553     height: 352,
39554     width: 512,
39555     x: 0,
39556     y: 0,
39557
39558     constructor: function(config) {
39559         var me = this;
39560         config = config || {};
39561         Ext.apply(me, config);
39562
39563         me.domRef = Ext.getDoc().dom;
39564         
39565         me.customAttributes = {};
39566
39567         me.addEvents(
39568             'mousedown',
39569             'mouseup',
39570             'mouseover',
39571             'mouseout',
39572             'mousemove',
39573             'mouseenter',
39574             'mouseleave',
39575             'click'
39576         );
39577
39578         me.mixins.observable.constructor.call(me);
39579
39580         me.getId();
39581         me.initGradients();
39582         me.initItems();
39583         if (me.renderTo) {
39584             me.render(me.renderTo);
39585             delete me.renderTo;
39586         }
39587         me.initBackground(config.background);
39588     },
39589
39590     
39591     
39592     initSurface: Ext.emptyFn,
39593
39594     
39595     
39596     renderItem: Ext.emptyFn,
39597
39598     
39599     renderItems: Ext.emptyFn,
39600
39601     
39602     setViewBox: Ext.emptyFn,
39603
39604     
39605     addCls: Ext.emptyFn,
39606
39607     
39608     removeCls: Ext.emptyFn,
39609
39610     
39611     setStyle: Ext.emptyFn,
39612
39613     
39614     initGradients: function() {
39615         var gradients = this.gradients;
39616         if (gradients) {
39617             Ext.each(gradients, this.addGradient, this);
39618         }
39619     },
39620
39621     
39622     initItems: function() {
39623         var items = this.items;
39624         this.items = Ext.create('Ext.draw.CompositeSprite');
39625         this.groups = Ext.create('Ext.draw.CompositeSprite');
39626         if (items) {
39627             this.add(items);
39628         }
39629     },
39630     
39631     
39632     initBackground: function(config) {
39633         var gradientId, 
39634             gradient,
39635             backgroundSprite,
39636             width = this.width,
39637             height = this.height;
39638         if (config) {
39639             if (config.gradient) {
39640                 gradient = config.gradient;
39641                 gradientId = gradient.id;
39642                 this.addGradient(gradient);
39643                 this.background = this.add({
39644                     type: 'rect',
39645                     x: 0,
39646                     y: 0,
39647                     width: width,
39648                     height: height,
39649                     fill: 'url(#' + gradientId + ')'
39650                 });
39651             } else if (config.fill) {
39652                 this.background = this.add({
39653                     type: 'rect',
39654                     x: 0,
39655                     y: 0,
39656                     width: width,
39657                     height: height,
39658                     fill: config.fill
39659                 });
39660             } else if (config.image) {
39661                 this.background = this.add({
39662                     type: 'image',
39663                     x: 0,
39664                     y: 0,
39665                     width: width,
39666                     height: height,
39667                     src: config.image
39668                 });
39669             }
39670         }
39671     },
39672     
39673     
39674     setSize: function(w, h) {
39675         if (this.background) {
39676             this.background.setAttributes({
39677                 width: w,
39678                 height: h,
39679                 hidden: false
39680             }, true);
39681         }
39682     },
39683
39684     
39685     scrubAttrs: function(sprite) {
39686         var i,
39687             attrs = {},
39688             exclude = {},
39689             sattr = sprite.attr;
39690         for (i in sattr) {    
39691             
39692             if (this.translateAttrs.hasOwnProperty(i)) {
39693                 
39694                 attrs[this.translateAttrs[i]] = sattr[i];
39695                 exclude[this.translateAttrs[i]] = true;
39696             }
39697             else if (this.availableAttrs.hasOwnProperty(i) && !exclude[i]) {
39698                 
39699                 attrs[i] = sattr[i];
39700             }
39701         }
39702         return attrs;
39703     },
39704
39705     
39706     onClick: function(e) {
39707         this.processEvent('click', e);
39708     },
39709
39710     
39711     onMouseUp: function(e) {
39712         this.processEvent('mouseup', e);
39713     },
39714
39715     
39716     onMouseDown: function(e) {
39717         this.processEvent('mousedown', e);
39718     },
39719
39720     
39721     onMouseOver: function(e) {
39722         this.processEvent('mouseover', e);
39723     },
39724
39725     
39726     onMouseOut: function(e) {
39727         this.processEvent('mouseout', e);
39728     },
39729
39730     
39731     onMouseMove: function(e) {
39732         this.fireEvent('mousemove', e);
39733     },
39734
39735     
39736     onMouseEnter: Ext.emptyFn,
39737
39738     
39739     onMouseLeave: Ext.emptyFn,
39740
39741     
39742     addGradient: Ext.emptyFn,
39743
39744     
39745     add: function() {
39746         var args = Array.prototype.slice.call(arguments),
39747             sprite,
39748             index;
39749
39750         var hasMultipleArgs = args.length > 1;
39751         if (hasMultipleArgs || Ext.isArray(args[0])) {
39752             var items = hasMultipleArgs ? args : args[0],
39753                 results = [],
39754                 i, ln, item;
39755
39756             for (i = 0, ln = items.length; i < ln; i++) {
39757                 item = items[i];
39758                 item = this.add(item);
39759                 results.push(item);
39760             }
39761
39762             return results;
39763         }
39764         sprite = this.prepareItems(args[0], true)[0];
39765         this.normalizeSpriteCollection(sprite);
39766         this.onAdd(sprite);
39767         return sprite;
39768     },
39769
39770     
39771     normalizeSpriteCollection: function(sprite) {
39772         var items = this.items,
39773             zIndex = sprite.attr.zIndex,
39774             idx = items.indexOf(sprite);
39775
39776         if (idx < 0 || (idx > 0 && items.getAt(idx - 1).attr.zIndex > zIndex) ||
39777                 (idx < items.length - 1 && items.getAt(idx + 1).attr.zIndex < zIndex)) {
39778             items.removeAt(idx);
39779             idx = items.findIndexBy(function(otherSprite) {
39780                 return otherSprite.attr.zIndex > zIndex;
39781             });
39782             if (idx < 0) {
39783                 idx = items.length;
39784             }
39785             items.insert(idx, sprite);
39786         }
39787         return idx;
39788     },
39789
39790     onAdd: function(sprite) {
39791         var group = sprite.group,
39792             draggable = sprite.draggable,
39793             groups, ln, i;
39794         if (group) {
39795             groups = [].concat(group);
39796             ln = groups.length;
39797             for (i = 0; i < ln; i++) {
39798                 group = groups[i];
39799                 this.getGroup(group).add(sprite);
39800             }
39801             delete sprite.group;
39802         }
39803         if (draggable) {
39804             sprite.initDraggable();
39805         }
39806     },
39807
39808     
39809     remove: function(sprite, destroySprite) {
39810         if (sprite) {
39811             this.items.remove(sprite);
39812             this.groups.each(function(item) {
39813                 item.remove(sprite);
39814             });
39815             sprite.onRemove();
39816             if (destroySprite === true) {
39817                 sprite.destroy();
39818             }
39819         }
39820     },
39821
39822     
39823     removeAll: function(destroySprites) {
39824         var items = this.items.items,
39825             ln = items.length,
39826             i;
39827         for (i = ln - 1; i > -1; i--) {
39828             this.remove(items[i], destroySprites);
39829         }
39830     },
39831
39832     onRemove: Ext.emptyFn,
39833
39834     onDestroy: Ext.emptyFn,
39835
39836     
39837     applyTransformations: function(sprite) {
39838             sprite.bbox.transform = 0;
39839             this.transform(sprite);
39840
39841         var me = this,
39842             dirty = false,
39843             attr = sprite.attr;
39844
39845         if (attr.translation.x != null || attr.translation.y != null) {
39846             me.translate(sprite);
39847             dirty = true;
39848         }
39849         if (attr.scaling.x != null || attr.scaling.y != null) {
39850             me.scale(sprite);
39851             dirty = true;
39852         }
39853         if (attr.rotation.degrees != null) {
39854             me.rotate(sprite);
39855             dirty = true;
39856         }
39857         if (dirty) {
39858             sprite.bbox.transform = 0;
39859             this.transform(sprite);
39860             sprite.transformations = [];
39861         }
39862     },
39863
39864     
39865     rotate: function (sprite) {
39866         var bbox,
39867             deg = sprite.attr.rotation.degrees,
39868             centerX = sprite.attr.rotation.x,
39869             centerY = sprite.attr.rotation.y;
39870         if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
39871             bbox = this.getBBox(sprite);
39872             centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
39873             centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
39874         }
39875         sprite.transformations.push({
39876             type: "rotate",
39877             degrees: deg,
39878             x: centerX,
39879             y: centerY
39880         });
39881     },
39882
39883     
39884     translate: function(sprite) {
39885         var x = sprite.attr.translation.x || 0,
39886             y = sprite.attr.translation.y || 0;
39887         sprite.transformations.push({
39888             type: "translate",
39889             x: x,
39890             y: y
39891         });
39892     },
39893
39894     
39895     scale: function(sprite) {
39896         var bbox,
39897             x = sprite.attr.scaling.x || 1,
39898             y = sprite.attr.scaling.y || 1,
39899             centerX = sprite.attr.scaling.centerX,
39900             centerY = sprite.attr.scaling.centerY;
39901
39902         if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
39903             bbox = this.getBBox(sprite);
39904             centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
39905             centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
39906         }
39907         sprite.transformations.push({
39908             type: "scale",
39909             x: x,
39910             y: y,
39911             centerX: centerX,
39912             centerY: centerY
39913         });
39914     },
39915
39916     
39917     rectPath: function (x, y, w, h, r) {
39918         if (r) {
39919             return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]];
39920         }
39921         return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]];
39922     },
39923
39924     
39925     ellipsePath: function (x, y, rx, ry) {
39926         if (ry == null) {
39927             ry = rx;
39928         }
39929         return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]];
39930     },
39931
39932     
39933     getPathpath: function (el) {
39934         return el.attr.path;
39935     },
39936
39937     
39938     getPathcircle: function (el) {
39939         var a = el.attr;
39940         return this.ellipsePath(a.x, a.y, a.radius, a.radius);
39941     },
39942
39943     
39944     getPathellipse: function (el) {
39945         var a = el.attr;
39946         return this.ellipsePath(a.x, a.y, a.radiusX, a.radiusY);
39947     },
39948
39949     
39950     getPathrect: function (el) {
39951         var a = el.attr;
39952         return this.rectPath(a.x, a.y, a.width, a.height, a.r);
39953     },
39954
39955     
39956     getPathimage: function (el) {
39957         var a = el.attr;
39958         return this.rectPath(a.x || 0, a.y || 0, a.width, a.height);
39959     },
39960
39961     
39962     getPathtext: function (el) {
39963         var bbox = this.getBBoxText(el);
39964         return this.rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
39965     },
39966
39967     createGroup: function(id) {
39968         var group = this.groups.get(id);
39969         if (!group) {
39970             group = Ext.create('Ext.draw.CompositeSprite', {
39971                 surface: this
39972             });
39973             group.id = id || Ext.id(null, 'ext-surface-group-');
39974             this.groups.add(group);
39975         }
39976         return group;
39977     },
39978
39979     
39980     getGroup: function(id) {
39981         if (typeof id == "string") {
39982             var group = this.groups.get(id);
39983             if (!group) {
39984                 group = this.createGroup(id);
39985             }
39986         } else {
39987             group = id;
39988         }
39989         return group;
39990     },
39991
39992     
39993     prepareItems: function(items, applyDefaults) {
39994         items = [].concat(items);
39995         
39996         var item, i, ln;
39997         for (i = 0, ln = items.length; i < ln; i++) {
39998             item = items[i];
39999             if (!(item instanceof Ext.draw.Sprite)) {
40000                 
40001                 item.surface = this;
40002                 items[i] = this.createItem(item);
40003             } else {
40004                 item.surface = this;
40005             }
40006         }
40007         return items;
40008     },
40009     
40010     
40011     setText: Ext.emptyFn,
40012     
40013     //@private Creates an item and appends it to the surface. Called
40014
40015     
40016     createItem: Ext.emptyFn,
40017
40018     
40019     getId: function() {
40020         return this.id || (this.id = Ext.id(null, 'ext-surface-'));
40021     },
40022
40023     
40024     destroy: function() {
40025         delete this.domRef;
40026         this.removeAll();
40027     }
40028 });
40029
40030 Ext.define('Ext.draw.Component', {
40031
40032     
40033
40034     alias: 'widget.draw',
40035
40036     extend: 'Ext.Component',
40037
40038     requires: [
40039         'Ext.draw.Surface',
40040         'Ext.layout.component.Draw'
40041     ],
40042
40043     
40044
40045     
40046     enginePriority: ['Svg', 'Vml'],
40047
40048     baseCls: Ext.baseCSSPrefix + 'surface',
40049
40050     componentLayout: 'draw',
40051
40052     
40053     viewBox: true,
40054
40055     
40056     autoSize: false,
40057     
40058     
40059
40060     initComponent: function() {
40061         this.callParent(arguments);
40062
40063         this.addEvents(
40064             'mousedown',
40065             'mouseup',
40066             'mousemove',
40067             'mouseenter',
40068             'mouseleave',
40069             'click'
40070         );
40071     },
40072
40073     
40074     onRender: function() {
40075         var me = this,
40076             viewBox = me.viewBox,
40077             autoSize = me.autoSize,
40078             bbox, items, width, height, x, y;
40079         me.callParent(arguments);
40080
40081         me.createSurface();
40082
40083         items = me.surface.items;
40084
40085         if (viewBox || autoSize) {
40086             bbox = items.getBBox();
40087             width = bbox.width;
40088             height = bbox.height;
40089             x = bbox.x;
40090             y = bbox.y;
40091             if (me.viewBox) {
40092                 me.surface.setViewBox(x, y, width, height);
40093             }
40094             else {
40095                 
40096                 me.autoSizeSurface();
40097             }
40098         }
40099     },
40100
40101     //@private
40102
40103     autoSizeSurface: function() {
40104         var me = this,
40105             items = me.surface.items,
40106             bbox = items.getBBox(),
40107             width = bbox.width,
40108             height = bbox.height;
40109         items.setAttributes({
40110             translate: {
40111                 x: -bbox.x,
40112                 
40113                 y: -bbox.y + (+Ext.isOpera)
40114             }
40115         }, true);
40116         if (me.rendered) {
40117             me.setSize(width, height);
40118         }
40119         else {
40120             me.surface.setSize(width, height);
40121         }
40122         me.el.setSize(width, height);
40123     },
40124
40125     
40126     createSurface: function() {
40127         var surface = Ext.draw.Surface.create(Ext.apply({}, {
40128                 width: this.width,
40129                 height: this.height,
40130                 renderTo: this.el
40131             }, this.initialConfig));
40132         this.surface = surface;
40133
40134         function refire(eventName) {
40135             return function(e) {
40136                 this.fireEvent(eventName, e);
40137             };
40138         }
40139
40140         surface.on({
40141             scope: this,
40142             mouseup: refire('mouseup'),
40143             mousedown: refire('mousedown'),
40144             mousemove: refire('mousemove'),
40145             mouseenter: refire('mouseenter'),
40146             mouseleave: refire('mouseleave'),
40147             click: refire('click')
40148         });
40149     },
40150
40151
40152     
40153     onDestroy: function() {
40154         var surface = this.surface;
40155         if (surface) {
40156             surface.destroy();
40157         }
40158         this.callParent(arguments);
40159     }
40160
40161 });
40162
40163
40164 Ext.define('Ext.chart.LegendItem', {
40165
40166     
40167
40168     extend: 'Ext.draw.CompositeSprite',
40169
40170     requires: ['Ext.chart.Shape'],
40171
40172     
40173
40174     
40175     x: 0,
40176     y: 0,
40177     zIndex: 500,
40178
40179     constructor: function(config) {
40180         this.callParent(arguments);
40181         this.createLegend(config);
40182     },
40183
40184     
40185     createLegend: function(config) {
40186         var me = this,
40187             index = config.yFieldIndex,
40188             series = me.series,
40189             seriesType = series.type,
40190             idx = me.yFieldIndex,
40191             legend = me.legend,
40192             surface = me.surface,
40193             refX = legend.x + me.x,
40194             refY = legend.y + me.y,
40195             bbox, z = me.zIndex,
40196             markerConfig, label, mask,
40197             radius, toggle = false,
40198             seriesStyle = Ext.apply(series.seriesStyle, series.style);
40199
40200         function getSeriesProp(name) {
40201             var val = series[name];
40202             return (Ext.isArray(val) ? val[idx] : val);
40203         }
40204         
40205         label = me.add('label', surface.add({
40206             type: 'text',
40207             x: 20,
40208             y: 0,
40209             zIndex: z || 0,
40210             font: legend.labelFont,
40211             text: getSeriesProp('title') || getSeriesProp('yField')
40212         }));
40213
40214         
40215         if (seriesType === 'line' || seriesType === 'scatter') {
40216             if(seriesType === 'line') {
40217                 me.add('line', surface.add({
40218                     type: 'path',
40219                     path: 'M0.5,0.5L16.5,0.5',
40220                     zIndex: z,
40221                     "stroke-width": series.lineWidth,
40222                     "stroke-linejoin": "round",
40223                     "stroke-dasharray": series.dash,
40224                     stroke: seriesStyle.stroke || '#000',
40225                     style: {
40226                         cursor: 'pointer'
40227                     }
40228                 }));
40229             }
40230             if (series.showMarkers || seriesType === 'scatter') {
40231                 markerConfig = Ext.apply(series.markerStyle, series.markerConfig || {});
40232                 me.add('marker', Ext.chart.Shape[markerConfig.type](surface, {
40233                     fill: markerConfig.fill,
40234                     x: 8.5,
40235                     y: 0.5,
40236                     zIndex: z,
40237                     radius: markerConfig.radius || markerConfig.size,
40238                     style: {
40239                         cursor: 'pointer'
40240                     }
40241                 }));
40242             }
40243         }
40244         
40245         else {
40246             me.add('box', surface.add({
40247                 type: 'rect',
40248                 zIndex: z,
40249                 x: 0,
40250                 y: 0,
40251                 width: 12,
40252                 height: 12,
40253                 fill: series.getLegendColor(index),
40254                 style: {
40255                     cursor: 'pointer'
40256                 }
40257             }));
40258         }
40259         
40260         me.setAttributes({
40261             hidden: false
40262         }, true);
40263         
40264         bbox = me.getBBox();
40265         
40266         mask = me.add('mask', surface.add({
40267             type: 'rect',
40268             x: bbox.x,
40269             y: bbox.y,
40270             width: bbox.width || 20,
40271             height: bbox.height || 20,
40272             zIndex: (z || 0) + 1000,
40273             fill: '#f00',
40274             opacity: 0,
40275             style: {
40276                 'cursor': 'pointer'
40277             }
40278         }));
40279
40280         
40281         me.on('mouseover', function() {
40282             label.setStyle({
40283                 'font-weight': 'bold'
40284             });
40285             mask.setStyle({
40286                 'cursor': 'pointer'
40287             });
40288             series._index = index;
40289             series.highlightItem();
40290         }, me);
40291
40292         me.on('mouseout', function() {
40293             label.setStyle({
40294                 'font-weight': 'normal'
40295             });
40296             series._index = index;
40297             series.unHighlightItem();
40298         }, me);
40299         
40300         if (!series.visibleInLegend(index)) {
40301             toggle = true;
40302             label.setAttributes({
40303                opacity: 0.5
40304             }, true);
40305         }
40306
40307         me.on('mousedown', function() {
40308             if (!toggle) {
40309                 series.hideAll();
40310                 label.setAttributes({
40311                     opacity: 0.5
40312                 }, true);
40313             } else {
40314                 series.showAll();
40315                 label.setAttributes({
40316                     opacity: 1
40317                 }, true);
40318             }
40319             toggle = !toggle;
40320         }, me);
40321         me.updatePosition({x:0, y:0}); 
40322     },
40323
40324     
40325     updatePosition: function(relativeTo) {
40326         var me = this,
40327             items = me.items,
40328             ln = items.length,
40329             i = 0,
40330             item;
40331         if (!relativeTo) {
40332             relativeTo = me.legend;
40333         }
40334         for (; i < ln; i++) {
40335             item = items[i];
40336             switch (item.type) {
40337                 case 'text':
40338                     item.setAttributes({
40339                         x: 20 + relativeTo.x + me.x,
40340                         y: relativeTo.y + me.y
40341                     }, true);
40342                     break;
40343                 case 'rect':
40344                     item.setAttributes({
40345                         translate: {
40346                             x: relativeTo.x + me.x,
40347                             y: relativeTo.y + me.y - 6
40348                         }
40349                     }, true);
40350                     break;
40351                 default:
40352                     item.setAttributes({
40353                         translate: {
40354                             x: relativeTo.x + me.x,
40355                             y: relativeTo.y + me.y
40356                         }
40357                     }, true);
40358             }
40359         }
40360     }
40361 });
40362
40363 Ext.define('Ext.chart.Legend', {
40364
40365     
40366
40367     requires: ['Ext.chart.LegendItem'],
40368
40369     
40370
40371     
40372     visible: true,
40373
40374     
40375     position: 'bottom',
40376
40377     
40378     x: 0,
40379
40380     
40381     y: 0,
40382
40383     
40384     labelFont: '12px Helvetica, sans-serif',
40385
40386     
40387     boxStroke: '#000',
40388
40389     
40390     boxStrokeWidth: 1,
40391
40392     
40393     boxFill: '#FFF',
40394
40395     
40396     itemSpacing: 10,
40397
40398     
40399     padding: 5,
40400
40401     
40402     width: 0,
40403     
40404     height: 0,
40405
40406     
40407     boxZIndex: 100,
40408
40409     constructor: function(config) {
40410         var me = this;
40411         if (config) {
40412             Ext.apply(me, config);
40413         }
40414         me.items = [];
40415         
40416         me.isVertical = ("left|right|float".indexOf(me.position) !== -1);
40417         
40418         
40419         me.origX = me.x;
40420         me.origY = me.y;
40421     },
40422
40423     
40424     create: function() {
40425         var me = this;
40426         me.createItems();
40427         if (!me.created && me.isDisplayed()) {
40428             me.createBox();
40429             me.created = true;
40430
40431             
40432             me.chart.series.each(function(series) {
40433                 series.on('titlechange', function() {
40434                     me.create();
40435                     me.updatePosition();
40436                 });
40437             });
40438         }
40439     },
40440
40441     
40442     isDisplayed: function() {
40443         return this.visible && this.chart.series.findIndex('showInLegend', true) !== -1;
40444     },
40445
40446     
40447     createItems: function() {
40448         var me = this,
40449             chart = me.chart,
40450             surface = chart.surface,
40451             items = me.items,
40452             padding = me.padding,
40453             itemSpacing = me.itemSpacing,
40454             spacingOffset = 2,
40455             maxWidth = 0,
40456             maxHeight = 0,
40457             totalWidth = 0,
40458             totalHeight = 0,
40459             vertical = me.isVertical,
40460             math = Math,
40461             mfloor = math.floor,
40462             mmax = math.max,
40463             index = 0, 
40464             i = 0, 
40465             len = items ? items.length : 0,
40466             x, y, spacing, item, bbox, height, width;
40467
40468         
40469         if (len) {
40470             for (; i < len; i++) {
40471                 items[i].destroy();
40472             }
40473         }
40474         
40475         items.length = [];
40476         
40477         
40478         chart.series.each(function(series, i) {
40479             if (series.showInLegend) {
40480                 Ext.each([].concat(series.yField), function(field, j) {
40481                     item = Ext.create('Ext.chart.LegendItem', {
40482                         legend: this,
40483                         series: series,
40484                         surface: chart.surface,
40485                         yFieldIndex: j
40486                     });
40487                     bbox = item.getBBox();
40488
40489                     
40490                     width = bbox.width; 
40491                     height = bbox.height;
40492
40493                     if (i + j === 0) {
40494                         spacing = vertical ? padding + height / 2 : padding;
40495                     }
40496                     else {
40497                         spacing = itemSpacing / (vertical ? 2 : 1);
40498                     }
40499                     
40500                     item.x = mfloor(vertical ? padding : totalWidth + spacing);
40501                     item.y = mfloor(vertical ? totalHeight + spacing : padding + height / 2);
40502
40503                     
40504                     totalWidth += width + spacing;
40505                     totalHeight += height + spacing;
40506                     maxWidth = mmax(maxWidth, width);
40507                     maxHeight = mmax(maxHeight, height);
40508
40509                     items.push(item);
40510                 }, this);
40511             }
40512         }, me);
40513
40514         
40515         me.width = mfloor((vertical ? maxWidth : totalWidth) + padding * 2);
40516         if (vertical && items.length === 1) {
40517             spacingOffset = 1;
40518         }
40519         me.height = mfloor((vertical ? totalHeight - spacingOffset * spacing : maxHeight) + (padding * 2));
40520         me.itemHeight = maxHeight;
40521     },
40522
40523     
40524     getBBox: function() {
40525         var me = this;
40526         return {
40527             x: Math.round(me.x) - me.boxStrokeWidth / 2,
40528             y: Math.round(me.y) - me.boxStrokeWidth / 2,
40529             width: me.width,
40530             height: me.height
40531         };
40532     },
40533
40534     
40535     createBox: function() {
40536         var me = this,
40537             box = me.boxSprite = me.chart.surface.add(Ext.apply({
40538                 type: 'rect',
40539                 stroke: me.boxStroke,
40540                 "stroke-width": me.boxStrokeWidth,
40541                 fill: me.boxFill,
40542                 zIndex: me.boxZIndex
40543             }, me.getBBox()));
40544         box.redraw();
40545     },
40546
40547     
40548     updatePosition: function() {
40549         var me = this,
40550             x, y,
40551             legendWidth = me.width,
40552             legendHeight = me.height,
40553             padding = me.padding,
40554             chart = me.chart,
40555             chartBBox = chart.chartBBox,
40556             insets = chart.insetPadding,
40557             chartWidth = chartBBox.width - (insets * 2),
40558             chartHeight = chartBBox.height - (insets * 2),
40559             chartX = chartBBox.x + insets,
40560             chartY = chartBBox.y + insets,
40561             surface = chart.surface,
40562             mfloor = Math.floor;
40563         
40564         if (me.isDisplayed()) {
40565             
40566             switch(me.position) {
40567                 case "left":
40568                     x = insets;
40569                     y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
40570                     break;
40571                 case "right":
40572                     x = mfloor(surface.width - legendWidth) - insets;
40573                     y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
40574                     break;
40575                 case "top":
40576                     x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
40577                     y = insets;
40578                     break;
40579                 case "bottom":
40580                     x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
40581                     y = mfloor(surface.height - legendHeight) - insets;
40582                     break;
40583                 default:
40584                     x = mfloor(me.origX) + insets;
40585                     y = mfloor(me.origY) + insets;
40586             }
40587             me.x = x;
40588             me.y = y;
40589
40590             
40591             Ext.each(me.items, function(item) {
40592                 item.updatePosition();
40593             });
40594             
40595             me.boxSprite.setAttributes(me.getBBox(), true);
40596         }
40597     }
40598 });
40599
40600
40601 Ext.define('Ext.chart.Chart', {
40602
40603     
40604
40605     alias: 'widget.chart',
40606
40607     extend: 'Ext.draw.Component',
40608     
40609     mixins: {
40610         themeManager: 'Ext.chart.theme.Theme',
40611         mask: 'Ext.chart.Mask',
40612         navigation: 'Ext.chart.Navigation'
40613     },
40614
40615     requires: [
40616         'Ext.util.MixedCollection',
40617         'Ext.data.StoreManager',
40618         'Ext.chart.Legend',
40619         'Ext.util.DelayedTask'
40620     ],
40621
40622     
40623
40624     
40625     viewBox: false,
40626
40627     
40628
40629     
40630     animate: false,
40631
40632     
40633     legend: false,
40634
40635     
40636     insetPadding: 10,
40637
40638     
40639     enginePriority: ['Svg', 'Vml'],
40640
40641     
40642     background: false,
40643
40644     
40645
40646
40647     constructor: function(config) {
40648         var me = this,
40649             defaultAnim;
40650         me.initTheme(config.theme || me.theme);
40651         if (me.gradients) {
40652             Ext.apply(config, { gradients: me.gradients });
40653         }
40654         if (me.background) {
40655             Ext.apply(config, { background: me.background });
40656         }
40657         if (config.animate) {
40658             defaultAnim = {
40659                 easing: 'ease',
40660                 duration: 500
40661             };
40662             if (Ext.isObject(config.animate)) {
40663                 config.animate = Ext.applyIf(config.animate, defaultAnim);
40664             }
40665             else {
40666                 config.animate = defaultAnim;
40667             }
40668         }
40669         me.mixins.mask.constructor.call(me, config);
40670         me.mixins.navigation.constructor.call(me, config);
40671         me.callParent([config]);
40672     },
40673
40674     initComponent: function() {
40675         var me = this,
40676             axes,
40677             series;
40678         me.callParent();
40679         me.addEvents(
40680             'itemmousedown',
40681             'itemmouseup',
40682             'itemmouseover',
40683             'itemmouseout',
40684             'itemclick',
40685             'itemdoubleclick',
40686             'itemdragstart',
40687             'itemdrag',
40688             'itemdragend',
40689             
40690             'beforerefresh',
40691             
40692             'refresh'
40693         );
40694         Ext.applyIf(me, {
40695             zoom: {
40696                 width: 1,
40697                 height: 1,
40698                 x: 0,
40699                 y: 0
40700             }
40701         });
40702         me.maxGutter = [0, 0];
40703         me.store = Ext.data.StoreManager.lookup(me.store);
40704         axes = me.axes;
40705         me.axes = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.position; });
40706         if (axes) {
40707             me.axes.addAll(axes);
40708         }
40709         series = me.series;
40710         me.series = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.seriesId || (a.seriesId = Ext.id(null, 'ext-chart-series-')); });
40711         if (series) {
40712             me.series.addAll(series);
40713         }
40714         if (me.legend !== false) {
40715             me.legend = Ext.create('Ext.chart.Legend', Ext.applyIf({chart:me}, me.legend));
40716         }
40717
40718         me.on({
40719             mousemove: me.onMouseMove,
40720             mouseleave: me.onMouseLeave,
40721             mousedown: me.onMouseDown,
40722             mouseup: me.onMouseUp,
40723             scope: me
40724         });
40725     },
40726
40727     
40728     afterComponentLayout: function(width, height) {
40729         var me = this;
40730         if (Ext.isNumber(width) && Ext.isNumber(height)) {
40731             me.curWidth = width;
40732             me.curHeight = height;
40733             me.redraw(true);
40734         }
40735         this.callParent(arguments);
40736     },
40737
40738     
40739     redraw: function(resize) {
40740         var me = this,
40741             chartBBox = me.chartBBox = {
40742                 x: 0,
40743                 y: 0,
40744                 height: me.curHeight,
40745                 width: me.curWidth
40746             },
40747             legend = me.legend;
40748         me.surface.setSize(chartBBox.width, chartBBox.height);
40749         
40750         me.series.each(me.initializeSeries, me);
40751         me.axes.each(me.initializeAxis, me);
40752         
40753         
40754         me.axes.each(function(axis) {
40755             axis.processView();
40756         });
40757         me.axes.each(function(axis) {
40758             axis.drawAxis(true);
40759         });
40760
40761         
40762         if (legend !== false) {
40763             legend.create();
40764         }
40765
40766         
40767         me.alignAxes();
40768
40769         
40770         if (me.legend !== false) {
40771             legend.updatePosition();
40772         }
40773
40774         
40775         me.getMaxGutter();
40776
40777         
40778         me.resizing = !!resize;
40779
40780         me.axes.each(me.drawAxis, me);
40781         me.series.each(me.drawCharts, me);
40782         me.resizing = false;
40783     },
40784
40785     
40786     afterRender: function() {
40787         var ref,
40788             me = this;
40789         this.callParent();
40790
40791         if (me.categoryNames) {
40792             me.setCategoryNames(me.categoryNames);
40793         }
40794
40795         if (me.tipRenderer) {
40796             ref = me.getFunctionRef(me.tipRenderer);
40797             me.setTipRenderer(ref.fn, ref.scope);
40798         }
40799         me.bindStore(me.store, true);
40800         me.refresh();
40801     },
40802
40803     
40804     getEventXY: function(e) {
40805         var me = this,
40806             box = this.surface.getRegion(),
40807             pageXY = e.getXY(),
40808             x = pageXY[0] - box.left,
40809             y = pageXY[1] - box.top;
40810         return [x, y];
40811     },
40812
40813     
40814     onClick: function(e) {
40815         var me = this,
40816             position = me.getEventXY(e),
40817             item;
40818
40819         
40820         
40821         me.series.each(function(series) {
40822             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
40823                 if (series.getItemForPoint) {
40824                     item = series.getItemForPoint(position[0], position[1]);
40825                     if (item) {
40826                         series.fireEvent('itemclick', item);
40827                     }
40828                 }
40829             }
40830         }, me);
40831     },
40832
40833     
40834     onMouseDown: function(e) {
40835         var me = this,
40836             position = me.getEventXY(e),
40837             item;
40838
40839         if (me.mask) {
40840             me.mixins.mask.onMouseDown.call(me, e);
40841         }
40842         
40843         
40844         me.series.each(function(series) {
40845             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
40846                 if (series.getItemForPoint) {
40847                     item = series.getItemForPoint(position[0], position[1]);
40848                     if (item) {
40849                         series.fireEvent('itemmousedown', item);
40850                     }
40851                 }
40852             }
40853         }, me);
40854     },
40855
40856     
40857     onMouseUp: function(e) {
40858         var me = this,
40859             position = me.getEventXY(e),
40860             item;
40861
40862         if (me.mask) {
40863             me.mixins.mask.onMouseUp.call(me, e);
40864         }
40865         
40866         
40867         me.series.each(function(series) {
40868             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
40869                 if (series.getItemForPoint) {
40870                     item = series.getItemForPoint(position[0], position[1]);
40871                     if (item) {
40872                         series.fireEvent('itemmouseup', item);
40873                     }
40874                 }
40875             }
40876         }, me);
40877     },
40878
40879     
40880     onMouseMove: function(e) {
40881         var me = this,
40882             position = me.getEventXY(e),
40883             item, last, storeItem, storeField;
40884
40885         if (me.mask) {
40886             me.mixins.mask.onMouseMove.call(me, e);
40887         }
40888         
40889         
40890         me.series.each(function(series) {
40891             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
40892                 if (series.getItemForPoint) {
40893                     item = series.getItemForPoint(position[0], position[1]);
40894                     last = series._lastItemForPoint;
40895                     storeItem = series._lastStoreItem;
40896                     storeField = series._lastStoreField;
40897
40898
40899                     if (item !== last || item && (item.storeItem != storeItem || item.storeField != storeField)) {
40900                         if (last) {
40901                             series.fireEvent('itemmouseout', last);
40902                             delete series._lastItemForPoint;
40903                             delete series._lastStoreField;
40904                             delete series._lastStoreItem;
40905                         }
40906                         if (item) {
40907                             series.fireEvent('itemmouseover', item);
40908                             series._lastItemForPoint = item;
40909                             series._lastStoreItem = item.storeItem;
40910                             series._lastStoreField = item.storeField;
40911                         }
40912                     }
40913                 }
40914             } else {
40915                 last = series._lastItemForPoint;
40916                 if (last) {
40917                     series.fireEvent('itemmouseout', last);
40918                     delete series._lastItemForPoint;
40919                     delete series._lastStoreField;
40920                     delete series._lastStoreItem;
40921                 }
40922             }
40923         }, me);
40924     },
40925
40926     
40927     onMouseLeave: function(e) {
40928         var me = this;
40929         if (me.mask) {
40930             me.mixins.mask.onMouseLeave.call(me, e);
40931         }
40932         me.series.each(function(series) {
40933             delete series._lastItemForPoint;
40934         });
40935     },
40936
40937     
40938     delayRefresh: function() {
40939         var me = this;
40940         if (!me.refreshTask) {
40941             me.refreshTask = Ext.create('Ext.util.DelayedTask', me.refresh, me);
40942         }
40943         me.refreshTask.delay(me.refreshBuffer);
40944     },
40945
40946     
40947     refresh: function() {
40948         var me = this;
40949         if (me.rendered && me.curWidth != undefined && me.curHeight != undefined) {
40950             if (me.fireEvent('beforerefresh', me) !== false) {
40951                 me.redraw();
40952                 me.fireEvent('refresh', me);
40953             }
40954         }
40955     },
40956
40957     
40958     bindStore: function(store, initial) {
40959         var me = this;
40960         if (!initial && me.store) {
40961             if (store !== me.store && me.store.autoDestroy) {
40962                 me.store.destroy();
40963             }
40964             else {
40965                 me.store.un('datachanged', me.refresh, me);
40966                 me.store.un('add', me.delayRefresh, me);
40967                 me.store.un('remove', me.delayRefresh, me);
40968                 me.store.un('update', me.delayRefresh, me);
40969                 me.store.un('clear', me.refresh, me);
40970             }
40971         }
40972         if (store) {
40973             store = Ext.data.StoreManager.lookup(store);
40974             store.on({
40975                 scope: me,
40976                 datachanged: me.refresh,
40977                 add: me.delayRefresh,
40978                 remove: me.delayRefresh,
40979                 update: me.delayRefresh,
40980                 clear: me.refresh
40981             });
40982         }
40983         me.store = store;
40984         if (store && !initial) {
40985             me.refresh();
40986         }
40987     },
40988
40989     
40990     initializeAxis: function(axis) {
40991         var me = this,
40992             chartBBox = me.chartBBox,
40993             w = chartBBox.width,
40994             h = chartBBox.height,
40995             x = chartBBox.x,
40996             y = chartBBox.y,
40997             themeAttrs = me.themeAttrs,
40998             config = {
40999                 chart: me
41000             };
41001         if (themeAttrs) {
41002             config.axisStyle = Ext.apply({}, themeAttrs.axis);
41003             config.axisLabelLeftStyle = Ext.apply({}, themeAttrs.axisLabelLeft);
41004             config.axisLabelRightStyle = Ext.apply({}, themeAttrs.axisLabelRight);
41005             config.axisLabelTopStyle = Ext.apply({}, themeAttrs.axisLabelTop);
41006             config.axisLabelBottomStyle = Ext.apply({}, themeAttrs.axisLabelBottom);
41007             config.axisTitleLeftStyle = Ext.apply({}, themeAttrs.axisTitleLeft);
41008             config.axisTitleRightStyle = Ext.apply({}, themeAttrs.axisTitleRight);
41009             config.axisTitleTopStyle = Ext.apply({}, themeAttrs.axisTitleTop);
41010             config.axisTitleBottomStyle = Ext.apply({}, themeAttrs.axisTitleBottom);
41011         }
41012         switch (axis.position) {
41013             case 'top':
41014                 Ext.apply(config, {
41015                     length: w,
41016                     width: h,
41017                     x: x,
41018                     y: y
41019                 });
41020             break;
41021             case 'bottom':
41022                 Ext.apply(config, {
41023                     length: w,
41024                     width: h,
41025                     x: x,
41026                     y: h
41027                 });
41028             break;
41029             case 'left':
41030                 Ext.apply(config, {
41031                     length: h,
41032                     width: w,
41033                     x: x,
41034                     y: h
41035                 });
41036             break;
41037             case 'right':
41038                 Ext.apply(config, {
41039                     length: h,
41040                     width: w,
41041                     x: w,
41042                     y: h
41043                 });
41044             break;
41045         }
41046         if (!axis.chart) {
41047             Ext.apply(config, axis);
41048             axis = me.axes.replace(Ext.createByAlias('axis.' + axis.type.toLowerCase(), config));
41049         }
41050         else {
41051             Ext.apply(axis, config);
41052         }
41053     },
41054
41055
41056     
41057     alignAxes: function() {
41058         var me = this,
41059             axes = me.axes,
41060             legend = me.legend,
41061             edges = ['top', 'right', 'bottom', 'left'],
41062             chartBBox,
41063             insetPadding = me.insetPadding,
41064             insets = {
41065                 top: insetPadding,
41066                 right: insetPadding,
41067                 bottom: insetPadding,
41068                 left: insetPadding
41069             };
41070
41071         function getAxis(edge) {
41072             var i = axes.findIndex('position', edge);
41073             return (i < 0) ? null : axes.getAt(i);
41074         }
41075
41076         
41077         Ext.each(edges, function(edge) {
41078             var isVertical = (edge === 'left' || edge === 'right'),
41079                 axis = getAxis(edge),
41080                 bbox;
41081
41082             
41083             if (legend !== false) {
41084                 if (legend.position === edge) {
41085                     bbox = legend.getBBox();
41086                     insets[edge] += (isVertical ? bbox.width : bbox.height) + insets[edge];
41087                 }
41088             }
41089
41090             
41091             
41092             if (axis && axis.bbox) {
41093                 bbox = axis.bbox;
41094                 insets[edge] += (isVertical ? bbox.width : bbox.height);
41095             }
41096         });
41097         
41098         chartBBox = {
41099             x: insets.left,
41100             y: insets.top,
41101             width: me.curWidth - insets.left - insets.right,
41102             height: me.curHeight - insets.top - insets.bottom
41103         };
41104         me.chartBBox = chartBBox;
41105
41106         
41107         
41108         axes.each(function(axis) {
41109             var pos = axis.position,
41110                 isVertical = (pos === 'left' || pos === 'right');
41111
41112             axis.x = (pos === 'right' ? chartBBox.x + chartBBox.width : chartBBox.x);
41113             axis.y = (pos === 'top' ? chartBBox.y : chartBBox.y + chartBBox.height);
41114             axis.width = (isVertical ? chartBBox.width : chartBBox.height);
41115             axis.length = (isVertical ? chartBBox.height : chartBBox.width);
41116         });
41117     },
41118
41119     
41120     initializeSeries: function(series, idx) {
41121         var me = this,
41122             themeAttrs = me.themeAttrs,
41123             seriesObj, markerObj, seriesThemes, st,
41124             markerThemes, colorArrayStyle = [],
41125             i = 0, l,
41126             config = {
41127                 chart: me,
41128                 seriesId: series.seriesId
41129             };
41130         if (themeAttrs) {
41131             seriesThemes = themeAttrs.seriesThemes;
41132             markerThemes = themeAttrs.markerThemes;
41133             seriesObj = Ext.apply({}, themeAttrs.series);
41134             markerObj = Ext.apply({}, themeAttrs.marker);
41135             config.seriesStyle = Ext.apply(seriesObj, seriesThemes[idx % seriesThemes.length]);
41136             config.seriesLabelStyle = Ext.apply({}, themeAttrs.seriesLabel);
41137             config.markerStyle = Ext.apply(markerObj, markerThemes[idx % markerThemes.length]);
41138             if (themeAttrs.colors) {
41139                 config.colorArrayStyle = themeAttrs.colors;
41140             } else {
41141                 colorArrayStyle = [];
41142                 for (l = seriesThemes.length; i < l; i++) {
41143                     st = seriesThemes[i];
41144                     if (st.fill || st.stroke) {
41145                         colorArrayStyle.push(st.fill || st.stroke);
41146                     }
41147                 }
41148                 if (colorArrayStyle.length) {
41149                     config.colorArrayStyle = colorArrayStyle;
41150                 }
41151             }
41152             config.seriesIdx = idx;
41153         }
41154         if (series instanceof Ext.chart.series.Series) {
41155             Ext.apply(series, config);
41156         } else {
41157             Ext.applyIf(config, series);
41158             series = me.series.replace(Ext.createByAlias('series.' + series.type.toLowerCase(), config));
41159         }
41160         if (series.initialize) {
41161             series.initialize();
41162         }
41163     },
41164
41165     
41166     getMaxGutter: function() {
41167         var me = this,
41168             maxGutter = [0, 0];
41169         me.series.each(function(s) {
41170             var gutter = s.getGutters && s.getGutters() || [0, 0];
41171             maxGutter[0] = Math.max(maxGutter[0], gutter[0]);
41172             maxGutter[1] = Math.max(maxGutter[1], gutter[1]);
41173         });
41174         me.maxGutter = maxGutter;
41175     },
41176
41177     
41178     drawAxis: function(axis) {
41179         axis.drawAxis();
41180     },
41181
41182     
41183     drawCharts: function(series) {
41184         series.triggerafterrender = false;
41185         series.drawSeries();
41186         if (!this.animate) {
41187             series.fireEvent('afterrender');
41188         }
41189     },
41190
41191     
41192     destroy: function() {
41193         this.surface.destroy();
41194         this.bindStore(null);
41195         this.callParent(arguments);
41196     }
41197 });
41198
41199
41200 Ext.define('Ext.chart.Highlight', {
41201
41202     
41203
41204     requires: ['Ext.fx.Anim'],
41205
41206     
41207
41208     
41209     highlight: false,
41210
41211     highlightCfg : null,
41212
41213     constructor: function(config) {
41214         if (config.highlight) {
41215             if (config.highlight !== true) { 
41216                 this.highlightCfg = Ext.apply({}, config.highlight);
41217             }
41218             else {
41219                 this.highlightCfg = {
41220                     fill: '#fdd',
41221                     radius: 20,
41222                     lineWidth: 5,
41223                     stroke: '#f55'
41224                 };
41225             }
41226         }
41227     },
41228
41229     
41230     highlightItem: function(item) {
41231         if (!item) {
41232             return;
41233         }
41234         
41235         var me = this,
41236             sprite = item.sprite,
41237             opts = me.highlightCfg,
41238             surface = me.chart.surface,
41239             animate = me.chart.animate,
41240             p,
41241             from,
41242             to,
41243             pi;
41244
41245         if (!me.highlight || !sprite || sprite._highlighted) {
41246             return;
41247         }
41248         if (sprite._anim) {
41249             sprite._anim.paused = true;
41250         }
41251         sprite._highlighted = true;
41252         if (!sprite._defaults) {
41253             sprite._defaults = Ext.apply(sprite._defaults || {},
41254             sprite.attr);
41255             from = {};
41256             to = {};
41257             for (p in opts) {
41258                 if (! (p in sprite._defaults)) {
41259                     sprite._defaults[p] = surface.availableAttrs[p];
41260                 }
41261                 from[p] = sprite._defaults[p];
41262                 to[p] = opts[p];
41263                 if (Ext.isObject(opts[p])) {
41264                     from[p] = {};
41265                     to[p] = {};
41266                     Ext.apply(sprite._defaults[p], sprite.attr[p]);
41267                     Ext.apply(from[p], sprite._defaults[p]);
41268                     for (pi in sprite._defaults[p]) {
41269                         if (! (pi in opts[p])) {
41270                             to[p][pi] = from[p][pi];
41271                         } else {
41272                             to[p][pi] = opts[p][pi];
41273                         }
41274                     }
41275                     for (pi in opts[p]) {
41276                         if (! (pi in to[p])) {
41277                             to[p][pi] = opts[p][pi];
41278                         }
41279                     }
41280                 }
41281             }
41282             sprite._from = from;
41283             sprite._to = to;
41284         }
41285         if (animate) {
41286             sprite._anim = Ext.create('Ext.fx.Anim', {
41287                 target: sprite,
41288                 from: sprite._from,
41289                 to: sprite._to,
41290                 duration: 150
41291             });
41292         } else {
41293             sprite.setAttributes(sprite._to, true);
41294         }
41295     },
41296
41297     
41298     unHighlightItem: function() {
41299         if (!this.highlight || !this.items) {
41300             return;
41301         }
41302
41303         var me = this,
41304             items = me.items,
41305             len = items.length,
41306             opts = me.highlightCfg,
41307             animate = me.chart.animate,
41308             i = 0,
41309             obj,
41310             p,
41311             sprite;
41312
41313         for (; i < len; i++) {
41314             if (!items[i]) {
41315                 continue;
41316             }
41317             sprite = items[i].sprite;
41318             if (sprite && sprite._highlighted) {
41319                 if (sprite._anim) {
41320                     sprite._anim.paused = true;
41321                 }
41322                 obj = {};
41323                 for (p in opts) {
41324                     if (Ext.isObject(sprite._defaults[p])) {
41325                         obj[p] = {};
41326                         Ext.apply(obj[p], sprite._defaults[p]);
41327                     }
41328                     else {
41329                         obj[p] = sprite._defaults[p];
41330                     }
41331                 }
41332                 if (animate) {
41333                     sprite._anim = Ext.create('Ext.fx.Anim', {
41334                         target: sprite,
41335                         to: obj,
41336                         duration: 150
41337                     });
41338                 }
41339                 else {
41340                     sprite.setAttributes(obj, true);
41341                 }
41342                 delete sprite._highlighted;
41343                 
41344             }
41345         }
41346     },
41347
41348     cleanHighlights: function() {
41349         if (!this.highlight) {
41350             return;
41351         }
41352
41353         var group = this.group,
41354             markerGroup = this.markerGroup,
41355             i = 0,
41356             l;
41357         for (l = group.getCount(); i < l; i++) {
41358             delete group.getAt(i)._defaults;
41359         }
41360         if (markerGroup) {
41361             for (l = markerGroup.getCount(); i < l; i++) {
41362                 delete markerGroup.getAt(i)._defaults;
41363             }
41364         }
41365     }
41366 });
41367
41368 Ext.define('Ext.chart.Label', {
41369
41370     
41371
41372     requires: ['Ext.draw.Color'],
41373     
41374     
41375
41376     
41377
41378     
41379
41380     
41381
41382     
41383
41384     
41385
41386     
41387
41388     
41389
41390     //@private a regex to parse url type colors.
41391
41392     colorStringRe: /url\s*\(\s*#([^\/)]+)\s*\)/,
41393     
41394     //@private the mixin constructor. Used internally by Series.
41395
41396     constructor: function(config) {
41397         var me = this;
41398         me.label = Ext.applyIf(me.label || {},
41399         {
41400             display: "none",
41401             color: "#000",
41402             field: "name",
41403             minMargin: 50,
41404             font: "11px Helvetica, sans-serif",
41405             orientation: "horizontal",
41406             renderer: function(v) {
41407                 return v;
41408             }
41409         });
41410
41411         if (me.label.display !== 'none') {
41412             me.labelsGroup = me.chart.surface.getGroup(me.seriesId + '-labels');
41413         }
41414     },
41415
41416     //@private a method to render all labels in the labelGroup
41417
41418     renderLabels: function() {
41419         var me = this,
41420             chart = me.chart,
41421             gradients = chart.gradients,
41422             gradient,
41423             items = me.items,
41424             animate = chart.animate,
41425             config = me.label,
41426             display = config.display,
41427             color = config.color,
41428             field = [].concat(config.field),
41429             group = me.labelsGroup,
41430             store = me.chart.store,
41431             len = store.getCount(),
41432             ratio = items.length / len,
41433             i, count, j, 
41434             k, gradientsCount = (gradients || 0) && gradients.length,
41435             colorStopTotal, colorStopIndex, colorStop,
41436             item, label, storeItem,
41437             sprite, spriteColor, spriteBrightness, labelColor,
41438             Color = Ext.draw.Color,
41439             colorString;
41440
41441         if (display == 'none') {
41442             return;
41443         }
41444
41445         for (i = 0, count = 0; i < len; i++) {
41446             for (j = 0; j < ratio; j++) {
41447                 item = items[count];
41448                 label = group.getAt(count);
41449                 storeItem = store.getAt(i);
41450
41451                 if (!item && label) {
41452                     label.hide(true);
41453                 }
41454
41455                 if (item && field[j]) {
41456                     if (!label) {
41457                         label = me.onCreateLabel(storeItem, item, i, display, j, count);
41458                     }
41459                     me.onPlaceLabel(label, storeItem, item, i, display, animate, j, count);
41460
41461                     
41462                     if (config.contrast && item.sprite) {
41463                         sprite = item.sprite;
41464                         colorString = sprite._to && sprite._to.fill || sprite.attr.fill;
41465                         spriteColor = Color.fromString(colorString);
41466                         
41467                         if (colorString && !spriteColor) {
41468                             colorString = colorString.match(me.colorStringRe)[1];
41469                             for (k = 0; k < gradientsCount; k++) {
41470                                 gradient = gradients[k];
41471                                 if (gradient.id == colorString) {
41472                                     
41473                                     colorStop = 0; colorStopTotal = 0;
41474                                     for (colorStopIndex in gradient.stops) {
41475                                         colorStop++;
41476                                         colorStopTotal += Color.fromString(gradient.stops[colorStopIndex].color).getGrayscale();
41477                                     }
41478                                     spriteBrightness = (colorStopTotal / colorStop) / 255;
41479                                     break;
41480                                 }
41481                             }
41482                         }
41483                         else {
41484                             spriteBrightness = spriteColor.getGrayscale() / 255;
41485                         }
41486                         labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
41487                         
41488                         labelColor[2] = spriteBrightness > 0.5? 0.2 : 0.8;
41489                         label.setAttributes({
41490                             fill: String(Color.fromHSL.apply({}, labelColor))
41491                         }, true);
41492                     }
41493                 }
41494                 count++;
41495             }
41496         }
41497         me.hideLabels(count);
41498     },
41499
41500     //@private a method to hide labels.
41501
41502     hideLabels: function(index) {
41503         var labelsGroup = this.labelsGroup, len;
41504         if (labelsGroup) {
41505             len = labelsGroup.getCount();
41506             while (len-->index) {
41507                 labelsGroup.getAt(len).hide(true);
41508             }
41509         }
41510     }
41511 });
41512 Ext.define('Ext.chart.MaskLayer', {
41513     extend: 'Ext.Component',
41514     
41515     constructor: function(config) {
41516         config = Ext.apply(config || {}, {
41517             style: 'position:absolute;background-color:#888;cursor:move;opacity:0.6;border:1px solid #222;'
41518         });
41519         this.callParent([config]);    
41520     },
41521     
41522     initComponent: function() {
41523         var me = this;
41524         me.callParent(arguments);
41525         me.addEvents(
41526             'mousedown',
41527             'mouseup',
41528             'mousemove',
41529             'mouseenter',
41530             'mouseleave'
41531         );
41532     },
41533
41534     initDraggable: function() {
41535         this.callParent(arguments);
41536         this.dd.onStart = function (e) {
41537             var me = this,
41538                 comp = me.comp;
41539     
41540             
41541             this.startPosition = comp.getPosition(true);
41542     
41543             
41544             
41545             if (comp.ghost && !comp.liveDrag) {
41546                  me.proxy = comp.ghost();
41547                  me.dragTarget = me.proxy.header.el;
41548             }
41549     
41550             
41551             if (me.constrain || me.constrainDelegate) {
41552                 me.constrainTo = me.calculateConstrainRegion();
41553             }
41554         };
41555     }
41556 });
41557
41558 Ext.define('Ext.chart.TipSurface', {
41559
41560     
41561
41562     extend: 'Ext.draw.Component',
41563
41564     
41565
41566     spriteArray: false,
41567     renderFirst: true,
41568
41569     constructor: function(config) {
41570         this.callParent([config]);
41571         if (config.sprites) {
41572             this.spriteArray = [].concat(config.sprites);
41573             delete config.sprites;
41574         }
41575     },
41576
41577     onRender: function() {
41578         var me = this,
41579             i = 0,
41580             l = 0,
41581             sp,
41582             sprites;
41583             this.callParent(arguments);
41584         sprites = me.spriteArray;
41585         if (me.renderFirst && sprites) {
41586             me.renderFirst = false;
41587             for (l = sprites.length; i < l; i++) {
41588                 sp = me.surface.add(sprites[i]);
41589                 sp.setAttributes({
41590                     hidden: false
41591                 },
41592                 true);
41593             }
41594         }
41595     }
41596 });
41597
41598
41599 Ext.define('Ext.chart.Tip', {
41600
41601     
41602
41603     requires: ['Ext.tip.ToolTip', 'Ext.chart.TipSurface'],
41604
41605     
41606
41607     constructor: function(config) {
41608         var me = this,
41609             surface,
41610             sprites,
41611             tipSurface;
41612         if (config.tips) {
41613             me.tipTimeout = null;
41614             me.tipConfig = Ext.apply({}, config.tips, {
41615                 renderer: Ext.emptyFn,
41616                 constrainPosition: false
41617             });
41618             me.tooltip = Ext.create('Ext.tip.ToolTip', me.tipConfig);
41619             Ext.getBody().on('mousemove', me.tooltip.onMouseMove, me.tooltip);
41620             if (me.tipConfig.surface) {
41621                 
41622                 surface = me.tipConfig.surface;
41623                 sprites = surface.sprites;
41624                 tipSurface = Ext.create('Ext.chart.TipSurface', {
41625                     id: 'tipSurfaceComponent',
41626                     sprites: sprites
41627                 });
41628                 if (surface.width && surface.height) {
41629                     tipSurface.setSize(surface.width, surface.height);
41630                 }
41631                 me.tooltip.add(tipSurface);
41632                 me.spriteTip = tipSurface;
41633             }
41634         }
41635     },
41636
41637     showTip: function(item) {
41638         var me = this;
41639         if (!me.tooltip) {
41640             return;
41641         }
41642         clearTimeout(me.tipTimeout);
41643         var tooltip = me.tooltip,
41644             spriteTip = me.spriteTip,
41645             tipConfig = me.tipConfig,
41646             trackMouse = tooltip.trackMouse,
41647             sprite, surface, surfaceExt, pos, x, y;
41648         if (!trackMouse) {
41649             tooltip.trackMouse = true;
41650             sprite = item.sprite;
41651             surface = sprite.surface;
41652             surfaceExt = Ext.get(surface.getId());
41653             if (surfaceExt) {
41654                 pos = surfaceExt.getXY();
41655                 x = pos[0] + (sprite.attr.x || 0) + (sprite.attr.translation && sprite.attr.translation.x || 0);
41656                 y = pos[1] + (sprite.attr.y || 0) + (sprite.attr.translation && sprite.attr.translation.y || 0);
41657                 tooltip.targetXY = [x, y];
41658             }
41659         }
41660         if (spriteTip) {
41661             tipConfig.renderer.call(tooltip, item.storeItem, item, spriteTip.surface);
41662         } else {
41663             tipConfig.renderer.call(tooltip, item.storeItem, item);
41664         }
41665         tooltip.show();
41666         tooltip.trackMouse = trackMouse;
41667     },
41668
41669     hideTip: function(item) {
41670         var tooltip = this.tooltip;
41671         if (!tooltip) {
41672             return;
41673         }
41674         clearTimeout(this.tipTimeout);
41675         this.tipTimeout = setTimeout(function() {
41676             tooltip.hide();
41677         }, 0);
41678     }
41679 });
41680
41681 Ext.define('Ext.chart.axis.Abstract', {
41682
41683     
41684
41685     requires: ['Ext.chart.Chart'],
41686
41687     
41688
41689     constructor: function(config) {
41690         config = config || {};
41691
41692         var me = this,
41693             pos = config.position || 'left';
41694
41695         pos = pos.charAt(0).toUpperCase() + pos.substring(1);
41696         
41697         config.label = Ext.apply(config['axisLabel' + pos + 'Style'] || {}, config.label || {});
41698         config.axisTitleStyle = Ext.apply(config['axisTitle' + pos + 'Style'] || {}, config.labelTitle || {});
41699         Ext.apply(me, config);
41700         me.fields = [].concat(me.fields);
41701         this.callParent();
41702         me.labels = [];
41703         me.getId();
41704         me.labelGroup = me.chart.surface.getGroup(me.axisId + "-labels");
41705     },
41706
41707     alignment: null,
41708     grid: false,
41709     steps: 10,
41710     x: 0,
41711     y: 0,
41712     minValue: 0,
41713     maxValue: 0,
41714
41715     getId: function() {
41716         return this.axisId || (this.axisId = Ext.id(null, 'ext-axis-'));
41717     },
41718
41719     
41720     processView: Ext.emptyFn,
41721
41722     drawAxis: Ext.emptyFn,
41723     addDisplayAndLabels: Ext.emptyFn
41724 });
41725
41726
41727 Ext.define('Ext.chart.axis.Axis', {
41728
41729     
41730
41731     extend: 'Ext.chart.axis.Abstract',
41732
41733     alternateClassName: 'Ext.chart.Axis',
41734
41735     requires: ['Ext.draw.Draw'],
41736
41737     
41738
41739     
41740
41741     
41742
41743     
41744     dashSize: 3,
41745     
41746     
41747     position: 'bottom',
41748     
41749     
41750     skipFirst: false,
41751     
41752     
41753     length: 0,
41754     
41755     
41756     width: 0,
41757     
41758     majorTickSteps: false,
41759
41760     
41761     applyData: Ext.emptyFn,
41762
41763     
41764     calcEnds: function() {
41765         var me = this,
41766             math = Math,
41767             mmax = math.max,
41768             mmin = math.min,
41769             store = me.chart.substore || me.chart.store,
41770             series = me.chart.series.items,
41771             fields = me.fields,
41772             ln = fields.length,
41773             min = isNaN(me.minimum) ? Infinity : me.minimum,
41774             max = isNaN(me.maximum) ? -Infinity : me.maximum,
41775             prevMin = me.prevMin,
41776             prevMax = me.prevMax,
41777             aggregate = false,
41778             total = 0,
41779             excludes = [],
41780             outfrom, outto,
41781             i, l, values, rec, out;
41782
41783         
41784         
41785         for (i = 0, l = series.length; !aggregate && i < l; i++) {
41786             aggregate = aggregate || series[i].stacked;
41787             excludes = series[i].__excludes || excludes;
41788         }
41789         store.each(function(record) {
41790             if (aggregate) {
41791                 if (!isFinite(min)) {
41792                     min = 0;
41793                 }
41794                 for (values = [0, 0], i = 0; i < ln; i++) {
41795                     if (excludes[i]) {
41796                         continue;
41797                     }
41798                     rec = record.get(fields[i]);
41799                     values[+(rec > 0)] += math.abs(rec);
41800                 }
41801                 max = mmax(max, -values[0], values[1]);
41802                 min = mmin(min, -values[0], values[1]);
41803             }
41804             else {
41805                 for (i = 0; i < ln; i++) {
41806                     if (excludes[i]) {
41807                         continue;
41808                     }
41809                     value = record.get(fields[i]);
41810                     max = mmax(max, value);
41811                     min = mmin(min, value);
41812                 }
41813             }
41814         });
41815         if (!isFinite(max)) {
41816             max = me.prevMax || 0;
41817         }
41818         if (!isFinite(min)) {
41819             min = me.prevMin || 0;
41820         }
41821         
41822         if (min != max && (max != (max >> 0))) {
41823             max = (max >> 0) + 1;
41824         }
41825         out = Ext.draw.Draw.snapEnds(min, max, me.majorTickSteps !== false ?  (me.majorTickSteps +1) : me.steps);
41826         outfrom = out.from;
41827         outto = out.to;
41828         if (!isNaN(me.maximum)) {
41829             
41830             
41831             out.to = me.maximum;
41832         }
41833         if (!isNaN(me.minimum)) {
41834             
41835             
41836             out.from = me.minimum;
41837         }
41838         
41839         
41840         out.step = (out.to - out.from) / (outto - outfrom) * out.step;
41841         
41842         if (me.adjustMaximumByMajorUnit) {
41843             out.to += out.step;
41844         }
41845         if (me.adjustMinimumByMajorUnit) {
41846             out.from -= out.step;
41847         }
41848         me.prevMin = min == max? 0 : min;
41849         me.prevMax = max;
41850         return out;
41851     },
41852
41853     
41854     drawAxis: function (init) {
41855         var me = this,
41856             i, j,
41857             x = me.x,
41858             y = me.y,
41859             gutterX = me.chart.maxGutter[0],
41860             gutterY = me.chart.maxGutter[1],
41861             dashSize = me.dashSize,
41862             subDashesX = me.minorTickSteps || 0,
41863             subDashesY = me.minorTickSteps || 0,
41864             length = me.length,
41865             position = me.position,
41866             inflections = [],
41867             calcLabels = false,
41868             stepCalcs = me.applyData(),
41869             step = stepCalcs.step,
41870             steps = stepCalcs.steps,
41871             from = stepCalcs.from,
41872             to = stepCalcs.to,
41873             trueLength,
41874             currentX,
41875             currentY,
41876             path,
41877             prev,
41878             dashesX,
41879             dashesY,
41880             delta;
41881         
41882         
41883         
41884         
41885         if (me.hidden || isNaN(step) || (from == to)) {
41886             return;
41887         }
41888
41889         me.from = stepCalcs.from;
41890         me.to = stepCalcs.to;
41891         if (position == 'left' || position == 'right') {
41892             currentX = Math.floor(x) + 0.5;
41893             path = ["M", currentX, y, "l", 0, -length];
41894             trueLength = length - (gutterY * 2);
41895         }
41896         else {
41897             currentY = Math.floor(y) + 0.5;
41898             path = ["M", x, currentY, "l", length, 0];
41899             trueLength = length - (gutterX * 2);
41900         }
41901         
41902         delta = trueLength / (steps || 1);
41903         dashesX = Math.max(subDashesX +1, 0);
41904         dashesY = Math.max(subDashesY +1, 0);
41905         if (me.type == 'Numeric') {
41906             calcLabels = true;
41907             me.labels = [stepCalcs.from];
41908         }
41909         if (position == 'right' || position == 'left') {
41910             currentY = y - gutterY;
41911             currentX = x - ((position == 'left') * dashSize * 2);
41912             while (currentY >= y - gutterY - trueLength) {
41913                 path.push("M", currentX, Math.floor(currentY) + 0.5, "l", dashSize * 2 + 1, 0);
41914                 if (currentY != y - gutterY) {
41915                     for (i = 1; i < dashesY; i++) {
41916                         path.push("M", currentX + dashSize, Math.floor(currentY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
41917                     }
41918                 }
41919                 inflections.push([ Math.floor(x), Math.floor(currentY) ]);
41920                 currentY -= delta;
41921                 if (calcLabels) {
41922                     me.labels.push(me.labels[me.labels.length -1] + step);
41923                 }
41924                 if (delta === 0) {
41925                     break;
41926                 }
41927             }
41928             if (Math.round(currentY + delta - (y - gutterY - trueLength))) {
41929                 path.push("M", currentX, Math.floor(y - length + gutterY) + 0.5, "l", dashSize * 2 + 1, 0);
41930                 for (i = 1; i < dashesY; i++) {
41931                     path.push("M", currentX + dashSize, Math.floor(y - length + gutterY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
41932                 }
41933                 inflections.push([ Math.floor(x), Math.floor(currentY) ]);
41934                 if (calcLabels) {
41935                     me.labels.push(me.labels[me.labels.length -1] + step);
41936                 }
41937             }
41938         } else {
41939             currentX = x + gutterX;
41940             currentY = y - ((position == 'top') * dashSize * 2);
41941             while (currentX <= x + gutterX + trueLength) {
41942                 path.push("M", Math.floor(currentX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
41943                 if (currentX != x + gutterX) {
41944                     for (i = 1; i < dashesX; i++) {
41945                         path.push("M", Math.floor(currentX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
41946                     }
41947                 }
41948                 inflections.push([ Math.floor(currentX), Math.floor(y) ]);
41949                 currentX += delta;
41950                 if (calcLabels) {
41951                     me.labels.push(me.labels[me.labels.length -1] + step);
41952                 }
41953                 if (delta === 0) {
41954                     break;
41955                 }
41956             }
41957             if (Math.round(currentX - delta - (x + gutterX + trueLength))) {
41958                 path.push("M", Math.floor(x + length - gutterX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
41959                 for (i = 1; i < dashesX; i++) {
41960                     path.push("M", Math.floor(x + length - gutterX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
41961                 }
41962                 inflections.push([ Math.floor(currentX), Math.floor(y) ]);
41963                 if (calcLabels) {
41964                     me.labels.push(me.labels[me.labels.length -1] + step);
41965                 }
41966             }
41967         }
41968         if (!me.axis) {
41969             me.axis = me.chart.surface.add(Ext.apply({
41970                 type: 'path',
41971                 path: path
41972             }, me.axisStyle));
41973         }
41974         me.axis.setAttributes({
41975             path: path
41976         }, true);
41977         me.inflections = inflections;
41978         if (!init && me.grid) {
41979             me.drawGrid();
41980         }
41981         me.axisBBox = me.axis.getBBox();
41982         me.drawLabel();
41983     },
41984
41985     
41986     drawGrid: function() {
41987         var me = this,
41988             surface = me.chart.surface, 
41989             grid = me.grid,
41990             odd = grid.odd,
41991             even = grid.even,
41992             inflections = me.inflections,
41993             ln = inflections.length - ((odd || even)? 0 : 1),
41994             position = me.position,
41995             gutter = me.chart.maxGutter,
41996             width = me.width - 2,
41997             vert = false,
41998             point, prevPoint,
41999             i = 1,
42000             path = [], styles, lineWidth, dlineWidth,
42001             oddPath = [], evenPath = [];
42002         
42003         if ((gutter[1] !== 0 && (position == 'left' || position == 'right')) ||
42004             (gutter[0] !== 0 && (position == 'top' || position == 'bottom'))) {
42005             i = 0;
42006             ln++;
42007         }
42008         for (; i < ln; i++) {
42009             point = inflections[i];
42010             prevPoint = inflections[i - 1];
42011             if (odd || even) {
42012                 path = (i % 2)? oddPath : evenPath;
42013                 styles = ((i % 2)? odd : even) || {};
42014                 lineWidth = (styles.lineWidth || styles['stroke-width'] || 0) / 2;
42015                 dlineWidth = 2 * lineWidth;
42016                 if (position == 'left') {
42017                     path.push("M", prevPoint[0] + 1 + lineWidth, prevPoint[1] + 0.5 - lineWidth, 
42018                               "L", prevPoint[0] + 1 + width - lineWidth, prevPoint[1] + 0.5 - lineWidth,
42019                               "L", point[0] + 1 + width - lineWidth, point[1] + 0.5 + lineWidth,
42020                               "L", point[0] + 1 + lineWidth, point[1] + 0.5 + lineWidth, "Z");
42021                 }
42022                 else if (position == 'right') {
42023                     path.push("M", prevPoint[0] - lineWidth, prevPoint[1] + 0.5 - lineWidth, 
42024                               "L", prevPoint[0] - width + lineWidth, prevPoint[1] + 0.5 - lineWidth,
42025                               "L", point[0] - width + lineWidth, point[1] + 0.5 + lineWidth,
42026                               "L", point[0] - lineWidth, point[1] + 0.5 + lineWidth, "Z");
42027                 }
42028                 else if (position == 'top') {
42029                     path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + lineWidth, 
42030                               "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + width - lineWidth,
42031                               "L", point[0] + 0.5 - lineWidth, point[1] + 1 + width - lineWidth,
42032                               "L", point[0] + 0.5 - lineWidth, point[1] + 1 + lineWidth, "Z");
42033                 }
42034                 else {
42035                     path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - lineWidth, 
42036                             "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - width + lineWidth,
42037                             "L", point[0] + 0.5 - lineWidth, point[1] - width + lineWidth,
42038                             "L", point[0] + 0.5 - lineWidth, point[1] - lineWidth, "Z");
42039                 }
42040             } else {
42041                 if (position == 'left') {
42042                     path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", width, 0]);
42043                 }
42044                 else if (position == 'right') {
42045                     path = path.concat(["M", point[0] - 0.5, point[1] + 0.5, "l", -width, 0]);
42046                 }
42047                 else if (position == 'top') {
42048                     path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", 0, width]);
42049                 }
42050                 else {
42051                     path = path.concat(["M", point[0] + 0.5, point[1] - 0.5, "l", 0, -width]);
42052                 }
42053             }
42054         }
42055         if (odd || even) {
42056             if (oddPath.length) {
42057                 if (!me.gridOdd && oddPath.length) {
42058                     me.gridOdd = surface.add({
42059                         type: 'path',
42060                         path: oddPath
42061                     });
42062                 }
42063                 me.gridOdd.setAttributes(Ext.apply({
42064                     path: oddPath,
42065                     hidden: false
42066                 }, odd || {}), true);
42067             }
42068             if (evenPath.length) {
42069                 if (!me.gridEven) {
42070                     me.gridEven = surface.add({
42071                         type: 'path',
42072                         path: evenPath
42073                     });
42074                 } 
42075                 me.gridEven.setAttributes(Ext.apply({
42076                     path: evenPath,
42077                     hidden: false
42078                 }, even || {}), true);
42079             }
42080         }
42081         else {
42082             if (path.length) {
42083                 if (!me.gridLines) {
42084                     me.gridLines = me.chart.surface.add({
42085                         type: 'path',
42086                         path: path,
42087                         "stroke-width": me.lineWidth || 1,
42088                         stroke: me.gridColor || '#ccc'
42089                     });
42090                 }
42091                 me.gridLines.setAttributes({
42092                     hidden: false,
42093                     path: path
42094                 }, true);
42095             }
42096             else if (me.gridLines) {
42097                 me.gridLines.hide(true);
42098             }
42099         }
42100     },
42101
42102     //@private
42103
42104     getOrCreateLabel: function(i, text) {
42105         var me = this,
42106             labelGroup = me.labelGroup,
42107             textLabel = labelGroup.getAt(i),
42108             surface = me.chart.surface;
42109         if (textLabel) {
42110             if (text != textLabel.attr.text) {
42111                 textLabel.setAttributes(Ext.apply({
42112                     text: text
42113                 }, me.label), true);
42114                 textLabel._bbox = textLabel.getBBox();
42115             }
42116         }
42117         else {
42118             textLabel = surface.add(Ext.apply({
42119                 group: labelGroup,
42120                 type: 'text',
42121                 x: 0,
42122                 y: 0,
42123                 text: text
42124             }, me.label));
42125             surface.renderItem(textLabel);
42126             textLabel._bbox = textLabel.getBBox();
42127         }
42128         
42129         if (me.label.rotation) {
42130             textLabel.setAttributes({
42131                 rotation: {
42132                     degrees: 0    
42133                 }    
42134             }, true);
42135             textLabel._ubbox = textLabel.getBBox();
42136             textLabel.setAttributes(me.label, true);
42137         } else {
42138             textLabel._ubbox = textLabel._bbox;
42139         }
42140         return textLabel;
42141     },
42142     
42143     rect2pointArray: function(sprite) {
42144         var surface = this.chart.surface,
42145             rect = surface.getBBox(sprite, true),
42146             p1 = [rect.x, rect.y],
42147             p1p = p1.slice(),
42148             p2 = [rect.x + rect.width, rect.y],
42149             p2p = p2.slice(),
42150             p3 = [rect.x + rect.width, rect.y + rect.height],
42151             p3p = p3.slice(),
42152             p4 = [rect.x, rect.y + rect.height],
42153             p4p = p4.slice(),
42154             matrix = sprite.matrix;
42155         
42156         p1[0] = matrix.x.apply(matrix, p1p);
42157         p1[1] = matrix.y.apply(matrix, p1p);
42158         
42159         p2[0] = matrix.x.apply(matrix, p2p);
42160         p2[1] = matrix.y.apply(matrix, p2p);
42161         
42162         p3[0] = matrix.x.apply(matrix, p3p);
42163         p3[1] = matrix.y.apply(matrix, p3p);
42164         
42165         p4[0] = matrix.x.apply(matrix, p4p);
42166         p4[1] = matrix.y.apply(matrix, p4p);
42167         return [p1, p2, p3, p4];
42168     },
42169     
42170     intersect: function(l1, l2) {
42171         var r1 = this.rect2pointArray(l1),
42172             r2 = this.rect2pointArray(l2);
42173         return !!Ext.draw.Draw.intersect(r1, r2).length;
42174     },
42175     
42176     drawHorizontalLabels: function() {
42177        var  me = this,
42178             labelConf = me.label,
42179             floor = Math.floor,
42180             max = Math.max,
42181             axes = me.chart.axes,
42182             position = me.position,
42183             inflections = me.inflections,
42184             ln = inflections.length,
42185             labels = me.labels,
42186             labelGroup = me.labelGroup,
42187             maxHeight = 0,
42188             ratio,
42189             gutterY = me.chart.maxGutter[1],
42190             ubbox, bbox, point, prevX, prevLabel,
42191             projectedWidth = 0,
42192             textLabel, attr, textRight, text,
42193             label, last, x, y, i, firstLabel;
42194
42195         last = ln - 1;
42196         
42197         point = inflections[0];
42198         firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0]));
42199         ratio = Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0)) >> 0;
42200         
42201         for (i = 0; i < ln; i++) {
42202             point = inflections[i];
42203             text = me.label.renderer(labels[i]);
42204             textLabel = me.getOrCreateLabel(i, text);
42205             bbox = textLabel._bbox;
42206             maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding);
42207             x = floor(point[0] - (ratio? bbox.height : bbox.width) / 2);
42208             if (me.chart.maxGutter[0] == 0) {
42209                 if (i == 0 && axes.findIndex('position', 'left') == -1) {
42210                     x = point[0];
42211                 }
42212                 else if (i == last && axes.findIndex('position', 'right') == -1) {
42213                     x = point[0] - bbox.width;
42214                 }
42215             }
42216             if (position == 'top') {
42217                 y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2);
42218             }
42219             else {
42220                 y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2);
42221             }
42222             
42223             textLabel.setAttributes({
42224                 hidden: false,
42225                 x: x,
42226                 y: y
42227             }, true);
42228
42229             
42230             if (i != 0 && (me.intersect(textLabel, prevLabel)
42231                 || me.intersect(textLabel, firstLabel))) {
42232                 textLabel.hide(true);
42233                 continue;
42234             }
42235             
42236             prevLabel = textLabel;
42237         }
42238
42239         return maxHeight;
42240     },
42241     
42242     drawVerticalLabels: function() {
42243         var me = this,
42244             inflections = me.inflections,
42245             position = me.position,
42246             ln = inflections.length,
42247             labels = me.labels,
42248             maxWidth = 0,
42249             max = Math.max,
42250             floor = Math.floor,
42251             ceil = Math.ceil,
42252             axes = me.chart.axes,
42253             gutterY = me.chart.maxGutter[1],
42254             ubbox, bbox, point, prevLabel,
42255             projectedWidth = 0,
42256             textLabel, attr, textRight, text,
42257             label, last, x, y, i;
42258
42259         last = ln;
42260         for (i = 0; i < last; i++) {
42261             point = inflections[i];
42262             text = me.label.renderer(labels[i]);
42263             textLabel = me.getOrCreateLabel(i, text);
42264             bbox = textLabel._bbox;
42265             
42266             maxWidth = max(maxWidth, bbox.width + me.dashSize + me.label.padding);
42267             y = point[1];
42268             if (gutterY < bbox.height / 2) {
42269                 if (i == last - 1 && axes.findIndex('position', 'top') == -1) {
42270                     y = me.y - me.length + ceil(bbox.height / 2);
42271                 }
42272                 else if (i == 0 && axes.findIndex('position', 'bottom') == -1) {
42273                     y = me.y - floor(bbox.height / 2);
42274                 }
42275             }
42276             if (position == 'left') {
42277                 x = point[0] - bbox.width - me.dashSize - me.label.padding - 2;
42278             }
42279             else {
42280                 x = point[0] + me.dashSize + me.label.padding + 2;
42281             }    
42282             textLabel.setAttributes(Ext.apply({
42283                 hidden: false,
42284                 x: x,
42285                 y: y
42286             }, me.label), true);
42287             
42288             if (i != 0 && me.intersect(textLabel, prevLabel)) {
42289                 textLabel.hide(true);
42290                 continue;
42291             }
42292             prevLabel = textLabel;
42293         }
42294         
42295         return maxWidth;
42296     },
42297
42298     
42299     drawLabel: function() {
42300         var me = this,
42301             position = me.position,
42302             labelGroup = me.labelGroup,
42303             inflections = me.inflections,
42304             maxWidth = 0,
42305             maxHeight = 0,
42306             ln, i;
42307
42308         if (position == 'left' || position == 'right') {
42309             maxWidth = me.drawVerticalLabels();    
42310         } else {
42311             maxHeight = me.drawHorizontalLabels();
42312         }
42313
42314         
42315         ln = labelGroup.getCount();
42316         i = inflections.length;
42317         for (; i < ln; i++) {
42318             labelGroup.getAt(i).hide(true);
42319         }
42320
42321         me.bbox = {};
42322         Ext.apply(me.bbox, me.axisBBox);
42323         me.bbox.height = maxHeight;
42324         me.bbox.width = maxWidth;
42325         if (Ext.isString(me.title)) {
42326             me.drawTitle(maxWidth, maxHeight);
42327         }
42328     },
42329
42330     
42331     elipsis: function(sprite, text, desiredWidth, minWidth, center) {
42332         var bbox,
42333             x;
42334
42335         if (desiredWidth < minWidth) {
42336             sprite.hide(true);
42337             return false;
42338         }
42339         while (text.length > 4) {
42340             text = text.substr(0, text.length - 4) + "...";
42341             sprite.setAttributes({
42342                 text: text
42343             }, true);
42344             bbox = sprite.getBBox();
42345             if (bbox.width < desiredWidth) {
42346                 if (typeof center == 'number') {
42347                     sprite.setAttributes({
42348                         x: Math.floor(center - (bbox.width / 2))
42349                     }, true);
42350                 }
42351                 break;
42352             }
42353         }
42354         return true;
42355     },
42356
42357     
42358     setTitle: function(title) {
42359         this.title = title;
42360         this.drawLabel();
42361     },
42362
42363     
42364     drawTitle: function(maxWidth, maxHeight) {
42365         var me = this,
42366             position = me.position,
42367             surface = me.chart.surface,
42368             displaySprite = me.displaySprite,
42369             title = me.title,
42370             rotate = (position == 'left' || position == 'right'),
42371             x = me.x,
42372             y = me.y,
42373             base, bbox, pad;
42374
42375         if (displaySprite) {
42376             displaySprite.setAttributes({text: title}, true);
42377         } else {
42378             base = {
42379                 type: 'text',
42380                 x: 0,
42381                 y: 0,
42382                 text: title
42383             };
42384             displaySprite = me.displaySprite = surface.add(Ext.apply(base, me.axisTitleStyle, me.labelTitle));
42385             surface.renderItem(displaySprite);
42386         }
42387         bbox = displaySprite.getBBox();
42388         pad = me.dashSize + me.label.padding;
42389
42390         if (rotate) {
42391             y -= ((me.length / 2) - (bbox.height / 2));
42392             if (position == 'left') {
42393                 x -= (maxWidth + pad + (bbox.width / 2));
42394             }
42395             else {
42396                 x += (maxWidth + pad + bbox.width - (bbox.width / 2));
42397             }
42398             me.bbox.width += bbox.width + 10;
42399         }
42400         else {
42401             x += (me.length / 2) - (bbox.width * 0.5);
42402             if (position == 'top') {
42403                 y -= (maxHeight + pad + (bbox.height * 0.3));
42404             }
42405             else {
42406                 y += (maxHeight + pad + (bbox.height * 0.8));
42407             }
42408             me.bbox.height += bbox.height + 10;
42409         }
42410         displaySprite.setAttributes({
42411             translate: {
42412                 x: x,
42413                 y: y
42414             }
42415         }, true);
42416     }
42417 });
42418
42419
42420 Ext.define('Ext.chart.axis.Category', {
42421
42422     
42423
42424     extend: 'Ext.chart.axis.Axis',
42425
42426     alternateClassName: 'Ext.chart.CategoryAxis',
42427
42428     alias: 'axis.category',
42429
42430     
42431
42432     
42433     categoryNames: null,
42434
42435     
42436     calculateCategoryCount: false,
42437
42438     
42439     setLabels: function() {
42440         var store = this.chart.store,
42441             fields = this.fields,
42442             ln = fields.length,
42443             i;
42444
42445         this.labels = [];
42446         store.each(function(record) {
42447             for (i = 0; i < ln; i++) {
42448                 this.labels.push(record.get(fields[i]));
42449             }
42450         }, this);
42451     },
42452
42453     
42454     applyData: function() {
42455         this.callParent();
42456         this.setLabels();
42457         var count = this.chart.store.getCount();
42458         return {
42459             from: 0,
42460             to: count,
42461             power: 1,
42462             step: 1,
42463             steps: count - 1
42464         };
42465     }
42466 });
42467
42468
42469 Ext.define('Ext.chart.axis.Gauge', {
42470
42471     
42472
42473     extend: 'Ext.chart.axis.Abstract',
42474
42475     
42476     
42477     
42478
42479     
42480
42481     
42482
42483     
42484
42485     position: 'gauge',
42486
42487     alias: 'axis.gauge',
42488
42489     drawAxis: function(init) {
42490         var chart = this.chart,
42491             surface = chart.surface,
42492             bbox = chart.chartBBox,
42493             centerX = bbox.x + (bbox.width / 2),
42494             centerY = bbox.y + bbox.height,
42495             margin = this.margin || 10,
42496             rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin,
42497             sprites = [], sprite,
42498             steps = this.steps,
42499             i, pi = Math.PI,
42500             cos = Math.cos,
42501             sin = Math.sin;
42502
42503         if (this.sprites && !chart.resizing) {
42504             this.drawLabel();
42505             return;
42506         }
42507
42508         if (this.margin >= 0) {
42509             if (!this.sprites) {
42510                 
42511                 for (i = 0; i <= steps; i++) {
42512                     sprite = surface.add({
42513                         type: 'path',
42514                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
42515                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
42516                                     'L', centerX + rho * cos(i / steps * pi - pi),
42517                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
42518                         stroke: '#ccc'
42519                     });
42520                     sprite.setAttributes({
42521                         hidden: false
42522                     }, true);
42523                     sprites.push(sprite);
42524                 }
42525             } else {
42526                 sprites = this.sprites;
42527                 
42528                 for (i = 0; i <= steps; i++) {
42529                     sprites[i].setAttributes({
42530                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
42531                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
42532                                'L', centerX + rho * cos(i / steps * pi - pi),
42533                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
42534                         stroke: '#ccc'
42535                     }, true);
42536                 }
42537             }
42538         }
42539         this.sprites = sprites;
42540         this.drawLabel();
42541         if (this.title) {
42542             this.drawTitle();
42543         }
42544     },
42545     
42546     drawTitle: function() {
42547         var me = this,
42548             chart = me.chart,
42549             surface = chart.surface,
42550             bbox = chart.chartBBox,
42551             labelSprite = me.titleSprite,
42552             labelBBox;
42553         
42554         if (!labelSprite) {
42555             me.titleSprite = labelSprite = surface.add({
42556                 type: 'text',
42557                 zIndex: 2
42558             });    
42559         }
42560         labelSprite.setAttributes(Ext.apply({
42561             text: me.title
42562         }, me.label || {}), true);
42563         labelBBox = labelSprite.getBBox();
42564         labelSprite.setAttributes({
42565             x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2),
42566             y: bbox.y + bbox.height - (labelBBox.height / 2) - 4
42567         }, true);
42568     },
42569
42570     
42571     setTitle: function(title) {
42572         this.title = title;
42573         this.drawTitle();
42574     },
42575
42576     drawLabel: function() {
42577         var chart = this.chart,
42578             surface = chart.surface,
42579             bbox = chart.chartBBox,
42580             centerX = bbox.x + (bbox.width / 2),
42581             centerY = bbox.y + bbox.height,
42582             margin = this.margin || 10,
42583             rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin,
42584             round = Math.round,
42585             labelArray = [], label,
42586             maxValue = this.maximum || 0,
42587             steps = this.steps, i = 0,
42588             adjY,
42589             pi = Math.PI,
42590             cos = Math.cos,
42591             sin = Math.sin,
42592             labelConf = this.label,
42593             renderer = labelConf.renderer || function(v) { return v; };
42594
42595         if (!this.labelArray) {
42596             
42597             for (i = 0; i <= steps; i++) {
42598                 
42599                 adjY = (i === 0 || i === steps) ? 7 : 0;
42600                 label = surface.add({
42601                     type: 'text',
42602                     text: renderer(round(i / steps * maxValue)),
42603                     x: centerX + rho * cos(i / steps * pi - pi),
42604                     y: centerY + rho * sin(i / steps * pi - pi) - adjY,
42605                     'text-anchor': 'middle',
42606                     'stroke-width': 0.2,
42607                     zIndex: 10,
42608                     stroke: '#333'
42609                 });
42610                 label.setAttributes({
42611                     hidden: false
42612                 }, true);
42613                 labelArray.push(label);
42614             }
42615         }
42616         else {
42617             labelArray = this.labelArray;
42618             
42619             for (i = 0; i <= steps; i++) {
42620                 
42621                 adjY = (i === 0 || i === steps) ? 7 : 0;
42622                 labelArray[i].setAttributes({
42623                     text: renderer(round(i / steps * maxValue)),
42624                     x: centerX + rho * cos(i / steps * pi - pi),
42625                     y: centerY + rho * sin(i / steps * pi - pi) - adjY
42626                 }, true);
42627             }
42628         }
42629         this.labelArray = labelArray;
42630     }
42631 });
42632
42633 Ext.define('Ext.chart.axis.Numeric', {
42634
42635     
42636
42637     extend: 'Ext.chart.axis.Axis',
42638
42639     alternateClassName: 'Ext.chart.NumericAxis',
42640
42641     
42642
42643     type: 'numeric',
42644
42645     alias: 'axis.numeric',
42646
42647     constructor: function(config) {
42648         var me = this, label, f;
42649         me.callParent([config]);
42650         label = me.label;
42651         if (me.roundToDecimal === false) {
42652             return;
42653         }
42654         if (label.renderer) {
42655             f = label.renderer;
42656             label.renderer = function(v) {
42657                 return me.roundToDecimal( f(v), me.decimals );
42658             };
42659         } else {
42660             label.renderer = function(v) {
42661                 return me.roundToDecimal(v, me.decimals);
42662             };
42663         }
42664     },
42665     
42666     roundToDecimal: function(v, dec) {
42667         var val = Math.pow(10, dec || 0);
42668         return ((v * val) >> 0) / val;
42669     },
42670     
42671     
42672     minimum: NaN,
42673
42674     
42675     maximum: NaN,
42676
42677     
42678     decimals: 2,
42679
42680     
42681     scale: "linear",
42682
42683     
42684     position: 'left',
42685
42686     
42687     adjustMaximumByMajorUnit: false,
42688
42689     
42690     adjustMinimumByMajorUnit: false,
42691
42692     
42693     applyData: function() {
42694         this.callParent();
42695         return this.calcEnds();
42696     }
42697 });
42698
42699
42700 Ext.define('Ext.chart.axis.Radial', {
42701
42702     
42703
42704     extend: 'Ext.chart.axis.Abstract',
42705
42706     
42707
42708     position: 'radial',
42709
42710     alias: 'axis.radial',
42711
42712     drawAxis: function(init) {
42713         var chart = this.chart,
42714             surface = chart.surface,
42715             bbox = chart.chartBBox,
42716             store = chart.store,
42717             l = store.getCount(),
42718             centerX = bbox.x + (bbox.width / 2),
42719             centerY = bbox.y + (bbox.height / 2),
42720             rho = Math.min(bbox.width, bbox.height) /2,
42721             sprites = [], sprite,
42722             steps = this.steps,
42723             i, j, pi2 = Math.PI * 2,
42724             cos = Math.cos, sin = Math.sin;
42725
42726         if (this.sprites && !chart.resizing) {
42727             this.drawLabel();
42728             return;
42729         }
42730
42731         if (!this.sprites) {
42732             
42733             for (i = 1; i <= steps; i++) {
42734                 sprite = surface.add({
42735                     type: 'circle',
42736                     x: centerX,
42737                     y: centerY,
42738                     radius: Math.max(rho * i / steps, 0),
42739                     stroke: '#ccc'
42740                 });
42741                 sprite.setAttributes({
42742                     hidden: false
42743                 }, true);
42744                 sprites.push(sprite);
42745             }
42746             
42747             store.each(function(rec, i) {
42748                 sprite = surface.add({
42749                     type: 'path',
42750                     path: ['M', centerX, centerY, 'L', centerX + rho * cos(i / l * pi2), centerY + rho * sin(i / l * pi2), 'Z'],
42751                     stroke: '#ccc'
42752                 });
42753                 sprite.setAttributes({
42754                     hidden: false
42755                 }, true);
42756                 sprites.push(sprite);
42757             });
42758         } else {
42759             sprites = this.sprites;
42760             
42761             for (i = 0; i < steps; i++) {
42762                 sprites[i].setAttributes({
42763                     x: centerX,
42764                     y: centerY,
42765                     radius: Math.max(rho * (i + 1) / steps, 0),
42766                     stroke: '#ccc'
42767                 }, true);
42768             }
42769             
42770             store.each(function(rec, j) {
42771                 sprites[i + j].setAttributes({
42772                     path: ['M', centerX, centerY, 'L', centerX + rho * cos(j / l * pi2), centerY + rho * sin(j / l * pi2), 'Z'],
42773                     stroke: '#ccc'
42774                 }, true);
42775             });
42776         }
42777         this.sprites = sprites;
42778
42779         this.drawLabel();
42780     },
42781
42782     drawLabel: function() {
42783         var chart = this.chart,
42784             surface = chart.surface,
42785             bbox = chart.chartBBox,
42786             store = chart.store,
42787             centerX = bbox.x + (bbox.width / 2),
42788             centerY = bbox.y + (bbox.height / 2),
42789             rho = Math.min(bbox.width, bbox.height) /2,
42790             max = Math.max, round = Math.round,
42791             labelArray = [], label,
42792             fields = [], nfields,
42793             categories = [], xField,
42794             aggregate = !this.maximum,
42795             maxValue = this.maximum || 0,
42796             steps = this.steps, i = 0, j, dx, dy,
42797             pi2 = Math.PI * 2,
42798             cos = Math.cos, sin = Math.sin,
42799             display = this.label.display,
42800             draw = display !== 'none',
42801             margin = 10;
42802
42803         if (!draw) {
42804             return;
42805         }
42806
42807         
42808         chart.series.each(function(series) {
42809             fields.push(series.yField);
42810             xField = series.xField;
42811         });
42812         
42813         
42814         store.each(function(record, i) {
42815             if (aggregate) {
42816                 for (i = 0, nfields = fields.length; i < nfields; i++) {
42817                     maxValue = max(+record.get(fields[i]), maxValue);
42818                 }
42819             }
42820             categories.push(record.get(xField));
42821         });
42822         if (!this.labelArray) {
42823             if (display != 'categories') {
42824                 
42825                 for (i = 1; i <= steps; i++) {
42826                     label = surface.add({
42827                         type: 'text',
42828                         text: round(i / steps * maxValue),
42829                         x: centerX,
42830                         y: centerY - rho * i / steps,
42831                         'text-anchor': 'middle',
42832                         'stroke-width': 0.1,
42833                         stroke: '#333'
42834                     });
42835                     label.setAttributes({
42836                         hidden: false
42837                     }, true);
42838                     labelArray.push(label);
42839                 }
42840             }
42841             if (display != 'scale') {
42842                 
42843                 for (j = 0, steps = categories.length; j < steps; j++) {
42844                     dx = cos(j / steps * pi2) * (rho + margin);
42845                     dy = sin(j / steps * pi2) * (rho + margin);
42846                     label = surface.add({
42847                         type: 'text',
42848                         text: categories[j],
42849                         x: centerX + dx,
42850                         y: centerY + dy,
42851                         'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start')
42852                     });
42853                     label.setAttributes({
42854                         hidden: false
42855                     }, true);
42856                     labelArray.push(label);
42857                 }
42858             }
42859         }
42860         else {
42861             labelArray = this.labelArray;
42862             if (display != 'categories') {
42863                 
42864                 for (i = 0; i < steps; i++) {
42865                     labelArray[i].setAttributes({
42866                         text: round((i + 1) / steps * maxValue),
42867                         x: centerX,
42868                         y: centerY - rho * (i + 1) / steps,
42869                         'text-anchor': 'middle',
42870                         'stroke-width': 0.1,
42871                         stroke: '#333'
42872                     }, true);
42873                 }
42874             }
42875             if (display != 'scale') {
42876                 
42877                 for (j = 0, steps = categories.length; j < steps; j++) {
42878                     dx = cos(j / steps * pi2) * (rho + margin);
42879                     dy = sin(j / steps * pi2) * (rho + margin);
42880                     if (labelArray[i + j]) {
42881                         labelArray[i + j].setAttributes({
42882                             type: 'text',
42883                             text: categories[j],
42884                             x: centerX + dx,
42885                             y: centerY + dy,
42886                             'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start')
42887                         }, true);
42888                     }
42889                 }
42890             }
42891         }
42892         this.labelArray = labelArray;
42893     }
42894 });
42895
42896 Ext.define('Ext.data.AbstractStore', {
42897     requires: ['Ext.util.MixedCollection', 'Ext.data.Operation', 'Ext.util.Filter'],
42898     
42899     mixins: {
42900         observable: 'Ext.util.Observable',
42901         sortable: 'Ext.util.Sortable'
42902     },
42903     
42904     statics: {
42905         create: function(store){
42906             if (!store.isStore) {
42907                 if (!store.type) {
42908                     store.type = 'store';
42909                 }
42910                 store = Ext.createByAlias('store.' + store.type, store);
42911             }
42912             return store;
42913         }    
42914     },
42915     
42916     remoteSort  : false,
42917     remoteFilter: false,
42918
42919     
42920
42921     
42922     autoLoad: false,
42923
42924     
42925     autoSync: false,
42926
42927     
42928     batchUpdateMode: 'operation',
42929
42930     
42931     filterOnLoad: true,
42932
42933     
42934     sortOnLoad: true,
42935
42936     
42937     implicitModel: false,
42938
42939     
42940     defaultProxyType: 'memory',
42941
42942     
42943     isDestroyed: false,
42944
42945     isStore: true,
42946
42947     
42948     
42949     
42950
42951     sortRoot: 'data',
42952     
42953     
42954     constructor: function(config) {
42955         var me = this;
42956         
42957         me.addEvents(
42958             
42959             'add',
42960
42961             
42962             'remove',
42963             
42964             
42965             'update',
42966
42967             
42968             'datachanged',
42969
42970             
42971             'beforeload',
42972
42973             
42974             'load',
42975
42976             
42977             'beforesync',
42978             
42979             'clear'
42980         );
42981         
42982         Ext.apply(me, config);
42983
42984         
42985         me.removed = [];
42986
42987         me.mixins.observable.constructor.apply(me, arguments);
42988         me.model = Ext.ModelManager.getModel(config.model || me.model);
42989
42990         
42991         Ext.applyIf(me, {
42992             modelDefaults: {}
42993         });
42994
42995         
42996         if (!me.model && me.fields) {
42997             me.model = Ext.define('Ext.data.Store.ImplicitModel-' + (me.storeId || Ext.id()), {
42998                 extend: 'Ext.data.Model',
42999                 fields: me.fields,
43000                 proxy: me.proxy || me.defaultProxyType
43001             });
43002
43003             delete me.fields;
43004
43005             me.implicitModel = true;
43006         }
43007
43008         
43009         me.setProxy(config.proxy || me.proxy || me.model.getProxy());
43010
43011         if (me.id && !me.storeId) {
43012             me.storeId = me.id;
43013             delete me.id;
43014         }
43015
43016         if (me.storeId) {
43017             Ext.data.StoreManager.register(me);
43018         }
43019         
43020         me.mixins.sortable.initSortable.call(me);        
43021         
43022         
43023         me.filters = Ext.create('Ext.util.MixedCollection');
43024         me.filters.addAll(me.decodeFilters(config.filters));
43025     },
43026
43027     
43028     setProxy: function(proxy) {
43029         var me = this;
43030         
43031         if (proxy instanceof Ext.data.proxy.Proxy) {
43032             proxy.setModel(me.model);
43033         } else {
43034             if (Ext.isString(proxy)) {
43035                 proxy = {
43036                     type: proxy    
43037                 };
43038             }
43039             Ext.applyIf(proxy, {
43040                 model: me.model
43041             });
43042             
43043             proxy = Ext.createByAlias('proxy.' + proxy.type, proxy);
43044         }
43045         
43046         me.proxy = proxy;
43047         
43048         return me.proxy;
43049     },
43050
43051     
43052     getProxy: function() {
43053         return this.proxy;
43054     },
43055
43056     
43057     create: function(data, options) {
43058         var me = this,
43059             instance = Ext.ModelManager.create(Ext.applyIf(data, me.modelDefaults), me.model.modelName),
43060             operation;
43061         
43062         options = options || {};
43063
43064         Ext.applyIf(options, {
43065             action : 'create',
43066             records: [instance]
43067         });
43068
43069         operation = Ext.create('Ext.data.Operation', options);
43070
43071         me.proxy.create(operation, me.onProxyWrite, me);
43072         
43073         return instance;
43074     },
43075
43076     read: function() {
43077         return this.load.apply(this, arguments);
43078     },
43079
43080     onProxyRead: Ext.emptyFn,
43081
43082     update: function(options) {
43083         var me = this,
43084             operation;
43085         options = options || {};
43086
43087         Ext.applyIf(options, {
43088             action : 'update',
43089             records: me.getUpdatedRecords()
43090         });
43091
43092         operation = Ext.create('Ext.data.Operation', options);
43093
43094         return me.proxy.update(operation, me.onProxyWrite, me);
43095     },
43096
43097     
43098     onProxyWrite: function(operation) {
43099         var me = this,
43100             success = operation.wasSuccessful(),
43101             records = operation.getRecords();
43102
43103         switch (operation.action) {
43104             case 'create':
43105                 me.onCreateRecords(records, operation, success);
43106                 break;
43107             case 'update':
43108                 me.onUpdateRecords(records, operation, success);
43109                 break;
43110             case 'destroy':
43111                 me.onDestroyRecords(records, operation, success);
43112                 break;
43113         }
43114
43115         if (success) {
43116             me.fireEvent('write', me, operation);
43117             me.fireEvent('datachanged', me);
43118         }
43119         
43120         Ext.callback(operation.callback, operation.scope || me, [records, operation, success]);
43121     },
43122
43123
43124     
43125     destroy: function(options) {
43126         var me = this,
43127             operation;
43128             
43129         options = options || {};
43130
43131         Ext.applyIf(options, {
43132             action : 'destroy',
43133             records: me.getRemovedRecords()
43134         });
43135
43136         operation = Ext.create('Ext.data.Operation', options);
43137
43138         return me.proxy.destroy(operation, me.onProxyWrite, me);
43139     },
43140
43141     
43142     onBatchOperationComplete: function(batch, operation) {
43143         return this.onProxyWrite(operation);
43144     },
43145
43146     
43147     onBatchComplete: function(batch, operation) {
43148         var me = this,
43149             operations = batch.operations,
43150             length = operations.length,
43151             i;
43152
43153         me.suspendEvents();
43154
43155         for (i = 0; i < length; i++) {
43156             me.onProxyWrite(operations[i]);
43157         }
43158
43159         me.resumeEvents();
43160
43161         me.fireEvent('datachanged', me);
43162     },
43163
43164     onBatchException: function(batch, operation) {
43165         
43166         
43167         
43168         
43169         
43170     },
43171
43172     
43173     filterNew: function(item) {
43174         
43175         return item.phantom === true && item.isValid();
43176     },
43177
43178     
43179     getNewRecords: function() {
43180         return [];
43181     },
43182
43183     
43184     getUpdatedRecords: function() {
43185         return [];
43186     },
43187
43188     
43189     filterUpdated: function(item) {
43190         
43191         return item.dirty === true && item.phantom !== true && item.isValid();
43192     },
43193
43194     
43195     getRemovedRecords: function() {
43196         return this.removed;
43197     },
43198
43199     filter: function(filters, value) {
43200
43201     },
43202
43203     
43204     decodeFilters: function(filters) {
43205         if (!Ext.isArray(filters)) {
43206             if (filters === undefined) {
43207                 filters = [];
43208             } else {
43209                 filters = [filters];
43210             }
43211         }
43212
43213         var length = filters.length,
43214             Filter = Ext.util.Filter,
43215             config, i;
43216
43217         for (i = 0; i < length; i++) {
43218             config = filters[i];
43219
43220             if (!(config instanceof Filter)) {
43221                 Ext.apply(config, {
43222                     root: 'data'
43223                 });
43224
43225                 
43226                 if (config.fn) {
43227                     config.filterFn = config.fn;
43228                 }
43229
43230                 
43231                 if (typeof config == 'function') {
43232                     config = {
43233                         filterFn: config
43234                     };
43235                 }
43236
43237                 filters[i] = new Filter(config);
43238             }
43239         }
43240
43241         return filters;
43242     },
43243
43244     clearFilter: function(supressEvent) {
43245
43246     },
43247
43248     isFiltered: function() {
43249
43250     },
43251
43252     filterBy: function(fn, scope) {
43253
43254     },
43255     
43256     
43257     sync: function() {
43258         var me        = this,
43259             options   = {},
43260             toCreate  = me.getNewRecords(),
43261             toUpdate  = me.getUpdatedRecords(),
43262             toDestroy = me.getRemovedRecords(),
43263             needsSync = false;
43264
43265         if (toCreate.length > 0) {
43266             options.create = toCreate;
43267             needsSync = true;
43268         }
43269
43270         if (toUpdate.length > 0) {
43271             options.update = toUpdate;
43272             needsSync = true;
43273         }
43274
43275         if (toDestroy.length > 0) {
43276             options.destroy = toDestroy;
43277             needsSync = true;
43278         }
43279
43280         if (needsSync && me.fireEvent('beforesync', options) !== false) {
43281             me.proxy.batch(options, me.getBatchListeners());
43282         }
43283     },
43284
43285
43286     
43287     getBatchListeners: function() {
43288         var me = this,
43289             listeners = {
43290                 scope: me,
43291                 exception: me.onBatchException
43292             };
43293
43294         if (me.batchUpdateMode == 'operation') {
43295             listeners.operationcomplete = me.onBatchOperationComplete;
43296         } else {
43297             listeners.complete = me.onBatchComplete;
43298         }
43299
43300         return listeners;
43301     },
43302
43303     
43304     save: function() {
43305         return this.sync.apply(this, arguments);
43306     },
43307
43308     
43309     load: function(options) {
43310         var me = this,
43311             operation;
43312
43313         options = options || {};
43314
43315         Ext.applyIf(options, {
43316             action : 'read',
43317             filters: me.filters.items,
43318             sorters: me.getSorters()
43319         });
43320         
43321         operation = Ext.create('Ext.data.Operation', options);
43322
43323         if (me.fireEvent('beforeload', me, operation) !== false) {
43324             me.loading = true;
43325             me.proxy.read(operation, me.onProxyLoad, me);
43326         }
43327         
43328         return me;
43329     },
43330
43331     
43332     afterEdit : function(record) {
43333         var me = this;
43334         
43335         if (me.autoSync) {
43336             me.sync();
43337         }
43338         
43339         me.fireEvent('update', me, record, Ext.data.Model.EDIT);
43340     },
43341
43342     
43343     afterReject : function(record) {
43344         this.fireEvent('update', this, record, Ext.data.Model.REJECT);
43345     },
43346
43347     
43348     afterCommit : function(record) {
43349         this.fireEvent('update', this, record, Ext.data.Model.COMMIT);
43350     },
43351
43352     clearData: Ext.emptyFn,
43353
43354     destroyStore: function() {
43355         var me = this;
43356         
43357         if (!me.isDestroyed) {
43358             if (me.storeId) {
43359                 Ext.data.StoreManager.unregister(me);
43360             }
43361             me.clearData();
43362             me.data = null;
43363             me.tree = null;
43364             
43365             me.reader = me.writer = null;
43366             me.clearListeners();
43367             me.isDestroyed = true;
43368
43369             if (me.implicitModel) {
43370                 Ext.destroy(me.model);
43371             }
43372         }
43373     },
43374     
43375     doSort: function(sorterFn) {
43376         var me = this;
43377         if (me.remoteSort) {
43378             
43379             me.load();
43380         } else {
43381             me.data.sortBy(sorterFn);
43382             me.fireEvent('datachanged', me);
43383         }
43384     },
43385
43386     getCount: Ext.emptyFn,
43387
43388     getById: Ext.emptyFn,
43389     
43390     
43391     removeAll: Ext.emptyFn,
43392     
43393     
43394
43395     
43396     isLoading: function() {
43397         return this.loading;
43398      }
43399 });
43400
43401
43402  
43403 Ext.define('Ext.util.Grouper', {
43404
43405     
43406
43407     extend: 'Ext.util.Sorter',
43408
43409     
43410
43411     
43412     getGroupString: function(instance) {
43413         return instance.get(this.property);
43414     }
43415 });
43416
43417 Ext.define('Ext.data.Store', {
43418     extend: 'Ext.data.AbstractStore',
43419
43420     alias: 'store.store',
43421
43422     requires: ['Ext.ModelManager', 'Ext.data.Model', 'Ext.util.Grouper'],
43423     uses: ['Ext.data.proxy.Memory'],
43424
43425     
43426     remoteSort: false,
43427
43428     
43429     remoteFilter: false,
43430     
43431     
43432     remoteGroup : false,
43433
43434     
43435
43436     
43437
43438     
43439
43440     
43441     groupField: undefined,
43442
43443     
43444     groupDir: "ASC",
43445
43446     
43447     pageSize: 25,
43448
43449     
43450     currentPage: 1,
43451
43452     
43453     clearOnPageLoad: true,
43454
43455     
43456     loading: false,
43457
43458     
43459     sortOnFilter: true,
43460     
43461     
43462     buffered: false,
43463     
43464     
43465     purgePageCount: 5,
43466
43467     isStore: true,
43468
43469     
43470     constructor: function(config) {
43471         config = config || {};
43472
43473         var me = this,
43474             groupers = config.groupers,
43475             proxy,
43476             data;
43477             
43478         if (config.buffered || me.buffered) {
43479             me.prefetchData = Ext.create('Ext.util.MixedCollection', false, function(record) {
43480                 return record.index;
43481             });
43482             me.pendingRequests = [];
43483             me.pagesRequested = [];
43484             
43485             me.sortOnLoad = false;
43486             me.filterOnLoad = false;
43487         }
43488             
43489         me.addEvents(
43490             
43491             'beforeprefetch',
43492             
43493             'groupchange',
43494             
43495             'prefetch'
43496         );
43497         data = config.data || me.data;
43498
43499         
43500         me.data = Ext.create('Ext.util.MixedCollection', false, function(record) {
43501             return record.internalId;
43502         });
43503
43504         if (data) {
43505             me.inlineData = data;
43506             delete config.data;
43507         }
43508         
43509         if (!groupers && config.groupField) {
43510             groupers = [{
43511                 property : config.groupField,
43512                 direction: config.groupDir
43513             }];
43514         }
43515         delete config.groupers;
43516         
43517         
43518         me.groupers = Ext.create('Ext.util.MixedCollection');
43519         me.groupers.addAll(me.decodeGroupers(groupers));
43520
43521         this.callParent([config]);
43522         
43523         if (me.groupers.items.length) {
43524             me.sort(me.groupers.items, 'prepend', false);
43525         }
43526
43527         proxy = me.proxy;
43528         data = me.inlineData;
43529
43530         if (data) {
43531             if (proxy instanceof Ext.data.proxy.Memory) {
43532                 proxy.data = data;
43533                 me.read();
43534             } else {
43535                 me.add.apply(me, data);
43536             }
43537
43538             me.sort();
43539             delete me.inlineData;
43540         } else if (me.autoLoad) {
43541             Ext.defer(me.load, 10, me, [typeof me.autoLoad === 'object' ? me.autoLoad: undefined]);
43542             
43543             
43544         }
43545     },
43546     
43547     onBeforeSort: function() {
43548         this.sort(this.groupers.items, 'prepend', false);
43549     },
43550     
43551     
43552     decodeGroupers: function(groupers) {
43553         if (!Ext.isArray(groupers)) {
43554             if (groupers === undefined) {
43555                 groupers = [];
43556             } else {
43557                 groupers = [groupers];
43558             }
43559         }
43560
43561         var length  = groupers.length,
43562             Grouper = Ext.util.Grouper,
43563             config, i;
43564
43565         for (i = 0; i < length; i++) {
43566             config = groupers[i];
43567
43568             if (!(config instanceof Grouper)) {
43569                 if (Ext.isString(config)) {
43570                     config = {
43571                         property: config
43572                     };
43573                 }
43574                 
43575                 Ext.applyIf(config, {
43576                     root     : 'data',
43577                     direction: "ASC"
43578                 });
43579
43580                 
43581                 if (config.fn) {
43582                     config.sorterFn = config.fn;
43583                 }
43584
43585                 
43586                 if (typeof config == 'function') {
43587                     config = {
43588                         sorterFn: config
43589                     };
43590                 }
43591
43592                 groupers[i] = new Grouper(config);
43593             }
43594         }
43595
43596         return groupers;
43597     },
43598     
43599     
43600     group: function(groupers, direction) {
43601         var me = this,
43602             grouper,
43603             newGroupers;
43604             
43605         if (Ext.isArray(groupers)) {
43606             newGroupers = groupers;
43607         } else if (Ext.isObject(groupers)) {
43608             newGroupers = [groupers];
43609         } else if (Ext.isString(groupers)) {
43610             grouper = me.groupers.get(groupers);
43611
43612             if (!grouper) {
43613                 grouper = {
43614                     property : groupers,
43615                     direction: direction
43616                 };
43617                 newGroupers = [grouper];
43618             } else if (direction === undefined) {
43619                 grouper.toggle();
43620             } else {
43621                 grouper.setDirection(direction);
43622             }
43623         }
43624         
43625         if (newGroupers && newGroupers.length) {
43626             newGroupers = me.decodeGroupers(newGroupers);
43627             me.groupers.clear();
43628             me.groupers.addAll(newGroupers);
43629         }
43630         
43631         if (me.remoteGroup) {
43632             me.load({
43633                 scope: me,
43634                 callback: me.fireGroupChange
43635             });
43636         } else {
43637             me.sort();
43638             me.fireEvent('groupchange', me, me.groupers);
43639         }
43640     },
43641     
43642     
43643     clearGrouping: function(){
43644         var me = this;
43645         
43646         me.groupers.each(function(grouper){
43647             me.sorters.remove(grouper);
43648         });
43649         me.groupers.clear();
43650         if (me.remoteGroup) {
43651             me.load({
43652                 scope: me,
43653                 callback: me.fireGroupChange
43654             });
43655         } else {
43656             me.sort();
43657             me.fireEvent('groupchange', me, me.groupers);
43658         }
43659     },
43660     
43661     
43662     isGrouped: function() {
43663         return this.groupers.getCount() > 0;    
43664     },
43665     
43666     
43667     fireGroupChange: function(){
43668         this.fireEvent('groupchange', this, this.groupers);    
43669     },
43670
43671     
43672     getGroups: function(requestGroupString) {
43673         var records = this.data.items,
43674             length = records.length,
43675             groups = [],
43676             pointers = {},
43677             record,
43678             groupStr,
43679             group,
43680             i;
43681
43682         for (i = 0; i < length; i++) {
43683             record = records[i];
43684             groupStr = this.getGroupString(record);
43685             group = pointers[groupStr];
43686
43687             if (group === undefined) {
43688                 group = {
43689                     name: groupStr,
43690                     children: []
43691                 };
43692
43693                 groups.push(group);
43694                 pointers[groupStr] = group;
43695             }
43696
43697             group.children.push(record);
43698         }
43699
43700         return requestGroupString ? pointers[requestGroupString] : groups;
43701     },
43702
43703     
43704     getGroupsForGrouper: function(records, grouper) {
43705         var length = records.length,
43706             groups = [],
43707             oldValue,
43708             newValue,
43709             record,
43710             group,
43711             i;
43712
43713         for (i = 0; i < length; i++) {
43714             record = records[i];
43715             newValue = grouper.getGroupString(record);
43716
43717             if (newValue !== oldValue) {
43718                 group = {
43719                     name: newValue,
43720                     grouper: grouper,
43721                     records: []
43722                 };
43723                 groups.push(group);
43724             }
43725
43726             group.records.push(record);
43727
43728             oldValue = newValue;
43729         }
43730
43731         return groups;
43732     },
43733
43734     
43735     getGroupsForGrouperIndex: function(records, grouperIndex) {
43736         var me = this,
43737             groupers = me.groupers,
43738             grouper = groupers.getAt(grouperIndex),
43739             groups = me.getGroupsForGrouper(records, grouper),
43740             length = groups.length,
43741             i;
43742
43743         if (grouperIndex + 1 < groupers.length) {
43744             for (i = 0; i < length; i++) {
43745                 groups[i].children = me.getGroupsForGrouperIndex(groups[i].records, grouperIndex + 1);
43746             }
43747         }
43748
43749         for (i = 0; i < length; i++) {
43750             groups[i].depth = grouperIndex;
43751         }
43752
43753         return groups;
43754     },
43755
43756     
43757     getGroupData: function(sort) {
43758         var me = this;
43759         if (sort !== false) {
43760             me.sort();
43761         }
43762
43763         return me.getGroupsForGrouperIndex(me.data.items, 0);
43764     },
43765
43766     
43767     getGroupString: function(instance) {
43768         var group = this.groupers.first();
43769         if (group) {
43770             return instance.get(group.property);
43771         }
43772         return '';
43773     },
43774     
43775     insert: function(index, records) {
43776         var me = this,
43777             sync = false,
43778             i,
43779             record,
43780             len;
43781
43782         records = [].concat(records);
43783         for (i = 0, len = records.length; i < len; i++) {
43784             record = me.createModel(records[i]);
43785             record.set(me.modelDefaults);
43786             
43787             records[i] = record;
43788             
43789             me.data.insert(index + i, record);
43790             record.join(me);
43791
43792             sync = sync || record.phantom === true;
43793         }
43794
43795         if (me.snapshot) {
43796             me.snapshot.addAll(records);
43797         }
43798
43799         me.fireEvent('add', me, records, index);
43800         me.fireEvent('datachanged', me);
43801         if (me.autoSync && sync) {
43802             me.sync();
43803         }
43804     },
43805
43806     
43807     add: function(records) {
43808         
43809         if (!Ext.isArray(records)) {
43810             records = Array.prototype.slice.apply(arguments);
43811         }
43812
43813         var me = this,
43814             i = 0,
43815             length = records.length,
43816             record;
43817
43818         for (; i < length; i++) {
43819             record = me.createModel(records[i]);
43820             
43821             records[i] = record;
43822         }
43823
43824         me.insert(me.data.length, records);
43825
43826         return records;
43827     },
43828
43829     
43830     createModel: function(record) {
43831         if (!record.isModel) {
43832             record = Ext.ModelManager.create(record, this.model);
43833         }
43834
43835         return record;
43836     },
43837
43838     
43839     each: function(fn, scope) {
43840         this.data.each(fn, scope);
43841     },
43842
43843     
43844     remove: function(records,  isMove) {
43845         if (!Ext.isArray(records)) {
43846             records = [records];
43847         }
43848
43849         
43850         isMove = isMove === true;
43851         var me = this,
43852             sync = false,
43853             i = 0,
43854             length = records.length,
43855             isPhantom,
43856             index,
43857             record;
43858
43859         for (; i < length; i++) {
43860             record = records[i];
43861             index = me.data.indexOf(record);
43862             
43863             if (me.snapshot) {
43864                 me.snapshot.remove(record);
43865             }
43866             
43867             if (index > -1) {
43868                 isPhantom = record.phantom === true;
43869                 if (!isMove && !isPhantom) {
43870                     
43871                     me.removed.push(record);
43872                 }
43873
43874                 record.unjoin(me);
43875                 me.data.remove(record);
43876                 sync = sync || !isPhantom;
43877
43878                 me.fireEvent('remove', me, record, index);
43879             }
43880         }
43881
43882         me.fireEvent('datachanged', me);
43883         if (!isMove && me.autoSync && sync) {
43884             me.sync();
43885         }
43886     },
43887
43888     
43889     removeAt: function(index) {
43890         var record = this.getAt(index);
43891
43892         if (record) {
43893             this.remove(record);
43894         }
43895     },
43896
43897     
43898     load: function(options) {
43899         var me = this;
43900             
43901         options = options || {};
43902
43903         if (Ext.isFunction(options)) {
43904             options = {
43905                 callback: options
43906             };
43907         }
43908
43909         Ext.applyIf(options, {
43910             groupers: me.groupers.items,
43911             page: me.currentPage,
43912             start: (me.currentPage - 1) * me.pageSize,
43913             limit: me.pageSize,
43914             addRecords: false
43915         });      
43916
43917         return me.callParent([options]);
43918     },
43919
43920     
43921     onProxyLoad: function(operation) {
43922         var me = this,
43923             resultSet = operation.getResultSet(),
43924             records = operation.getRecords(),
43925             successful = operation.wasSuccessful();
43926
43927         if (resultSet) {
43928             me.totalCount = resultSet.total;
43929         }
43930
43931         if (successful) {
43932             me.loadRecords(records, operation);
43933         }
43934
43935         me.loading = false;
43936         me.fireEvent('load', me, records, successful);
43937
43938         
43939         
43940         me.fireEvent('read', me, records, operation.wasSuccessful());
43941
43942         
43943         Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
43944     },
43945     
43946     
43947     onCreateRecords: function(records, operation, success) {
43948         if (success) {
43949             var i = 0,
43950                 data = this.data,
43951                 snapshot = this.snapshot,
43952                 length = records.length,
43953                 originalRecords = operation.records,
43954                 record,
43955                 original,
43956                 index;
43957
43958             
43959             for (; i < length; ++i) {
43960                 record = records[i];
43961                 original = originalRecords[i];
43962                 if (original) {
43963                     index = data.indexOf(original);
43964                     if (index > -1) {
43965                         data.removeAt(index);
43966                         data.insert(index, record);
43967                     }
43968                     if (snapshot) {
43969                         index = snapshot.indexOf(original);
43970                         if (index > -1) {
43971                             snapshot.removeAt(index);
43972                             snapshot.insert(index, record);
43973                         }
43974                     }
43975                     record.phantom = false;
43976                     record.join(this);
43977                 }
43978             }
43979         }
43980     },
43981
43982     
43983     onUpdateRecords: function(records, operation, success){
43984         if (success) {
43985             var i = 0,
43986                 length = records.length,
43987                 data = this.data,
43988                 snapshot = this.snapshot,
43989                 record;
43990
43991             for (; i < length; ++i) {
43992                 record = records[i];
43993                 data.replace(record);
43994                 if (snapshot) {
43995                     snapshot.replace(record);
43996                 }
43997                 record.join(this);
43998             }
43999         }
44000     },
44001
44002     
44003     onDestroyRecords: function(records, operation, success){
44004         if (success) {
44005             var me = this,
44006                 i = 0,
44007                 length = records.length,
44008                 data = me.data,
44009                 snapshot = me.snapshot,
44010                 record;
44011
44012             for (; i < length; ++i) {
44013                 record = records[i];
44014                 record.unjoin(me);
44015                 data.remove(record);
44016                 if (snapshot) {
44017                     snapshot.remove(record);
44018                 }
44019             }
44020             me.removed = [];
44021         }
44022     },
44023
44024     
44025     getNewRecords: function() {
44026         return this.data.filterBy(this.filterNew).items;
44027     },
44028
44029     
44030     getUpdatedRecords: function() {
44031         return this.data.filterBy(this.filterUpdated).items;
44032     },
44033
44034     
44035     filter: function(filters, value) {
44036         if (Ext.isString(filters)) {
44037             filters = {
44038                 property: filters,
44039                 value: value
44040             };
44041         }
44042
44043         var me = this,
44044             decoded = me.decodeFilters(filters),
44045             i = 0,
44046             doLocalSort = me.sortOnFilter && !me.remoteSort,
44047             length = decoded.length;
44048
44049         for (; i < length; i++) {
44050             me.filters.replace(decoded[i]);
44051         }
44052
44053         if (me.remoteFilter) {
44054             
44055             me.load();
44056         } else {
44057             
44058             if (me.filters.getCount()) {
44059                 me.snapshot = me.snapshot || me.data.clone();
44060                 me.data = me.data.filter(me.filters.items);
44061
44062                 if (doLocalSort) {
44063                     me.sort();
44064                 }
44065                 
44066                 if (!doLocalSort || me.sorters.length < 1) {
44067                     me.fireEvent('datachanged', me);
44068                 }
44069             }
44070         }
44071     },
44072
44073     
44074     clearFilter: function(suppressEvent) {
44075         var me = this;
44076
44077         me.filters.clear();
44078
44079         if (me.remoteFilter) {
44080             me.load();
44081         } else if (me.isFiltered()) {
44082             me.data = me.snapshot.clone();
44083             delete me.snapshot;
44084
44085             if (suppressEvent !== true) {
44086                 me.fireEvent('datachanged', me);
44087             }
44088         }
44089     },
44090
44091     
44092     isFiltered: function() {
44093         var snapshot = this.snapshot;
44094         return !! snapshot && snapshot !== this.data;
44095     },
44096
44097     
44098     filterBy: function(fn, scope) {
44099         var me = this;
44100
44101         me.snapshot = me.snapshot || me.data.clone();
44102         me.data = me.queryBy(fn, scope || me);
44103         me.fireEvent('datachanged', me);
44104     },
44105
44106     
44107     queryBy: function(fn, scope) {
44108         var me = this,
44109         data = me.snapshot || me.data;
44110         return data.filterBy(fn, scope || me);
44111     },
44112
44113     
44114     loadData: function(data, append) {
44115         var model = this.model,
44116             length = data.length,
44117             i,
44118             record;
44119
44120         
44121         for (i = 0; i < length; i++) {
44122             record = data[i];
44123
44124             if (! (record instanceof Ext.data.Model)) {
44125                 data[i] = Ext.ModelManager.create(record, model);
44126             }
44127         }
44128
44129         this.loadRecords(data, {addRecords: append});
44130     },
44131
44132     
44133     loadRecords: function(records, options) {
44134         var me     = this,
44135             i      = 0,
44136             length = records.length;
44137
44138         options = options || {};
44139
44140
44141         if (!options.addRecords) {
44142             delete me.snapshot;
44143             me.data.clear();
44144         }
44145
44146         me.data.addAll(records);
44147
44148         
44149         for (; i < length; i++) {
44150             if (options.start !== undefined) {
44151                 records[i].index = options.start + i;
44152
44153             }
44154             records[i].join(me);
44155         }
44156
44157         
44158         me.suspendEvents();
44159
44160         if (me.filterOnLoad && !me.remoteFilter) {
44161             me.filter();
44162         }
44163
44164         if (me.sortOnLoad && !me.remoteSort) {
44165             me.sort();
44166         }
44167
44168         me.resumeEvents();
44169         me.fireEvent('datachanged', me, records);
44170     },
44171
44172     
44173     
44174     loadPage: function(page) {
44175         var me = this;
44176
44177         me.currentPage = page;
44178
44179         me.read({
44180             page: page,
44181             start: (page - 1) * me.pageSize,
44182             limit: me.pageSize,
44183             addRecords: !me.clearOnPageLoad
44184         });
44185     },
44186
44187     
44188     nextPage: function() {
44189         this.loadPage(this.currentPage + 1);
44190     },
44191
44192     
44193     previousPage: function() {
44194         this.loadPage(this.currentPage - 1);
44195     },
44196
44197     
44198     clearData: function() {
44199         this.data.each(function(record) {
44200             record.unjoin();
44201         });
44202
44203         this.data.clear();
44204     },
44205     
44206     
44207     
44208     prefetch: function(options) {
44209         var me = this,
44210             operation,
44211             requestId = me.getRequestId();
44212
44213         options = options || {};
44214
44215         Ext.applyIf(options, {
44216             action : 'read',
44217             filters: me.filters.items,
44218             sorters: me.sorters.items,
44219             requestId: requestId
44220         });
44221         me.pendingRequests.push(requestId);
44222
44223         operation = Ext.create('Ext.data.Operation', options);
44224
44225         
44226         
44227         
44228         
44229         if (me.fireEvent('beforeprefetch', me, operation) !== false) {
44230             me.loading = true;
44231             me.proxy.read(operation, me.onProxyPrefetch, me);
44232         }
44233         
44234         return me;
44235     },
44236     
44237     
44238     prefetchPage: function(page, options) {
44239         var me = this,
44240             pageSize = me.pageSize,
44241             start = (page - 1) * me.pageSize,
44242             end = start + pageSize;
44243         
44244         
44245         if (Ext.Array.indexOf(me.pagesRequested, page) === -1 && !me.rangeSatisfied(start, end)) {
44246             options = options || {};
44247             me.pagesRequested.push(page);
44248             Ext.applyIf(options, {
44249                 page : page,
44250                 start: start,
44251                 limit: pageSize,
44252                 callback: me.onWaitForGuarantee,
44253                 scope: me
44254             });
44255             
44256             me.prefetch(options);
44257         }
44258         
44259     },
44260     
44261     
44262     getRequestId: function() {
44263         this.requestSeed = this.requestSeed || 1;
44264         return this.requestSeed++;
44265     },
44266     
44267     
44268     onProxyPrefetch: function(operation) {
44269         var me         = this,
44270             resultSet  = operation.getResultSet(),
44271             records    = operation.getRecords(),
44272             
44273             successful = operation.wasSuccessful();
44274         
44275         if (resultSet) {
44276             me.totalCount = resultSet.total;
44277             me.fireEvent('totalcountchange', me.totalCount);
44278         }
44279         
44280         if (successful) {
44281             me.cacheRecords(records, operation);
44282         }
44283         Ext.Array.remove(me.pendingRequests, operation.requestId);
44284         if (operation.page) {
44285             Ext.Array.remove(me.pagesRequested, operation.page);
44286         }
44287         
44288         me.loading = false;
44289         me.fireEvent('prefetch', me, records, successful, operation);
44290         
44291         
44292         if (operation.blocking) {
44293             me.fireEvent('load', me, records, successful);
44294         }
44295
44296         
44297         Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
44298     },
44299     
44300     
44301     cacheRecords: function(records, operation) {
44302         var me     = this,
44303             i      = 0,
44304             length = records.length,
44305             start  = operation ? operation.start : 0;
44306         
44307         if (!Ext.isDefined(me.totalCount)) {
44308             me.totalCount = records.length;
44309             me.fireEvent('totalcountchange', me.totalCount);
44310         }
44311         
44312         for (; i < length; i++) {
44313             
44314             records[i].index = start + i;
44315         }
44316         
44317         me.prefetchData.addAll(records);
44318         if (me.purgePageCount) {
44319             me.purgeRecords();
44320         }
44321         
44322     },
44323     
44324     
44325     
44326     purgeRecords: function() {
44327         var me = this,
44328             prefetchCount = me.prefetchData.getCount(),
44329             purgeCount = me.purgePageCount * me.pageSize,
44330             numRecordsToPurge = prefetchCount - purgeCount - 1,
44331             i = 0;
44332
44333         for (; i <= numRecordsToPurge; i++) {
44334             me.prefetchData.removeAt(0);
44335         }
44336     },
44337     
44338     
44339     rangeSatisfied: function(start, end) {
44340         var me = this,
44341             i = start,
44342             satisfied = true;
44343
44344         for (; i < end; i++) {
44345             if (!me.prefetchData.getByKey(i)) {
44346                 satisfied = false;
44347                 if (end - i > me.pageSize) {
44348                     Ext.Error.raise("A single page prefetch could never satisfy this request.");
44349                 }
44350                 break;
44351             }
44352         }
44353         return satisfied;
44354     },
44355     
44356     
44357     getPageFromRecordIndex: function(index) {
44358         return Math.floor(index / this.pageSize) + 1;
44359     },
44360     
44361     
44362     onGuaranteedRange: function() {
44363         var me = this,
44364             totalCount = me.getTotalCount(),
44365             start = me.requestStart,
44366             end = ((totalCount - 1) < me.requestEnd) ? totalCount - 1 : me.requestEnd,
44367             range = [],
44368             record,
44369             i = start;
44370             
44371         if (start > end) {
44372             Ext.Error.raise("Start (" + start + ") was greater than end (" + end + ")");
44373         }
44374         
44375         if (start !== me.guaranteedStart && end !== me.guaranteedEnd) {
44376             me.guaranteedStart = start;
44377             me.guaranteedEnd = end;
44378             
44379             for (; i <= end; i++) {
44380                 record = me.prefetchData.getByKey(i);
44381                 if (!record) {
44382                     Ext.Error.raise("Record was not found and store said it was guaranteed");
44383                 }
44384                 range.push(record);
44385             }
44386             me.fireEvent('guaranteedrange', range, start, end);
44387             if (me.cb) {
44388                 me.cb.call(me.scope || me, range);
44389             }
44390         }
44391         
44392         me.unmask();
44393     },
44394     
44395     
44396     mask: function() {
44397         this.masked = true;
44398         this.fireEvent('beforeload');
44399     },
44400     
44401     
44402     unmask: function() {
44403         if (this.masked) {
44404             this.fireEvent('load');
44405         }
44406     },
44407     
44408     
44409     hasPendingRequests: function() {
44410         return this.pendingRequests.length;
44411     },
44412     
44413     
44414     
44415     onWaitForGuarantee: function() {
44416         if (!this.hasPendingRequests()) {
44417             this.onGuaranteedRange();
44418         }
44419     },
44420     
44421     
44422     guaranteeRange: function(start, end, cb, scope) {
44423         if (start && end) {
44424             if (end - start > this.pageSize) {
44425                 Ext.Error.raise({
44426                     start: start,
44427                     end: end,
44428                     pageSize: this.pageSize,
44429                     msg: "Requested a bigger range than the specified pageSize"
44430                 });
44431             }
44432         }
44433         
44434         end = (end > this.totalCount) ? this.totalCount - 1 : end;
44435         
44436         var me = this,
44437             i = start,
44438             prefetchData = me.prefetchData,
44439             range = [],
44440             startLoaded = !!prefetchData.getByKey(start),
44441             endLoaded = !!prefetchData.getByKey(end),
44442             startPage = me.getPageFromRecordIndex(start),
44443             endPage = me.getPageFromRecordIndex(end);
44444             
44445         me.cb = cb;
44446         me.scope = scope;
44447
44448         me.requestStart = start;
44449         me.requestEnd = end;
44450         
44451         if (!startLoaded || !endLoaded) {
44452             
44453             if (startPage === endPage) {
44454                 me.mask();
44455                 me.prefetchPage(startPage, {
44456                     
44457                     callback: me.onWaitForGuarantee,
44458                     scope: me
44459                 });
44460             
44461             } else {
44462                 me.mask();
44463                 me.prefetchPage(startPage, {
44464                     
44465                     callback: me.onWaitForGuarantee,
44466                     scope: me
44467                 });
44468                 me.prefetchPage(endPage, {
44469                     
44470                     callback: me.onWaitForGuarantee,
44471                     scope: me
44472                 });
44473             }
44474         
44475         } else {
44476             me.onGuaranteedRange();
44477         }
44478     },
44479     
44480     
44481     
44482     sort: function() {
44483         var me = this,
44484             prefetchData = me.prefetchData,
44485             sorters,
44486             start,
44487             end,
44488             range;
44489             
44490         if (me.buffered) {
44491             if (me.remoteSort) {
44492                 prefetchData.clear();
44493                 me.callParent(arguments);
44494             } else {
44495                 sorters = me.getSorters();
44496                 start = me.guaranteedStart;
44497                 end = me.guaranteedEnd;
44498                 range;
44499                 
44500                 if (sorters.length) {
44501                     prefetchData.sort(sorters);
44502                     range = prefetchData.getRange();
44503                     prefetchData.clear();
44504                     me.cacheRecords(range);
44505                     delete me.guaranteedStart;
44506                     delete me.guaranteedEnd;
44507                     me.guaranteeRange(start, end);
44508                 }
44509                 me.callParent(arguments);
44510             }
44511         } else {
44512             me.callParent(arguments);
44513         }
44514     },
44515
44516     
44517     
44518     
44519     doSort: function(sorterFn) {
44520         var me = this;
44521         if (me.remoteSort) {
44522             
44523             me.load();
44524         } else {
44525             me.data.sortBy(sorterFn);
44526             if (!me.buffered) {
44527                 var range = me.getRange(),
44528                     ln = range.length,
44529                     i  = 0;
44530                 for (; i < ln; i++) {
44531                     range[i].index = i;
44532                 }
44533             }
44534             me.fireEvent('datachanged', me);
44535         }
44536     },
44537     
44538     
44539     find: function(property, value, start, anyMatch, caseSensitive, exactMatch) {
44540         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
44541         return fn ? this.data.findIndexBy(fn, null, start) : -1;
44542     },
44543
44544     
44545     findRecord: function() {
44546         var me = this,
44547             index = me.find.apply(me, arguments);
44548         return index !== -1 ? me.getAt(index) : null;
44549     },
44550
44551     
44552     createFilterFn: function(property, value, anyMatch, caseSensitive, exactMatch) {
44553         if (Ext.isEmpty(value)) {
44554             return false;
44555         }
44556         value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
44557         return function(r) {
44558             return value.test(r.data[property]);
44559         };
44560     },
44561
44562     
44563     findExact: function(property, value, start) {
44564         return this.data.findIndexBy(function(rec) {
44565             return rec.get(property) === value;
44566         },
44567         this, start);
44568     },
44569
44570     
44571     findBy: function(fn, scope, start) {
44572         return this.data.findIndexBy(fn, scope, start);
44573     },
44574
44575     
44576     collect: function(dataIndex, allowNull, bypassFilter) {
44577         var me = this,
44578             data = (bypassFilter === true && me.snapshot) ? me.snapshot: me.data;
44579
44580         return data.collect(dataIndex, 'data', allowNull);
44581     },
44582
44583     
44584     getCount: function() {
44585         return this.data.length || 0;
44586     },
44587
44588     
44589     getTotalCount: function() {
44590         return this.totalCount;
44591     },
44592
44593     
44594     getAt: function(index) {
44595         return this.data.getAt(index);
44596     },
44597
44598     
44599     getRange: function(start, end) {
44600         return this.data.getRange(start, end);
44601     },
44602
44603     
44604     getById: function(id) {
44605         return (this.snapshot || this.data).findBy(function(record) {
44606             return record.getId() === id;
44607         });
44608     },
44609
44610     
44611     indexOf: function(record) {
44612         return this.data.indexOf(record);
44613     },
44614
44615
44616     
44617     indexOfTotal: function(record) {
44618         return record.index || this.indexOf(record);
44619     },
44620
44621     
44622     indexOfId: function(id) {
44623         return this.data.indexOfKey(id);
44624     },
44625         
44626     
44627     removeAll: function(silent) {
44628         var me = this;
44629
44630         me.clearData();
44631         if (me.snapshot) {
44632             me.snapshot.clear();
44633         }
44634         if (silent !== true) {
44635             me.fireEvent('clear', me);
44636         }
44637     },
44638
44639     
44640
44641     
44642     first: function(grouped) {
44643         var me = this;
44644
44645         if (grouped && me.isGrouped()) {
44646             return me.aggregate(function(records) {
44647                 return records.length ? records[0] : undefined;
44648             }, me, true);
44649         } else {
44650             return me.data.first();
44651         }
44652     },
44653
44654     
44655     last: function(grouped) {
44656         var me = this;
44657
44658         if (grouped && me.isGrouped()) {
44659             return me.aggregate(function(records) {
44660                 var len = records.length;
44661                 return len ? records[len - 1] : undefined;
44662             }, me, true);
44663         } else {
44664             return me.data.last();
44665         }
44666     },
44667
44668     
44669     sum: function(field, grouped) {
44670         var me = this;
44671
44672         if (grouped && me.isGrouped()) {
44673             return me.aggregate(me.getSum, me, true, [field]);
44674         } else {
44675             return me.getSum(me.data.items, field);
44676         }
44677     },
44678
44679     
44680     getSum: function(records, field) {
44681         var total = 0,
44682             i = 0,
44683             len = records.length;
44684
44685         for (; i < len; ++i) {
44686             total += records[i].get(field);
44687         }
44688
44689         return total;
44690     },
44691
44692     
44693     count: function(grouped) {
44694         var me = this;
44695
44696         if (grouped && me.isGrouped()) {
44697             return me.aggregate(function(records) {
44698                 return records.length;
44699             }, me, true);
44700         } else {
44701             return me.getCount();
44702         }
44703     },
44704
44705     
44706     min: function(field, grouped) {
44707         var me = this;
44708
44709         if (grouped && me.isGrouped()) {
44710             return me.aggregate(me.getMin, me, true, [field]);
44711         } else {
44712             return me.getMin(me.data.items, field);
44713         }
44714     },
44715
44716     
44717     getMin: function(records, field){
44718         var i = 1,
44719             len = records.length,
44720             value, min;
44721
44722         if (len > 0) {
44723             min = records[0].get(field);
44724         }
44725
44726         for (; i < len; ++i) {
44727             value = records[i].get(field);
44728             if (value < min) {
44729                 min = value;
44730             }
44731         }
44732         return min;
44733     },
44734
44735     
44736     max: function(field, grouped) {
44737         var me = this;
44738
44739         if (grouped && me.isGrouped()) {
44740             return me.aggregate(me.getMax, me, true, [field]);
44741         } else {
44742             return me.getMax(me.data.items, field);
44743         }
44744     },
44745
44746     
44747     getMax: function(records, field) {
44748         var i = 1,
44749             len = records.length,
44750             value,
44751             max;
44752
44753         if (len > 0) {
44754             max = records[0].get(field);
44755         }
44756
44757         for (; i < len; ++i) {
44758             value = records[i].get(field);
44759             if (value > max) {
44760                 max = value;
44761             }
44762         }
44763         return max;
44764     },
44765
44766     
44767     average: function(field, grouped) {
44768         var me = this;
44769         if (grouped && me.isGrouped()) {
44770             return me.aggregate(me.getAverage, me, true, [field]);
44771         } else {
44772             return me.getAverage(me.data.items, field);
44773         }
44774     },
44775
44776     
44777     getAverage: function(records, field) {
44778         var i = 0,
44779             len = records.length,
44780             sum = 0;
44781
44782         if (records.length > 0) {
44783             for (; i < len; ++i) {
44784                 sum += records[i].get(field);
44785             }
44786             return sum / len;
44787         }
44788         return 0;
44789     },
44790
44791     
44792     aggregate: function(fn, scope, grouped, args) {
44793         args = args || [];
44794         if (grouped && this.isGrouped()) {
44795             var groups = this.getGroups(),
44796                 i = 0,
44797                 len = groups.length,
44798                 out = {},
44799                 group;
44800
44801             for (; i < len; ++i) {
44802                 group = groups[i];
44803                 out[group.name] = fn.apply(scope || this, [group.children].concat(args));
44804             }
44805             return out;
44806         } else {
44807             return fn.apply(scope || this, [this.data.items].concat(args));
44808         }
44809     }
44810 });
44811
44812
44813 Ext.define('Ext.data.JsonStore',  {
44814     extend: 'Ext.data.Store',
44815     alias: 'store.json',
44816
44817     
44818     constructor: function(config) {
44819         config = config || {};
44820
44821         Ext.applyIf(config, {
44822             proxy: {
44823                 type  : 'ajax',
44824                 reader: 'json',
44825                 writer: 'json'
44826             }
44827         });
44828
44829         this.callParent([config]);
44830     }
44831 });
44832
44833
44834 Ext.define('Ext.chart.axis.Time', {
44835
44836     
44837
44838     extend: 'Ext.chart.axis.Category',
44839
44840     alternateClassName: 'Ext.chart.TimeAxis',
44841
44842     alias: 'axis.time',
44843
44844     requires: ['Ext.data.Store', 'Ext.data.JsonStore'],
44845
44846     
44847
44848      
44849     calculateByLabelSize: true,
44850     
44851      
44852     dateFormat: false,
44853     
44854      
44855     groupBy: 'year,month,day',
44856     
44857     
44858     aggregateOp: 'sum',
44859     
44860     
44861     fromDate: false,
44862     
44863     
44864     toDate: false,
44865     
44866     
44867     step: [Ext.Date.DAY, 1],
44868     
44869     
44870     constrain: false,
44871     
44872     
44873     dateMethods: {
44874         'year': function(date) {
44875             return date.getFullYear();
44876         },
44877         'month': function(date) {
44878             return date.getMonth() + 1;
44879         },
44880         'day': function(date) {
44881             return date.getDate();
44882         },
44883         'hour': function(date) {
44884             return date.getHours();
44885         },
44886         'minute': function(date) {
44887             return date.getMinutes();
44888         },
44889         'second': function(date) {
44890             return date.getSeconds();
44891         },
44892         'millisecond': function(date) {
44893             return date.getMilliseconds();
44894         }
44895     },
44896     
44897     
44898     aggregateFn: (function() {
44899         var etype = (function() {
44900             var rgxp = /^\[object\s(.*)\]$/,
44901                 toString = Object.prototype.toString;
44902             return function(e) {
44903                 return toString.call(e).match(rgxp)[1];
44904             };
44905         })();
44906         return {
44907             'sum': function(list) {
44908                 var i = 0, l = list.length, acum = 0;
44909                 if (!list.length || etype(list[0]) != 'Number') {
44910                     return list[0];
44911                 }
44912                 for (; i < l; i++) {
44913                     acum += list[i];
44914                 }
44915                 return acum;
44916             },
44917             'max': function(list) {
44918                 if (!list.length || etype(list[0]) != 'Number') {
44919                     return list[0];
44920                 }
44921                 return Math.max.apply(Math, list);
44922             },
44923             'min': function(list) {
44924                 if (!list.length || etype(list[0]) != 'Number') {
44925                     return list[0];
44926                 }
44927                 return Math.min.apply(Math, list);
44928             },
44929             'avg': function(list) {
44930                 var i = 0, l = list.length, acum = 0;
44931                 if (!list.length || etype(list[0]) != 'Number') {
44932                     return list[0];
44933                 }
44934                 for (; i < l; i++) {
44935                     acum += list[i];
44936                 }
44937                 return acum / l;
44938             }
44939         };
44940     })(),
44941     
44942     
44943     constrainDates: function() {
44944         var fromDate = Ext.Date.clone(this.fromDate),
44945             toDate = Ext.Date.clone(this.toDate),
44946             step = this.step,
44947             field = this.fields,
44948             store = this.chart.store,
44949             record, recObj, fieldNames = [],
44950             newStore = Ext.create('Ext.data.Store', {
44951                 model: store.model
44952             });
44953         
44954         var getRecordByDate = (function() {
44955             var index = 0, l = store.getCount();
44956             return function(date) {
44957                 var rec, recDate;
44958                 for (; index < l; index++) {
44959                     rec = store.getAt(index);
44960                     recDate = rec.get(field);
44961                     if (+recDate > +date) {
44962                         return false;
44963                     } else if (+recDate == +date) {
44964                         return rec;
44965                     }
44966                 }
44967                 return false;
44968             };
44969         })();
44970         
44971         if (!this.constrain) {
44972             this.chart.filteredStore = this.chart.store;
44973             return;
44974         }
44975
44976         while(+fromDate <= +toDate) {
44977             record = getRecordByDate(fromDate);
44978             recObj = {};
44979             if (record) {
44980                 newStore.add(record.data);
44981             } else {
44982                 newStore.model.prototype.fields.each(function(f) {
44983                     recObj[f.name] = false;
44984                 });
44985                 recObj.date = fromDate;
44986                 newStore.add(recObj);
44987             }
44988             fromDate = Ext.Date.add(fromDate, step[0], step[1]);
44989         }
44990          
44991         this.chart.filteredStore = newStore;
44992     },
44993     
44994     
44995     aggregate: function() {
44996         var aggStore = {}, 
44997             aggKeys = [], key, value,
44998             op = this.aggregateOp,
44999             field = this.fields, i,
45000             fields = this.groupBy.split(','),
45001             curField,
45002             recFields = [],
45003             recFieldsLen = 0,
45004             obj,
45005             dates = [],
45006             json = [],
45007             l = fields.length,
45008             dateMethods = this.dateMethods,
45009             aggregateFn = this.aggregateFn,
45010             store = this.chart.filteredStore || this.chart.store;
45011         
45012         store.each(function(rec) {
45013             
45014             if (!recFields.length) {
45015                 rec.fields.each(function(f) {
45016                     recFields.push(f.name);
45017                 });
45018                 recFieldsLen = recFields.length;
45019             }
45020             
45021             value = rec.get(field);
45022             
45023             for (i = 0; i < l; i++) {
45024                 if (i == 0) {
45025                     key = String(dateMethods[fields[i]](value));
45026                 } else {
45027                     key += '||' + dateMethods[fields[i]](value);
45028                 }
45029             }
45030             
45031             if (key in aggStore) {
45032                 obj = aggStore[key];
45033             } else {
45034                 obj = aggStore[key] = {};
45035                 aggKeys.push(key);
45036                 dates.push(value);
45037             }
45038             
45039             for (i = 0; i < recFieldsLen; i++) {
45040                 curField = recFields[i];
45041                 if (!obj[curField]) {
45042                     obj[curField] = [];
45043                 }
45044                 if (rec.get(curField) !== undefined) {
45045                     obj[curField].push(rec.get(curField));
45046                 }
45047             }
45048         });
45049         
45050         for (key in aggStore) {
45051             obj = aggStore[key];
45052             for (i = 0; i < recFieldsLen; i++) {
45053                 curField = recFields[i];
45054                 obj[curField] = aggregateFn[op](obj[curField]);
45055             }
45056             json.push(obj);
45057         }
45058         this.chart.substore = Ext.create('Ext.data.JsonStore', {
45059             fields: recFields,
45060             data: json
45061         });
45062         
45063         this.dates = dates;
45064     },
45065     
45066     
45067      setLabels: function() {
45068         var store = this.chart.substore,
45069             fields = this.fields,
45070             format = this.dateFormat,
45071             labels, i, dates = this.dates,
45072             formatFn = Ext.Date.format;
45073         this.labels = labels = [];
45074         store.each(function(record, i) {
45075             if (!format) {
45076                 labels.push(record.get(fields));
45077             } else {
45078                 labels.push(formatFn(dates[i], format));
45079             }
45080          }, this);
45081      },
45082
45083     processView: function() {
45084          
45085          if (this.constrain) {
45086              this.constrainDates();
45087              this.aggregate();
45088              this.chart.substore = this.chart.filteredStore;
45089          } else {
45090              this.aggregate();
45091          }
45092     },
45093
45094      
45095      applyData: function() {
45096         this.setLabels();
45097         var count = this.chart.substore.getCount();
45098          return {
45099              from: 0,
45100              to: count,
45101              steps: count - 1,
45102              step: 1
45103          };
45104      }
45105  });
45106
45107
45108
45109 Ext.define('Ext.chart.series.Series', {
45110
45111     
45112
45113     mixins: {
45114         observable: 'Ext.util.Observable',
45115         labels: 'Ext.chart.Label',
45116         highlights: 'Ext.chart.Highlight',
45117         tips: 'Ext.chart.Tip',
45118         callouts: 'Ext.chart.Callout'
45119     },
45120
45121     
45122
45123     
45124
45125     
45126
45127     
45128     type: null,
45129
45130     
45131     title: null,
45132
45133     
45134     showInLegend: true,
45135
45136     
45137     renderer: function(sprite, record, attributes, index, store) {
45138         return attributes;
45139     },
45140
45141     
45142     shadowAttributes: null,
45143     
45144     //@private triggerdrawlistener flag
45145
45146     triggerAfterDraw: false,
45147
45148     
45149     
45150     constructor: function(config) {
45151         var me = this;
45152         if (config) {
45153             Ext.apply(me, config);
45154         }
45155         
45156         me.shadowGroups = [];
45157         
45158         me.mixins.labels.constructor.call(me, config);
45159         me.mixins.highlights.constructor.call(me, config);
45160         me.mixins.tips.constructor.call(me, config);
45161         me.mixins.callouts.constructor.call(me, config);
45162
45163         me.addEvents({
45164             scope: me,
45165             itemmouseover: true,
45166             itemmouseout: true,
45167             itemmousedown: true,
45168             itemmouseup: true,
45169             mouseleave: true,
45170             afterdraw: true,
45171
45172             
45173             titlechange: true
45174         });
45175
45176         me.mixins.observable.constructor.call(me, config);
45177
45178         me.on({
45179             scope: me,
45180             itemmouseover: me.onItemMouseOver,
45181             itemmouseout: me.onItemMouseOut,
45182             mouseleave: me.onMouseLeave
45183         });
45184     },
45185
45186     
45187     setBBox: function(noGutter) {
45188         var me = this,
45189             chart = me.chart,
45190             chartBBox = chart.chartBBox,
45191             gutterX = noGutter ? 0 : chart.maxGutter[0],
45192             gutterY = noGutter ? 0 : chart.maxGutter[1],
45193             clipBox, bbox;
45194
45195         clipBox = {
45196             x: chartBBox.x,
45197             y: chartBBox.y,
45198             width: chartBBox.width,
45199             height: chartBBox.height
45200         };
45201         me.clipBox = clipBox;
45202
45203         bbox = {
45204             x: (clipBox.x + gutterX) - (chart.zoom.x * chart.zoom.width),
45205             y: (clipBox.y + gutterY) - (chart.zoom.y * chart.zoom.height),
45206             width: (clipBox.width - (gutterX * 2)) * chart.zoom.width,
45207             height: (clipBox.height - (gutterY * 2)) * chart.zoom.height
45208         };
45209         me.bbox = bbox;
45210     },
45211
45212     
45213     onAnimate: function(sprite, attr) {
45214         var me = this;
45215         sprite.stopAnimation();
45216         if (me.triggerAfterDraw) {
45217             return sprite.animate(Ext.applyIf(attr, me.chart.animate));
45218         } else {
45219             me.triggerAfterDraw = true;
45220             return sprite.animate(Ext.apply(Ext.applyIf(attr, me.chart.animate), {
45221                 listeners: {
45222                     'afteranimate': function() {
45223                         me.triggerAfterDraw = false;
45224                         me.fireEvent('afterrender');
45225                     }    
45226                 }    
45227             }));
45228         }
45229     },
45230     
45231     
45232     getGutters: function() {
45233         return [0, 0];
45234     },
45235
45236     
45237     onItemMouseOver: function(item) { 
45238         var me = this;
45239         if (item.series === me) {
45240             if (me.highlight) {
45241                 me.highlightItem(item);
45242             }
45243             if (me.tooltip) {
45244                 me.showTip(item);
45245             }
45246         }
45247     },
45248
45249     
45250     onItemMouseOut: function(item) {
45251         var me = this;
45252         if (item.series === me) {
45253             me.unHighlightItem();
45254             if (me.tooltip) {
45255                 me.hideTip(item);
45256             }
45257         }
45258     },
45259
45260     
45261     onMouseLeave: function() {
45262         var me = this;
45263         me.unHighlightItem();
45264         if (me.tooltip) {
45265             me.hideTip();
45266         }
45267     },
45268
45269     
45270     getItemForPoint: function(x, y) {
45271         
45272         if (!this.items || !this.items.length || this.seriesIsHidden) {
45273             return null;
45274         }
45275         var me = this,
45276             items = me.items,
45277             bbox = me.bbox,
45278             item, i, ln;
45279         
45280         if (!Ext.draw.Draw.withinBox(x, y, bbox)) {
45281             return null;
45282         }
45283         for (i = 0, ln = items.length; i < ln; i++) {
45284             if (items[i] && this.isItemInPoint(x, y, items[i], i)) {
45285                 return items[i];
45286             }
45287         }
45288         
45289         return null;
45290     },
45291     
45292     isItemInPoint: function(x, y, item, i) {
45293         return false;
45294     },
45295
45296     
45297     hideAll: function() {
45298         var me = this,
45299             items = me.items,
45300             item, len, i, sprite;
45301
45302         me.seriesIsHidden = true;
45303         me._prevShowMarkers = me.showMarkers;
45304
45305         me.showMarkers = false;
45306         
45307         me.hideLabels(0);
45308         
45309         for (i = 0, len = items.length; i < len; i++) {
45310             item = items[i];
45311             sprite = item.sprite;
45312             if (sprite) {
45313                 sprite.setAttributes({
45314                     hidden: true
45315                 }, true);
45316             }
45317         }
45318     },
45319
45320     
45321     showAll: function() {
45322         var me = this,
45323             prevAnimate = me.chart.animate;
45324         me.chart.animate = false;
45325         me.seriesIsHidden = false;
45326         me.showMarkers = me._prevShowMarkers;
45327         me.drawSeries();
45328         me.chart.animate = prevAnimate;
45329     },
45330     
45331     
45332     getLegendColor: function(index) {
45333         var me = this, fill, stroke;
45334         if (me.seriesStyle) {
45335             fill = me.seriesStyle.fill;
45336             stroke = me.seriesStyle.stroke;
45337             if (fill && fill != 'none') {
45338                 return fill;
45339             }
45340             return stroke;
45341         }
45342         return '#000';
45343     },
45344     
45345     
45346     visibleInLegend: function(index){
45347         var excludes = this.__excludes;
45348         if (excludes) {
45349             return !excludes[index];
45350         }
45351         return !this.seriesIsHidden;
45352     },
45353
45354     
45355     setTitle: function(index, title) {
45356         var me = this,
45357             oldTitle = me.title;
45358
45359         if (Ext.isString(index)) {
45360             title = index;
45361             index = 0;
45362         }
45363
45364         if (Ext.isArray(oldTitle)) {
45365             oldTitle[index] = title;
45366         } else {
45367             me.title = title;
45368         }
45369
45370         me.fireEvent('titlechange', title, index);
45371     }
45372 });
45373
45374
45375 Ext.define('Ext.chart.series.Cartesian', {
45376
45377     
45378
45379     extend: 'Ext.chart.series.Series',
45380
45381     alternateClassName: ['Ext.chart.CartesianSeries', 'Ext.chart.CartesianChart'],
45382
45383     
45384
45385     
45386     xField: null,
45387
45388     
45389     yField: null,
45390
45391     
45392     axis: 'left'
45393 });
45394
45395
45396 Ext.define('Ext.chart.series.Area', {
45397
45398     
45399
45400     extend: 'Ext.chart.series.Cartesian',
45401     
45402     alias: 'series.area',
45403
45404     requires: ['Ext.chart.axis.Axis', 'Ext.draw.Color', 'Ext.fx.Anim'],
45405
45406     
45407
45408     type: 'area',
45409
45410     
45411     stacked: true,
45412
45413     
45414     style: {},
45415
45416     constructor: function(config) {
45417         this.callParent(arguments);
45418         var me = this,
45419             surface = me.chart.surface,
45420             i, l;
45421         Ext.apply(me, config, {
45422             __excludes: [],
45423             highlightCfg: {
45424                 lineWidth: 3,
45425                 stroke: '#55c',
45426                 opacity: 0.8,
45427                 color: '#f00'
45428             }
45429         });
45430         if (me.highlight) {
45431             me.highlightSprite = surface.add({
45432                 type: 'path',
45433                 path: ['M', 0, 0],
45434                 zIndex: 1000,
45435                 opacity: 0.3,
45436                 lineWidth: 5,
45437                 hidden: true,
45438                 stroke: '#444'
45439             });
45440         }
45441         me.group = surface.getGroup(me.seriesId);
45442     },
45443
45444     
45445     shrink: function(xValues, yValues, size) {
45446         var len = xValues.length,
45447             ratio = Math.floor(len / size),
45448             i, j,
45449             xSum = 0,
45450             yCompLen = this.areas.length,
45451             ySum = [],
45452             xRes = [],
45453             yRes = [];
45454         
45455         for (j = 0; j < yCompLen; ++j) {
45456             ySum[j] = 0;
45457         }
45458         for (i = 0; i < len; ++i) {
45459             xSum += xValues[i];
45460             for (j = 0; j < yCompLen; ++j) {
45461                 ySum[j] += yValues[i][j];
45462             }
45463             if (i % ratio == 0) {
45464                 
45465                 xRes.push(xSum/ratio);
45466                 for (j = 0; j < yCompLen; ++j) {
45467                     ySum[j] /= ratio;
45468                 }
45469                 yRes.push(ySum);
45470                 
45471                 xSum = 0;
45472                 for (j = 0, ySum = []; j < yCompLen; ++j) {
45473                     ySum[j] = 0;
45474                 }
45475             }
45476         }
45477         return {
45478             x: xRes,
45479             y: yRes
45480         };
45481     },
45482
45483     
45484     getBounds: function() {
45485         var me = this,
45486             chart = me.chart,
45487             store = chart.substore || chart.store,
45488             areas = [].concat(me.yField),
45489             areasLen = areas.length,
45490             xValues = [],
45491             yValues = [],
45492             infinity = Infinity,
45493             minX = infinity,
45494             minY = infinity,
45495             maxX = -infinity,
45496             maxY = -infinity,
45497             math = Math,
45498             mmin = math.min,
45499             mmax = math.max,
45500             bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem;
45501
45502         me.setBBox();
45503         bbox = me.bbox;
45504
45505         
45506         if (me.axis) {
45507             axis = chart.axes.get(me.axis);
45508             if (axis) {
45509                 out = axis.calcEnds();
45510                 minY = out.from || axis.prevMin;
45511                 maxY = mmax(out.to || axis.prevMax, 0);
45512             }
45513         }
45514
45515         if (me.yField && !Ext.isNumber(minY)) {
45516             axis = Ext.create('Ext.chart.axis.Axis', {
45517                 chart: chart,
45518                 fields: [].concat(me.yField)
45519             });
45520             out = axis.calcEnds();
45521             minY = out.from || axis.prevMin;
45522             maxY = mmax(out.to || axis.prevMax, 0);
45523         }
45524
45525         if (!Ext.isNumber(minY)) {
45526             minY = 0;
45527         }
45528         if (!Ext.isNumber(maxY)) {
45529             maxY = 0;
45530         }
45531
45532         store.each(function(record, i) {
45533             xValue = record.get(me.xField);
45534             yValue = [];
45535             if (typeof xValue != 'number') {
45536                 xValue = i;
45537             }
45538             xValues.push(xValue);
45539             acumY = 0;
45540             for (areaIndex = 0; areaIndex < areasLen; areaIndex++) {
45541                 areaElem = record.get(areas[areaIndex]);
45542                 if (typeof areaElem == 'number') {
45543                     minY = mmin(minY, areaElem);
45544                     yValue.push(areaElem);
45545                     acumY += areaElem;
45546                 }
45547             }
45548             minX = mmin(minX, xValue);
45549             maxX = mmax(maxX, xValue);
45550             maxY = mmax(maxY, acumY);
45551             yValues.push(yValue);
45552         }, me);
45553
45554         xScale = bbox.width / (maxX - minX);
45555         yScale = bbox.height / (maxY - minY);
45556
45557         ln = xValues.length;
45558         if ((ln > bbox.width) && me.areas) {
45559             sumValues = me.shrink(xValues, yValues, bbox.width);
45560             xValues = sumValues.x;
45561             yValues = sumValues.y;
45562         }
45563
45564         return {
45565             bbox: bbox,
45566             minX: minX,
45567             minY: minY,
45568             xValues: xValues,
45569             yValues: yValues,
45570             xScale: xScale,
45571             yScale: yScale,
45572             areasLen: areasLen
45573         };
45574     },
45575
45576     
45577     getPaths: function() {
45578         var me = this,
45579             chart = me.chart,
45580             store = chart.substore || chart.store,
45581             first = true,
45582             bounds = me.getBounds(),
45583             bbox = bounds.bbox,
45584             items = me.items = [],
45585             componentPaths = [],
45586             componentPath,
45587             paths = [],
45588             i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path;
45589
45590         ln = bounds.xValues.length;
45591         
45592         for (i = 0; i < ln; i++) {
45593             xValue = bounds.xValues[i];
45594             yValue = bounds.yValues[i];
45595             x = bbox.x + (xValue - bounds.minX) * bounds.xScale;
45596             acumY = 0;
45597             for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
45598                 
45599                 if (me.__excludes[areaIndex]) {
45600                     continue;
45601                 }
45602                 if (!componentPaths[areaIndex]) {
45603                     componentPaths[areaIndex] = [];
45604                 }
45605                 areaElem = yValue[areaIndex];
45606                 acumY += areaElem;
45607                 y = bbox.y + bbox.height - (acumY - bounds.minY) * bounds.yScale;
45608                 if (!paths[areaIndex]) {
45609                     paths[areaIndex] = ['M', x, y];
45610                     componentPaths[areaIndex].push(['L', x, y]);
45611                 } else {
45612                     paths[areaIndex].push('L', x, y);
45613                     componentPaths[areaIndex].push(['L', x, y]);
45614                 }
45615                 if (!items[areaIndex]) {
45616                     items[areaIndex] = {
45617                         pointsUp: [],
45618                         pointsDown: [],
45619                         series: me
45620                     };
45621                 }
45622                 items[areaIndex].pointsUp.push([x, y]);
45623             }
45624         }
45625         
45626         
45627         for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
45628             
45629             if (me.__excludes[areaIndex]) {
45630                 continue;
45631             }
45632             path = paths[areaIndex];
45633             
45634             if (areaIndex == 0 || first) {
45635                 first = false;
45636                 path.push('L', x, bbox.y + bbox.height,
45637                           'L', bbox.x, bbox.y + bbox.height,
45638                           'Z');
45639             }
45640             
45641             else {
45642                 componentPath = componentPaths[prevAreaIndex];
45643                 componentPath.reverse();
45644                 path.push('L', x, componentPath[0][2]);
45645                 for (i = 0; i < ln; i++) {
45646                     path.push(componentPath[i][0],
45647                               componentPath[i][1],
45648                               componentPath[i][2]);
45649                     items[areaIndex].pointsDown[ln -i -1] = [componentPath[i][1], componentPath[i][2]];
45650                 }
45651                 path.push('L', bbox.x, path[2], 'Z');
45652             }
45653             prevAreaIndex = areaIndex;
45654         }
45655         return {
45656             paths: paths,
45657             areasLen: bounds.areasLen
45658         };
45659     },
45660
45661     
45662     drawSeries: function() {
45663         var me = this,
45664             chart = me.chart,
45665             store = chart.substore || chart.store,
45666             surface = chart.surface,
45667             animate = chart.animate,
45668             group = me.group,
45669             endLineStyle = Ext.apply(me.seriesStyle, me.style),
45670             colorArrayStyle = me.colorArrayStyle,
45671             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
45672             areaIndex, areaElem, paths, path, rendererAttributes;
45673
45674         me.unHighlightItem();
45675         me.cleanHighlights();
45676
45677         if (!store || !store.getCount()) {
45678             return;
45679         }
45680         
45681         paths = me.getPaths();
45682
45683         if (!me.areas) {
45684             me.areas = [];
45685         }
45686
45687         for (areaIndex = 0; areaIndex < paths.areasLen; areaIndex++) {
45688             
45689             if (me.__excludes[areaIndex]) {
45690                 continue;
45691             }
45692             if (!me.areas[areaIndex]) {
45693                 me.items[areaIndex].sprite = me.areas[areaIndex] = surface.add(Ext.apply({}, {
45694                     type: 'path',
45695                     group: group,
45696                     
45697                     path: paths.paths[areaIndex],
45698                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength],
45699                     fill: colorArrayStyle[areaIndex % colorArrayLength]
45700                 }, endLineStyle || {}));
45701             }
45702             areaElem = me.areas[areaIndex];
45703             path = paths.paths[areaIndex];
45704             if (animate) {
45705                 
45706                 rendererAttributes = me.renderer(areaElem, false, { 
45707                     path: path,
45708                     
45709                     fill: colorArrayStyle[areaIndex % colorArrayLength],
45710                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
45711                 }, areaIndex, store);
45712                 
45713                 me.animation = me.onAnimate(areaElem, {
45714                     to: rendererAttributes
45715                 });
45716             } else {
45717                 rendererAttributes = me.renderer(areaElem, false, { 
45718                     path: path,
45719                     
45720                     hidden: false,
45721                     fill: colorArrayStyle[areaIndex % colorArrayLength],
45722                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
45723                 }, areaIndex, store);
45724                 me.areas[areaIndex].setAttributes(rendererAttributes, true);
45725             }
45726         }
45727         me.renderLabels();
45728         me.renderCallouts();
45729     },
45730
45731     
45732     onAnimate: function(sprite, attr) {
45733         sprite.show();
45734         return this.callParent(arguments);
45735     },
45736
45737     
45738     onCreateLabel: function(storeItem, item, i, display) {
45739         var me = this,
45740             group = me.labelsGroup,
45741             config = me.label,
45742             bbox = me.bbox,
45743             endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
45744
45745         return me.chart.surface.add(Ext.apply({
45746             'type': 'text',
45747             'text-anchor': 'middle',
45748             'group': group,
45749             'x': item.point[0],
45750             'y': bbox.y + bbox.height / 2
45751         }, endLabelStyle || {}));
45752     },
45753
45754     
45755     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
45756         var me = this,
45757             chart = me.chart,
45758             resizing = chart.resizing,
45759             config = me.label,
45760             format = config.renderer,
45761             field = config.field,
45762             bbox = me.bbox,
45763             x = item.point[0],
45764             y = item.point[1],
45765             bb, width, height;
45766         
45767         label.setAttributes({
45768             text: format(storeItem.get(field[index])),
45769             hidden: true
45770         }, true);
45771         
45772         bb = label.getBBox();
45773         width = bb.width / 2;
45774         height = bb.height / 2;
45775         
45776         x = x - width < bbox.x? bbox.x + width : x;
45777         x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
45778         y = y - height < bbox.y? bbox.y + height : y;
45779         y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
45780
45781         if (me.chart.animate && !me.chart.resizing) {
45782             label.show(true);
45783             me.onAnimate(label, {
45784                 to: {
45785                     x: x,
45786                     y: y
45787                 }
45788             });
45789         } else {
45790             label.setAttributes({
45791                 x: x,
45792                 y: y
45793             }, true);
45794             if (resizing) {
45795                 me.animation.on('afteranimate', function() {
45796                     label.show(true);
45797                 });
45798             } else {
45799                 label.show(true);
45800             }
45801         }
45802     },
45803
45804     
45805     onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
45806         var me = this,
45807             chart = me.chart,
45808             surface = chart.surface,
45809             resizing = chart.resizing,
45810             config = me.callouts,
45811             items = me.items,
45812             prev = (i == 0) ? false : items[i -1].point,
45813             next = (i == items.length -1) ? false : items[i +1].point,
45814             cur = item.point,
45815             dir, norm, normal, a, aprev, anext,
45816             bbox = callout.label.getBBox(),
45817             offsetFromViz = 30,
45818             offsetToSide = 10,
45819             offsetBox = 3,
45820             boxx, boxy, boxw, boxh,
45821             p, clipRect = me.clipRect,
45822             x, y;
45823
45824         
45825         if (!prev) {
45826             prev = cur;
45827         }
45828         if (!next) {
45829             next = cur;
45830         }
45831         a = (next[1] - prev[1]) / (next[0] - prev[0]);
45832         aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
45833         anext = (next[1] - cur[1]) / (next[0] - cur[0]);
45834         
45835         norm = Math.sqrt(1 + a * a);
45836         dir = [1 / norm, a / norm];
45837         normal = [-dir[1], dir[0]];
45838         
45839         
45840         if (aprev > 0 && anext < 0 && normal[1] < 0 || aprev < 0 && anext > 0 && normal[1] > 0) {
45841             normal[0] *= -1;
45842             normal[1] *= -1;
45843         } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0 || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
45844             normal[0] *= -1;
45845             normal[1] *= -1;
45846         }
45847
45848         
45849         x = cur[0] + normal[0] * offsetFromViz;
45850         y = cur[1] + normal[1] * offsetFromViz;
45851         
45852         
45853         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
45854         boxy = y - bbox.height /2 - offsetBox;
45855         boxw = bbox.width + 2 * offsetBox;
45856         boxh = bbox.height + 2 * offsetBox;
45857         
45858         
45859         
45860         if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
45861             normal[0] *= -1;
45862         }
45863         if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
45864             normal[1] *= -1;
45865         }
45866
45867         
45868         x = cur[0] + normal[0] * offsetFromViz;
45869         y = cur[1] + normal[1] * offsetFromViz;
45870         
45871         
45872         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
45873         boxy = y - bbox.height /2 - offsetBox;
45874         boxw = bbox.width + 2 * offsetBox;
45875         boxh = bbox.height + 2 * offsetBox;
45876         
45877         
45878         callout.lines.setAttributes({
45879             path: ["M", cur[0], cur[1], "L", x, y, "Z"]
45880         }, true);
45881         
45882         callout.box.setAttributes({
45883             x: boxx,
45884             y: boxy,
45885             width: boxw,
45886             height: boxh
45887         }, true);
45888         
45889         callout.label.setAttributes({
45890             x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
45891             y: y
45892         }, true);
45893         for (p in callout) {
45894             callout[p].show(true);
45895         }
45896     },
45897     
45898     isItemInPoint: function(x, y, item, i) {
45899         var me = this,
45900             pointsUp = item.pointsUp,
45901             pointsDown = item.pointsDown,
45902             abs = Math.abs,
45903             dist = Infinity, p, pln, point;
45904         
45905         for (p = 0, pln = pointsUp.length; p < pln; p++) {
45906             point = [pointsUp[p][0], pointsUp[p][1]];
45907             if (dist > abs(x - point[0])) {
45908                 dist = abs(x - point[0]);
45909             } else {
45910                 point = pointsUp[p -1];
45911                 if (y >= point[1] && (!pointsDown.length || y <= (pointsDown[p -1][1]))) {
45912                     item.storeIndex = p -1;
45913                     item.storeField = me.yField[i];
45914                     item.storeItem = me.chart.store.getAt(p -1);
45915                     item._points = pointsDown.length? [point, pointsDown[p -1]] : [point];
45916                     return true;
45917                 } else {
45918                     break;
45919                 }
45920             }
45921         }
45922         return false;
45923     },
45924
45925     
45926     highlightSeries: function() {
45927         var area, to, fillColor;
45928         if (this._index !== undefined) {
45929             area = this.areas[this._index];
45930             if (area.__highlightAnim) {
45931                 area.__highlightAnim.paused = true;
45932             }
45933             area.__highlighted = true;
45934             area.__prevOpacity = area.__prevOpacity || area.attr.opacity || 1;
45935             area.__prevFill = area.__prevFill || area.attr.fill;
45936             area.__prevLineWidth = area.__prevLineWidth || area.attr.lineWidth;
45937             fillColor = Ext.draw.Color.fromString(area.__prevFill);
45938             to = {
45939                 lineWidth: (area.__prevLineWidth || 0) + 2
45940             };
45941             if (fillColor) {
45942                 to.fill = fillColor.getLighter(0.2).toString();
45943             }
45944             else {
45945                 to.opacity = Math.max(area.__prevOpacity - 0.3, 0);
45946             }
45947             if (this.chart.animate) {
45948                 area.__highlightAnim = Ext.create('Ext.fx.Anim', Ext.apply({
45949                     target: area,
45950                     to: to
45951                 }, this.chart.animate));
45952             }
45953             else {
45954                 area.setAttributes(to, true);
45955             }
45956         }
45957     },
45958
45959     
45960     unHighlightSeries: function() {
45961         var area;
45962         if (this._index !== undefined) {
45963             area = this.areas[this._index];
45964             if (area.__highlightAnim) {
45965                 area.__highlightAnim.paused = true;
45966             }
45967             if (area.__highlighted) {
45968                 area.__highlighted = false;
45969                 area.__highlightAnim = Ext.create('Ext.fx.Anim', {
45970                     target: area,
45971                     to: {
45972                         fill: area.__prevFill,
45973                         opacity: area.__prevOpacity,
45974                         lineWidth: area.__prevLineWidth
45975                     }
45976                 });
45977             }
45978         }
45979     },
45980
45981     
45982     highlightItem: function(item) {
45983         var me = this,
45984             points, path;
45985         if (!item) {
45986             this.highlightSeries();
45987             return;
45988         }
45989         points = item._points;
45990         path = points.length == 2? ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]
45991                 : ['M', points[0][0], points[0][1], 'L', points[0][0], me.bbox.y + me.bbox.height];
45992         me.highlightSprite.setAttributes({
45993             path: path,
45994             hidden: false
45995         }, true);
45996     },
45997
45998     
45999     unHighlightItem: function(item) {
46000         if (!item) {
46001             this.unHighlightSeries();
46002         }
46003
46004         if (this.highlightSprite) {
46005             this.highlightSprite.hide(true);
46006         }
46007     },
46008
46009     
46010     hideAll: function() {
46011         if (!isNaN(this._index)) {
46012             this.__excludes[this._index] = true;
46013             this.areas[this._index].hide(true);
46014             this.drawSeries();
46015         }
46016     },
46017
46018     
46019     showAll: function() {
46020         if (!isNaN(this._index)) {
46021             this.__excludes[this._index] = false;
46022             this.areas[this._index].show(true);
46023             this.drawSeries();
46024         }
46025     },
46026
46027     
46028     getLegendColor: function(index) {
46029         var me = this;
46030         return me.colorArrayStyle[index % me.colorArrayStyle.length];
46031     }
46032 });
46033
46034
46035 Ext.define('Ext.chart.series.Bar', {
46036
46037     
46038
46039     extend: 'Ext.chart.series.Cartesian',
46040
46041     alternateClassName: ['Ext.chart.BarSeries', 'Ext.chart.BarChart', 'Ext.chart.StackedBarChart'],
46042
46043     requires: ['Ext.chart.axis.Axis', 'Ext.fx.Anim'],
46044
46045     
46046
46047     type: 'bar',
46048
46049     alias: 'series.bar',
46050     
46051     column: false,
46052     
46053     
46054     style: {},
46055     
46056     
46057     gutter: 38.2,
46058
46059     
46060     groupGutter: 38.2,
46061
46062     
46063     xPadding: 0,
46064
46065     
46066     yPadding: 10,
46067
46068     constructor: function(config) {
46069         this.callParent(arguments);
46070         var me = this,
46071             surface = me.chart.surface,
46072             shadow = me.chart.shadow,
46073             i, l;
46074         Ext.apply(me, config, {
46075             highlightCfg: {
46076                 lineWidth: 3,
46077                 stroke: '#55c',
46078                 opacity: 0.8,
46079                 color: '#f00'
46080             },
46081             
46082             shadowAttributes: [{
46083                 "stroke-width": 6,
46084                 "stroke-opacity": 0.05,
46085                 stroke: 'rgb(200, 200, 200)',
46086                 translate: {
46087                     x: 1.2,
46088                     y: 1.2
46089                 }
46090             }, {
46091                 "stroke-width": 4,
46092                 "stroke-opacity": 0.1,
46093                 stroke: 'rgb(150, 150, 150)',
46094                 translate: {
46095                     x: 0.9,
46096                     y: 0.9
46097                 }
46098             }, {
46099                 "stroke-width": 2,
46100                 "stroke-opacity": 0.15,
46101                 stroke: 'rgb(100, 100, 100)',
46102                 translate: {
46103                     x: 0.6,
46104                     y: 0.6
46105                 }
46106             }]
46107         });
46108         me.group = surface.getGroup(me.seriesId + '-bars');
46109         if (shadow) {
46110             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
46111                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
46112             }
46113         }
46114     },
46115
46116     
46117     getBarGirth: function() {
46118         var me = this,
46119             store = me.chart.store,
46120             column = me.column,
46121             ln = store.getCount(),
46122             gutter = me.gutter / 100;
46123         
46124         return (me.chart.chartBBox[column ? 'width' : 'height'] - me[column ? 'xPadding' : 'yPadding'] * 2) / (ln * (gutter + 1) - gutter);
46125     },
46126
46127     
46128     getGutters: function() {
46129         var me = this,
46130             column = me.column,
46131             gutter = Math.ceil(me[column ? 'xPadding' : 'yPadding'] + me.getBarGirth() / 2);
46132         return me.column ? [gutter, 0] : [0, gutter];
46133     },
46134
46135     
46136     getBounds: function() {
46137         var me = this,
46138             chart = me.chart,
46139             store = chart.substore || chart.store,
46140             bars = [].concat(me.yField),
46141             barsLen = bars.length,
46142             groupBarsLen = barsLen,
46143             groupGutter = me.groupGutter / 100,
46144             column = me.column,
46145             xPadding = me.xPadding,
46146             yPadding = me.yPadding,
46147             stacked = me.stacked,
46148             barWidth = me.getBarGirth(),
46149             math = Math,
46150             mmax = math.max,
46151             mabs = math.abs,
46152             groupBarWidth, bbox, minY, maxY, axis, out,
46153             scale, zero, total, rec, j, plus, minus;
46154
46155         me.setBBox(true);
46156         bbox = me.bbox;
46157
46158         
46159         if (me.__excludes) {
46160             for (j = 0, total = me.__excludes.length; j < total; j++) {
46161                 if (me.__excludes[j]) {
46162                     groupBarsLen--;
46163                 }
46164             }
46165         }
46166
46167         if (me.axis) {
46168             axis = chart.axes.get(me.axis);
46169             if (axis) {
46170                 out = axis.calcEnds();
46171                 minY = out.from || axis.prevMin;
46172                 maxY = mmax(out.to || axis.prevMax, 0);
46173             }
46174         }
46175
46176         if (me.yField && !Ext.isNumber(minY)) {
46177             axis = Ext.create('Ext.chart.axis.Axis', {
46178                 chart: chart,
46179                 fields: [].concat(me.yField)
46180             });
46181             out = axis.calcEnds();
46182             minY = out.from || axis.prevMin;
46183             maxY = mmax(out.to || axis.prevMax, 0);
46184         }
46185
46186         if (!Ext.isNumber(minY)) {
46187             minY = 0;
46188         }
46189         if (!Ext.isNumber(maxY)) {
46190             maxY = 0;
46191         }
46192         scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (maxY - minY);
46193         groupBarWidth = barWidth / ((stacked ? 1 : groupBarsLen) * (groupGutter + 1) - groupGutter);
46194         zero = (column) ? bbox.y + bbox.height - yPadding : bbox.x + xPadding;
46195
46196         if (stacked) {
46197             total = [[], []];
46198             store.each(function(record, i) {
46199                 total[0][i] = total[0][i] || 0;
46200                 total[1][i] = total[1][i] || 0;
46201                 for (j = 0; j < barsLen; j++) {
46202                     if (me.__excludes && me.__excludes[j]) {
46203                         continue;
46204                     }
46205                     rec = record.get(bars[j]);
46206                     total[+(rec > 0)][i] += mabs(rec);
46207                 }
46208             });
46209             total[+(maxY > 0)].push(mabs(maxY));
46210             total[+(minY > 0)].push(mabs(minY));
46211             minus = mmax.apply(math, total[0]);
46212             plus = mmax.apply(math, total[1]);
46213             scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (plus + minus);
46214             zero = zero + minus * scale * (column ? -1 : 1);
46215         }
46216         else if (minY / maxY < 0) {
46217             zero = zero - minY * scale * (column ? -1 : 1);
46218         }
46219         return {
46220             bars: bars,
46221             bbox: bbox,
46222             barsLen: barsLen,
46223             groupBarsLen: groupBarsLen,
46224             barWidth: barWidth,
46225             groupBarWidth: groupBarWidth,
46226             scale: scale,
46227             zero: zero,
46228             xPadding: xPadding,
46229             yPadding: yPadding,
46230             signed: minY / maxY < 0,
46231             minY: minY,
46232             maxY: maxY
46233         };
46234     },
46235
46236     
46237     getPaths: function() {
46238         var me = this,
46239             chart = me.chart,
46240             store = chart.substore || chart.store,
46241             bounds = me.bounds = me.getBounds(),
46242             items = me.items = [],
46243             gutter = me.gutter / 100,
46244             groupGutter = me.groupGutter / 100,
46245             animate = chart.animate,
46246             column = me.column,
46247             group = me.group,
46248             enableShadows = chart.shadow,
46249             shadowGroups = me.shadowGroups,
46250             shadowAttributes = me.shadowAttributes,
46251             shadowGroupsLn = shadowGroups.length,
46252             bbox = bounds.bbox,
46253             xPadding = me.xPadding,
46254             yPadding = me.yPadding,
46255             stacked = me.stacked,
46256             barsLen = bounds.barsLen,
46257             colors = me.colorArrayStyle,
46258             colorLength = colors && colors.length || 0,
46259             math = Math,
46260             mmax = math.max,
46261             mmin = math.min,
46262             mabs = math.abs,
46263             j, yValue, height, totalDim, totalNegDim, bottom, top, hasShadow, barAttr, attrs, counter,
46264             shadowIndex, shadow, sprite, offset, floorY;
46265
46266         store.each(function(record, i, total) {
46267             bottom = bounds.zero;
46268             top = bounds.zero;
46269             totalDim = 0;
46270             totalNegDim = 0;
46271             hasShadow = false; 
46272             for (j = 0, counter = 0; j < barsLen; j++) {
46273                 
46274                 if (me.__excludes && me.__excludes[j]) {
46275                     continue;
46276                 }
46277                 yValue = record.get(bounds.bars[j]);
46278                 height = Math.round((yValue - ((bounds.minY < 0) ? 0 : bounds.minY)) * bounds.scale);
46279                 barAttr = {
46280                     fill: colors[(barsLen > 1 ? j : 0) % colorLength]
46281                 };
46282                 if (column) {
46283                     Ext.apply(barAttr, {
46284                         height: height,
46285                         width: mmax(bounds.groupBarWidth, 0),
46286                         x: (bbox.x + xPadding + i * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked),
46287                         y: bottom - height
46288                     });
46289                 }
46290                 else {
46291                     
46292                     offset = (total - 1) - i;
46293                     Ext.apply(barAttr, {
46294                         height: mmax(bounds.groupBarWidth, 0),
46295                         width: height + (bottom == bounds.zero),
46296                         x: bottom + (bottom != bounds.zero),
46297                         y: (bbox.y + yPadding + offset * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked + 1)
46298                     });
46299                 }
46300                 if (height < 0) {
46301                     if (column) {
46302                         barAttr.y = top;
46303                         barAttr.height = mabs(height);
46304                     } else {
46305                         barAttr.x = top + height;
46306                         barAttr.width = mabs(height);
46307                     }
46308                 }
46309                 if (stacked) {
46310                     if (height < 0) {
46311                         top += height * (column ? -1 : 1);
46312                     } else {
46313                         bottom += height * (column ? -1 : 1);
46314                     }
46315                     totalDim += mabs(height);
46316                     if (height < 0) {
46317                         totalNegDim += mabs(height);
46318                     }
46319                 }
46320                 barAttr.x = Math.floor(barAttr.x) + 1;
46321                 floorY = Math.floor(barAttr.y);
46322                 if (!Ext.isIE9 && barAttr.y > floorY) {
46323                     floorY--;
46324                 }
46325                 barAttr.y = floorY;
46326                 barAttr.width = Math.floor(barAttr.width);
46327                 barAttr.height = Math.floor(barAttr.height);
46328                 items.push({
46329                     series: me,
46330                     storeItem: record,
46331                     value: [record.get(me.xField), yValue],
46332                     attr: barAttr,
46333                     point: column ? [barAttr.x + barAttr.width / 2, yValue >= 0 ? barAttr.y : barAttr.y + barAttr.height] :
46334                                     [yValue >= 0 ? barAttr.x + barAttr.width : barAttr.x, barAttr.y + barAttr.height / 2]
46335                 });
46336                 
46337                 if (animate && chart.resizing) {
46338                     attrs = column ? {
46339                         x: barAttr.x,
46340                         y: bounds.zero,
46341                         width: barAttr.width,
46342                         height: 0
46343                     } : {
46344                         x: bounds.zero,
46345                         y: barAttr.y,
46346                         width: 0,
46347                         height: barAttr.height
46348                     };
46349                     if (enableShadows && (stacked && !hasShadow || !stacked)) {
46350                         hasShadow = true;
46351                         
46352                         for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
46353                             shadow = shadowGroups[shadowIndex].getAt(stacked ? i : (i * barsLen + j));
46354                             if (shadow) {
46355                                 shadow.setAttributes(attrs, true);
46356                             }
46357                         }
46358                     }
46359                     
46360                     sprite = group.getAt(i * barsLen + j);
46361                     if (sprite) {
46362                         sprite.setAttributes(attrs, true);
46363                     }
46364                 }
46365                 counter++;
46366             }
46367             if (stacked && items.length) {
46368                 items[i * counter].totalDim = totalDim;
46369                 items[i * counter].totalNegDim = totalNegDim;
46370             }
46371         }, me);
46372     },
46373
46374     
46375     renderShadows: function(i, barAttr, baseAttrs, bounds) {
46376         var me = this,
46377             chart = me.chart,
46378             surface = chart.surface,
46379             animate = chart.animate,
46380             stacked = me.stacked,
46381             shadowGroups = me.shadowGroups,
46382             shadowAttributes = me.shadowAttributes,
46383             shadowGroupsLn = shadowGroups.length,
46384             store = chart.substore || chart.store,
46385             column = me.column,
46386             items = me.items,
46387             shadows = [],
46388             zero = bounds.zero,
46389             shadowIndex, shadowBarAttr, shadow, totalDim, totalNegDim, j, rendererAttributes;
46390
46391         if ((stacked && (i % bounds.groupBarsLen === 0)) || !stacked) {
46392             j = i / bounds.groupBarsLen;
46393             
46394             for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
46395                 shadowBarAttr = Ext.apply({}, shadowAttributes[shadowIndex]);
46396                 shadow = shadowGroups[shadowIndex].getAt(stacked ? j : i);
46397                 Ext.copyTo(shadowBarAttr, barAttr, 'x,y,width,height');
46398                 if (!shadow) {
46399                     shadow = surface.add(Ext.apply({
46400                         type: 'rect',
46401                         group: shadowGroups[shadowIndex]
46402                     }, Ext.apply({}, baseAttrs, shadowBarAttr)));
46403                 }
46404                 if (stacked) {
46405                     totalDim = items[i].totalDim;
46406                     totalNegDim = items[i].totalNegDim;
46407                     if (column) {
46408                         shadowBarAttr.y = zero - totalNegDim;
46409                         shadowBarAttr.height = totalDim;
46410                     }
46411                     else {
46412                         shadowBarAttr.x = zero - totalNegDim;
46413                         shadowBarAttr.width = totalDim;
46414                     }
46415                 }
46416                 if (animate) {
46417                     if (!stacked) {
46418                         rendererAttributes = me.renderer(shadow, store.getAt(j), shadowBarAttr, i, store);
46419                         me.onAnimate(shadow, { to: rendererAttributes });
46420                     }
46421                     else {
46422                         rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: true }), i, store);
46423                         shadow.setAttributes(rendererAttributes, true);
46424                     }
46425                 }
46426                 else {
46427                     rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: false }), i, store);
46428                     shadow.setAttributes(rendererAttributes, true);
46429                 }
46430                 shadows.push(shadow);
46431             }
46432         }
46433         return shadows;
46434     },
46435
46436     
46437     drawSeries: function() {
46438         var me = this,
46439             chart = me.chart,
46440             store = chart.substore || chart.store,
46441             surface = chart.surface,
46442             animate = chart.animate,
46443             stacked = me.stacked,
46444             column = me.column,
46445             enableShadows = chart.shadow,
46446             shadowGroups = me.shadowGroups,
46447             shadowGroupsLn = shadowGroups.length,
46448             group = me.group,
46449             seriesStyle = me.seriesStyle,
46450             items, ln, i, j, baseAttrs, sprite, rendererAttributes, shadowIndex, shadowGroup,
46451             bounds, endSeriesStyle, barAttr, attrs, anim;
46452         
46453         if (!store || !store.getCount()) {
46454             return;
46455         }
46456         
46457         
46458         delete seriesStyle.fill;
46459         endSeriesStyle = Ext.apply(seriesStyle, this.style);
46460         me.unHighlightItem();
46461         me.cleanHighlights();
46462
46463         me.getPaths();
46464         bounds = me.bounds;
46465         items = me.items;
46466
46467         baseAttrs = column ? {
46468             y: bounds.zero,
46469             height: 0
46470         } : {
46471             x: bounds.zero,
46472             width: 0
46473         };
46474         ln = items.length;
46475         
46476         for (i = 0; i < ln; i++) {
46477             sprite = group.getAt(i);
46478             barAttr = items[i].attr;
46479
46480             if (enableShadows) {
46481                 items[i].shadows = me.renderShadows(i, barAttr, baseAttrs, bounds);
46482             }
46483
46484             
46485             if (!sprite) {
46486                 attrs = Ext.apply({}, baseAttrs, barAttr);
46487                 attrs = Ext.apply(attrs, endSeriesStyle || {});
46488                 sprite = surface.add(Ext.apply({}, {
46489                     type: 'rect',
46490                     group: group
46491                 }, attrs));
46492             }
46493             if (animate) {
46494                 rendererAttributes = me.renderer(sprite, store.getAt(i), barAttr, i, store);
46495                 sprite._to = rendererAttributes;
46496                 anim = me.onAnimate(sprite, { to: Ext.apply(rendererAttributes, endSeriesStyle) });
46497                 if (enableShadows && stacked && (i % bounds.barsLen === 0)) {
46498                     j = i / bounds.barsLen;
46499                     for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
46500                         anim.on('afteranimate', function() {
46501                             this.show(true);
46502                         }, shadowGroups[shadowIndex].getAt(j));
46503                     }
46504                 }
46505             }
46506             else {
46507                 rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(barAttr, { hidden: false }), i, store);
46508                 sprite.setAttributes(Ext.apply(rendererAttributes, endSeriesStyle), true);
46509             }
46510             items[i].sprite = sprite;
46511         }
46512
46513         
46514         ln = group.getCount();
46515         for (j = i; j < ln; j++) {
46516             group.getAt(j).hide(true);
46517         }
46518         
46519         if (enableShadows) {
46520             for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
46521                 shadowGroup = shadowGroups[shadowIndex];
46522                 ln = shadowGroup.getCount();
46523                 for (j = i; j < ln; j++) {
46524                     shadowGroup.getAt(j).hide(true);
46525                 }
46526             }
46527         }
46528         me.renderLabels();
46529     },
46530     
46531     
46532     onCreateLabel: function(storeItem, item, i, display) {
46533         var me = this,
46534             surface = me.chart.surface,
46535             group = me.labelsGroup,
46536             config = me.label,
46537             endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle || {}),
46538             sprite;
46539         return surface.add(Ext.apply({
46540             type: 'text',
46541             group: group
46542         }, endLabelStyle || {}));
46543     },
46544     
46545     
46546     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
46547         
46548         
46549         var me = this,
46550             opt = me.bounds,
46551             groupBarWidth = opt.groupBarWidth,
46552             column = me.column,
46553             chart = me.chart,
46554             chartBBox = chart.chartBBox,
46555             resizing = chart.resizing,
46556             xValue = item.value[0],
46557             yValue = item.value[1],
46558             attr = item.attr,
46559             config = me.label,
46560             rotate = config.orientation == 'vertical',
46561             field = [].concat(config.field),
46562             format = config.renderer,
46563             text = format(storeItem.get(field[index])),
46564             size = me.getLabelSize(text),
46565             width = size.width,
46566             height = size.height,
46567             zero = opt.zero,
46568             outside = 'outside',
46569             insideStart = 'insideStart',
46570             insideEnd = 'insideEnd',
46571             offsetX = 10,
46572             offsetY = 6,
46573             signed = opt.signed,
46574             x, y, finalAttr;
46575
46576         label.setAttributes({
46577             text: text
46578         });
46579
46580         if (column) {
46581             if (display == outside) {
46582                 if (height + offsetY + attr.height > (yValue >= 0 ? zero - chartBBox.y : chartBBox.y + chartBBox.height - zero)) {
46583                     display = insideEnd;
46584                 }
46585             } else {
46586                 if (height + offsetY > attr.height) {
46587                     display = outside;
46588                 }
46589             }
46590             x = attr.x + groupBarWidth / 2;
46591             y = display == insideStart ?
46592                     (zero + ((height / 2 + 3) * (yValue >= 0 ? -1 : 1))) :
46593                     (yValue >= 0 ? (attr.y + ((height / 2 + 3) * (display == outside ? -1 : 1))) :
46594                                    (attr.y + attr.height + ((height / 2 + 3) * (display === outside ? 1 : -1))));
46595         }
46596         else {
46597             if (display == outside) {
46598                 if (width + offsetX + attr.width > (yValue >= 0 ? chartBBox.x + chartBBox.width - zero : zero - chartBBox.x)) {
46599                     display = insideEnd;
46600                 }
46601             }
46602             else {
46603                 if (width + offsetX > attr.width) {
46604                     display = outside;
46605                 }
46606             }
46607             x = display == insideStart ?
46608                 (zero + ((width / 2 + 5) * (yValue >= 0 ? 1 : -1))) :
46609                 (yValue >= 0 ? (attr.x + attr.width + ((width / 2 + 5) * (display === outside ? 1 : -1))) :
46610                 (attr.x + ((width / 2 + 5) * (display === outside ? -1 : 1))));
46611             y = attr.y + groupBarWidth / 2;
46612         }
46613         
46614         finalAttr = {
46615             x: x,
46616             y: y
46617         };
46618         
46619         if (rotate) {
46620             finalAttr.rotate = {
46621                 x: x,
46622                 y: y,
46623                 degrees: 270
46624             };
46625         }
46626         
46627         if (animate && resizing) {
46628             if (column) {
46629                 x = attr.x + attr.width / 2;
46630                 y = zero;
46631             } else {
46632                 x = zero;
46633                 y = attr.y + attr.height / 2;
46634             }
46635             label.setAttributes({
46636                 x: x,
46637                 y: y
46638             }, true);
46639             if (rotate) {
46640                 label.setAttributes({
46641                     rotate: {
46642                         x: x,
46643                         y: y,
46644                         degrees: 270
46645                     }
46646                 }, true);
46647             }
46648         }
46649         
46650         if (animate) {
46651             me.onAnimate(label, { to: finalAttr });
46652         }
46653         else {
46654             label.setAttributes(Ext.apply(finalAttr, {
46655                 hidden: false
46656             }), true);
46657         }
46658     },
46659
46660     
46661     getLabelSize: function(value) {
46662         var tester = this.testerLabel,
46663             config = this.label,
46664             endLabelStyle = Ext.apply({}, config, this.seriesLabelStyle || {}),
46665             rotated = config.orientation === 'vertical',
46666             bbox, w, h,
46667             undef;
46668         if (!tester) {
46669             tester = this.testerLabel = this.chart.surface.add(Ext.apply({
46670                 type: 'text',
46671                 opacity: 0
46672             }, endLabelStyle));
46673         }
46674         tester.setAttributes({
46675             text: value
46676         }, true);
46677
46678         
46679         bbox = tester.getBBox();
46680         w = bbox.width;
46681         h = bbox.height;
46682         return {
46683             width: rotated ? h : w,
46684             height: rotated ? w : h
46685         };
46686     },
46687
46688     
46689     onAnimate: function(sprite, attr) {
46690         sprite.show();
46691         return this.callParent(arguments);
46692     },
46693     
46694     isItemInPoint: function(x, y, item) {
46695         var bbox = item.sprite.getBBox();
46696         return bbox.x <= x && bbox.y <= y
46697             && (bbox.x + bbox.width) >= x
46698             && (bbox.y + bbox.height) >= y;
46699     },
46700     
46701     
46702     hideAll: function() {
46703         var axes = this.chart.axes;
46704         if (!isNaN(this._index)) {
46705             if (!this.__excludes) {
46706                 this.__excludes = [];
46707             }
46708             this.__excludes[this._index] = true;
46709             this.drawSeries();
46710             axes.each(function(axis) {
46711                 axis.drawAxis();
46712             });
46713         }
46714     },
46715
46716     
46717     showAll: function() {
46718         var axes = this.chart.axes;
46719         if (!isNaN(this._index)) {
46720             if (!this.__excludes) {
46721                 this.__excludes = [];
46722             }
46723             this.__excludes[this._index] = false;
46724             this.drawSeries();
46725             axes.each(function(axis) {
46726                 axis.drawAxis();
46727             });
46728         }
46729     },
46730     
46731     
46732     getLegendColor: function(index) {
46733         var me = this;
46734         return me.colorArrayStyle[index % me.colorArrayStyle.length];
46735     }
46736 });
46737
46738
46739 Ext.define('Ext.chart.series.Column', {
46740
46741     
46742
46743     alternateClassName: ['Ext.chart.ColumnSeries', 'Ext.chart.ColumnChart', 'Ext.chart.StackedColumnChart'],
46744
46745     extend: 'Ext.chart.series.Bar',
46746
46747     
46748
46749     type: 'column',
46750     alias: 'series.column',
46751
46752     column: true,
46753
46754     
46755     xPadding: 10,
46756
46757     
46758     yPadding: 0
46759 });
46760
46761 Ext.define('Ext.chart.series.Gauge', {
46762
46763     
46764
46765     extend: 'Ext.chart.series.Series',
46766
46767     
46768
46769     type: "gauge",
46770     alias: 'series.gauge',
46771
46772     rad: Math.PI / 180,
46773
46774     
46775     highlightDuration: 150,
46776
46777     
46778     angleField: false,
46779
46780     
46781     needle: false,
46782     
46783     
46784     donut: false,
46785
46786     
46787     showInLegend: false,
46788
46789     
46790     style: {},
46791     
46792     constructor: function(config) {
46793         this.callParent(arguments);
46794         var me = this,
46795             chart = me.chart,
46796             surface = chart.surface,
46797             store = chart.store,
46798             shadow = chart.shadow, i, l, cfg;
46799         Ext.apply(me, config, {
46800             shadowAttributes: [{
46801                 "stroke-width": 6,
46802                 "stroke-opacity": 1,
46803                 stroke: 'rgb(200, 200, 200)',
46804                 translate: {
46805                     x: 1.2,
46806                     y: 2
46807                 }
46808             },
46809             {
46810                 "stroke-width": 4,
46811                 "stroke-opacity": 1,
46812                 stroke: 'rgb(150, 150, 150)',
46813                 translate: {
46814                     x: 0.9,
46815                     y: 1.5
46816                 }
46817             },
46818             {
46819                 "stroke-width": 2,
46820                 "stroke-opacity": 1,
46821                 stroke: 'rgb(100, 100, 100)',
46822                 translate: {
46823                     x: 0.6,
46824                     y: 1
46825                 }
46826             }]
46827         });
46828         me.group = surface.getGroup(me.seriesId);
46829         if (shadow) {
46830             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
46831                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
46832             }
46833         }
46834         surface.customAttributes.segment = function(opt) {
46835             return me.getSegment(opt);
46836         };
46837     },
46838     
46839     //@private updates some onbefore render parameters.
46840
46841     initialize: function() {
46842         var me = this,
46843             store = me.chart.substore || me.chart.store;
46844         
46845         me.yField = [];
46846         if (me.label.field) {
46847             store.each(function(rec) {
46848                 me.yField.push(rec.get(me.label.field));
46849             });
46850         }
46851     },
46852
46853     
46854     getSegment: function(opt) {
46855         var me = this,
46856             rad = me.rad,
46857             cos = Math.cos,
46858             sin = Math.sin,
46859             abs = Math.abs,
46860             x = me.centerX,
46861             y = me.centerY,
46862             x1 = 0, x2 = 0, x3 = 0, x4 = 0,
46863             y1 = 0, y2 = 0, y3 = 0, y4 = 0,
46864             delta = 1e-2,
46865             r = opt.endRho - opt.startRho,
46866             startAngle = opt.startAngle,
46867             endAngle = opt.endAngle,
46868             midAngle = (startAngle + endAngle) / 2 * rad,
46869             margin = opt.margin || 0,
46870             flag = abs(endAngle - startAngle) > 180,
46871             a1 = Math.min(startAngle, endAngle) * rad,
46872             a2 = Math.max(startAngle, endAngle) * rad,
46873             singleSlice = false;
46874
46875         x += margin * cos(midAngle);
46876         y += margin * sin(midAngle);
46877
46878         x1 = x + opt.startRho * cos(a1);
46879         y1 = y + opt.startRho * sin(a1);
46880
46881         x2 = x + opt.endRho * cos(a1);
46882         y2 = y + opt.endRho * sin(a1);
46883
46884         x3 = x + opt.startRho * cos(a2);
46885         y3 = y + opt.startRho * sin(a2);
46886
46887         x4 = x + opt.endRho * cos(a2);
46888         y4 = y + opt.endRho * sin(a2);
46889
46890         if (abs(x1 - x3) <= delta && abs(y1 - y3) <= delta) {
46891             singleSlice = true;
46892         }
46893         
46894         if (singleSlice) {
46895             return {
46896                 path: [
46897                 ["M", x1, y1],
46898                 ["L", x2, y2],
46899                 ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
46900                 ["Z"]]
46901             };
46902         } else {
46903             return {
46904                 path: [
46905                 ["M", x1, y1],
46906                 ["L", x2, y2],
46907                 ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
46908                 ["L", x3, y3],
46909                 ["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
46910                 ["Z"]]
46911             };
46912         }
46913     },
46914
46915     
46916     calcMiddle: function(item) {
46917         var me = this,
46918             rad = me.rad,
46919             slice = item.slice,
46920             x = me.centerX,
46921             y = me.centerY,
46922             startAngle = slice.startAngle,
46923             endAngle = slice.endAngle,
46924             radius = Math.max(('rho' in slice) ? slice.rho: me.radius, me.label.minMargin),
46925             donut = +me.donut,
46926             a1 = Math.min(startAngle, endAngle) * rad,
46927             a2 = Math.max(startAngle, endAngle) * rad,
46928             midAngle = -(a1 + (a2 - a1) / 2),
46929             xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle),
46930             ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle);
46931
46932         item.middle = {
46933             x: xm,
46934             y: ym
46935         };
46936     },
46937
46938     
46939     drawSeries: function() {
46940         var me = this,
46941             chart = me.chart,
46942             store = chart.substore || chart.store,
46943             group = me.group,
46944             animate = me.chart.animate,
46945             axis = me.chart.axes.get(0),
46946             minimum = axis && axis.minimum || me.minimum || 0,
46947             maximum = axis && axis.maximum || me.maximum || 0,
46948             field = me.angleField || me.field || me.xField,
46949             surface = chart.surface,
46950             chartBBox = chart.chartBBox,
46951             rad = me.rad,
46952             donut = +me.donut,
46953             values = {},
46954             items = [],
46955             seriesStyle = me.seriesStyle,
46956             seriesLabelStyle = me.seriesLabelStyle,
46957             colorArrayStyle = me.colorArrayStyle,
46958             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
46959             gutterX = chart.maxGutter[0],
46960             gutterY = chart.maxGutter[1],
46961             cos = Math.cos,
46962             sin = Math.sin,
46963             rendererAttributes, centerX, centerY, slice, slices, sprite, value,
46964             item, ln, record, i, j, startAngle, endAngle, middleAngle, sliceLength, path,
46965             p, spriteOptions, bbox, splitAngle, sliceA, sliceB;
46966         
46967         Ext.apply(seriesStyle, me.style || {});
46968
46969         me.setBBox();
46970         bbox = me.bbox;
46971
46972         
46973         if (me.colorSet) {
46974             colorArrayStyle = me.colorSet;
46975             colorArrayLength = colorArrayStyle.length;
46976         }
46977         
46978         
46979         if (!store || !store.getCount()) {
46980             return;
46981         }
46982         
46983         centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
46984         centerY = me.centerY = chartBBox.y + chartBBox.height;
46985         me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
46986         me.slices = slices = [];
46987         me.items = items = [];
46988         
46989         if (!me.value) {
46990             record = store.getAt(0);
46991             me.value = record.get(field);
46992         }
46993         
46994         value = me.value;
46995         if (me.needle) {
46996             sliceA = {
46997                 series: me,
46998                 value: value,
46999                 startAngle: -180,
47000                 endAngle: 0,
47001                 rho: me.radius
47002             };
47003             splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
47004             slices.push(sliceA);
47005         } else {
47006             splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
47007             sliceA = {
47008                 series: me,
47009                 value: value,
47010                 startAngle: -180,
47011                 endAngle: splitAngle,
47012                 rho: me.radius
47013             };
47014             sliceB = {
47015                 series: me,
47016                 value: me.maximum - value,
47017                 startAngle: splitAngle,
47018                 endAngle: 0,
47019                 rho: me.radius
47020             };
47021             slices.push(sliceA, sliceB);
47022         }
47023         
47024         
47025         for (i = 0, ln = slices.length; i < ln; i++) {
47026             slice = slices[i];
47027             sprite = group.getAt(i);
47028             
47029             rendererAttributes = Ext.apply({
47030                 segment: {
47031                     startAngle: slice.startAngle,
47032                     endAngle: slice.endAngle,
47033                     margin: 0,
47034                     rho: slice.rho,
47035                     startRho: slice.rho * +donut / 100,
47036                     endRho: slice.rho
47037                 } 
47038             }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
47039
47040             item = Ext.apply({},
47041             rendererAttributes.segment, {
47042                 slice: slice,
47043                 series: me,
47044                 storeItem: record,
47045                 index: i
47046             });
47047             items[i] = item;
47048             
47049             if (!sprite) {
47050                 spriteOptions = Ext.apply({
47051                     type: "path",
47052                     group: group
47053                 }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
47054                 sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
47055             }
47056             slice.sprite = slice.sprite || [];
47057             item.sprite = sprite;
47058             slice.sprite.push(sprite);
47059             if (animate) {
47060                 rendererAttributes = me.renderer(sprite, record, rendererAttributes, i, store);
47061                 sprite._to = rendererAttributes;
47062                 me.onAnimate(sprite, {
47063                     to: rendererAttributes
47064                 });
47065             } else {
47066                 rendererAttributes = me.renderer(sprite, record, Ext.apply(rendererAttributes, {
47067                     hidden: false
47068                 }), i, store);
47069                 sprite.setAttributes(rendererAttributes, true);
47070             }
47071         }
47072         
47073         if (me.needle) {
47074             splitAngle = splitAngle * Math.PI / 180;
47075             
47076             if (!me.needleSprite) {
47077                 me.needleSprite = me.chart.surface.add({
47078                     type: 'path',
47079                     path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
47080                                 centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
47081                            'L', centerX + me.radius * cos(splitAngle),
47082                                 centerY + -Math.abs(me.radius * sin(splitAngle))],
47083                     'stroke-width': 4,
47084                     'stroke': '#222'
47085                 });
47086             } else {
47087                 if (animate) {
47088                     me.onAnimate(me.needleSprite, {
47089                         to: {
47090                         path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
47091                                     centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
47092                                'L', centerX + me.radius * cos(splitAngle),
47093                                     centerY + -Math.abs(me.radius * sin(splitAngle))]
47094                         }
47095                     });
47096                 } else {
47097                     me.needleSprite.setAttributes({
47098                         type: 'path',
47099                         path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
47100                                     centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
47101                                'L', centerX + me.radius * cos(splitAngle),
47102                                     centerY + -Math.abs(me.radius * sin(splitAngle))]
47103                     });
47104                 }
47105             }
47106             me.needleSprite.setAttributes({
47107                 hidden: false    
47108             }, true);
47109         }
47110         
47111         delete me.value;
47112     },
47113     
47114     
47115     setValue: function (value) {
47116         this.value = value;
47117         this.drawSeries();
47118     },
47119
47120     
47121     onCreateLabel: function(storeItem, item, i, display) {},
47122
47123     
47124     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {},
47125
47126     
47127     onPlaceCallout: function() {},
47128
47129     
47130     onAnimate: function(sprite, attr) {
47131         sprite.show();
47132         return this.callParent(arguments);
47133     },
47134
47135     isItemInPoint: function(x, y, item, i) {
47136         return false;
47137     },
47138     
47139     
47140     showAll: function() {
47141         if (!isNaN(this._index)) {
47142             this.__excludes[this._index] = false;
47143             this.drawSeries();
47144         }
47145     },
47146     
47147     
47148     getLegendColor: function(index) {
47149         var me = this;
47150         return me.colorArrayStyle[index % me.colorArrayStyle.length];
47151     }
47152 });
47153
47154
47155
47156
47157 Ext.define('Ext.chart.series.Line', {
47158
47159     
47160
47161     extend: 'Ext.chart.series.Cartesian',
47162
47163     alternateClassName: ['Ext.chart.LineSeries', 'Ext.chart.LineChart'],
47164
47165     requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.draw.Draw', 'Ext.fx.Anim'],
47166
47167     
47168
47169     type: 'line',
47170     
47171     alias: 'series.line',
47172
47173     
47174     selectionTolerance: 20,
47175     
47176     
47177     showMarkers: true,
47178
47179     
47180     markerConfig: {},
47181
47182     
47183     style: {},
47184     
47185     
47186     smooth: false,
47187
47188     
47189     fill: false,
47190
47191     constructor: function(config) {
47192         this.callParent(arguments);
47193         var me = this,
47194             surface = me.chart.surface,
47195             shadow = me.chart.shadow,
47196             i, l;
47197         Ext.apply(me, config, {
47198             highlightCfg: {
47199                 'stroke-width': 3
47200             },
47201             shadowAttributes: [{
47202                 "stroke-width": 6,
47203                 "stroke-opacity": 0.05,
47204                 stroke: 'rgb(0, 0, 0)',
47205                 translate: {
47206                     x: 1,
47207                     y: 1
47208                 }
47209             }, {
47210                 "stroke-width": 4,
47211                 "stroke-opacity": 0.1,
47212                 stroke: 'rgb(0, 0, 0)',
47213                 translate: {
47214                     x: 1,
47215                     y: 1
47216                 }
47217             }, {
47218                 "stroke-width": 2,
47219                 "stroke-opacity": 0.15,
47220                 stroke: 'rgb(0, 0, 0)',
47221                 translate: {
47222                     x: 1,
47223                     y: 1
47224                 }
47225             }]
47226         });
47227         me.group = surface.getGroup(me.seriesId);
47228         if (me.showMarkers) {
47229             me.markerGroup = surface.getGroup(me.seriesId + '-markers');
47230         }
47231         if (shadow) {
47232             for (i = 0, l = this.shadowAttributes.length; i < l; i++) {
47233                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
47234             }
47235         }
47236     },
47237     
47238     
47239     shrink: function(xValues, yValues, size) {
47240         
47241         var len = xValues.length,
47242             ratio = Math.floor(len / size),
47243             i = 1,
47244             xSum = 0,
47245             ySum = 0,
47246             xRes = [xValues[0]],
47247             yRes = [yValues[0]];
47248         
47249         for (; i < len; ++i) {
47250             xSum += xValues[i] || 0;
47251             ySum += yValues[i] || 0;
47252             if (i % ratio == 0) {
47253                 xRes.push(xSum/ratio);
47254                 yRes.push(ySum/ratio);
47255                 xSum = 0;
47256                 ySum = 0;
47257             }
47258         }
47259         return {
47260             x: xRes,
47261             y: yRes
47262         };
47263     },
47264
47265     
47266     drawSeries: function() {
47267         var me = this,
47268             chart = me.chart,
47269             store = chart.substore || chart.store,
47270             surface = chart.surface,
47271             chartBBox = chart.chartBBox,
47272             bbox = {},
47273             group = me.group,
47274             gutterX = chart.maxGutter[0],
47275             gutterY = chart.maxGutter[1],
47276             showMarkers = me.showMarkers,
47277             markerGroup = me.markerGroup,
47278             enableShadows = chart.shadow,
47279             shadowGroups = me.shadowGroups,
47280             shadowAttributes = this.shadowAttributes,
47281             lnsh = shadowGroups.length,
47282             dummyPath = ["M"],
47283             path = ["M"],
47284             markerIndex = chart.markerIndex,
47285             axes = [].concat(me.axis),
47286             shadowGroup,
47287             shadowBarAttr,
47288             xValues = [],
47289             yValues = [],
47290             onbreak = false,
47291             markerStyle = me.markerStyle,
47292             seriesStyle = me.seriesStyle,
47293             seriesLabelStyle = me.seriesLabelStyle,
47294             colorArrayStyle = me.colorArrayStyle,
47295             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
47296             seriesIdx = me.seriesIdx, shadows, shadow, shindex, fromPath, fill, fillPath, rendererAttributes,
47297             x, y, prevX, prevY, firstY, markerCount, i, j, ln, axis, ends, marker, markerAux, item, xValue,
47298             yValue, coords, xScale, yScale, minX, maxX, minY, maxY, line, animation, endMarkerStyle,
47299             endLineStyle, type, props, firstMarker;
47300         
47301         
47302         if (!store || !store.getCount()) {
47303             return;
47304         }
47305         
47306         
47307         endMarkerStyle = Ext.apply(markerStyle, me.markerConfig);
47308         type = endMarkerStyle.type;
47309         delete endMarkerStyle.type;
47310         endLineStyle = Ext.apply(seriesStyle, me.style);
47311         
47312         
47313         if (!endLineStyle['stroke-width']) {
47314             endLineStyle['stroke-width'] = 0.5;
47315         }
47316         
47317         
47318         if (markerIndex && markerGroup && markerGroup.getCount()) {
47319             for (i = 0; i < markerIndex; i++) {
47320                 marker = markerGroup.getAt(i);
47321                 markerGroup.remove(marker);
47322                 markerGroup.add(marker);
47323                 markerAux = markerGroup.getAt(markerGroup.getCount() - 2);
47324                 marker.setAttributes({
47325                     x: 0,
47326                     y: 0,
47327                     translate: {
47328                         x: markerAux.attr.translation.x,
47329                         y: markerAux.attr.translation.y
47330                     }
47331                 }, true);
47332             }
47333         }
47334         
47335         me.unHighlightItem();
47336         me.cleanHighlights();
47337
47338         me.setBBox();
47339         bbox = me.bbox;
47340
47341         me.clipRect = [bbox.x, bbox.y, bbox.width, bbox.height];
47342
47343         for (i = 0, ln = axes.length; i < ln; i++) { 
47344             axis = chart.axes.get(axes[i]);
47345             if (axis) {
47346                 ends = axis.calcEnds();
47347                 if (axis.position == 'top' || axis.position == 'bottom') {
47348                     minX = ends.from;
47349                     maxX = ends.to;
47350                 }
47351                 else {
47352                     minY = ends.from;
47353                     maxY = ends.to;
47354                 }
47355             }
47356         }
47357         
47358         
47359         
47360         if (me.xField && !Ext.isNumber(minX)
47361             && (me.axis == 'bottom' || me.axis == 'top')) {
47362             axis = Ext.create('Ext.chart.axis.Axis', {
47363                 chart: chart,
47364                 fields: [].concat(me.xField)
47365             }).calcEnds();
47366             minX = axis.from;
47367             maxX = axis.to;
47368         }
47369         if (me.yField && !Ext.isNumber(minY)
47370             && (me.axis == 'right' || me.axis == 'left')) {
47371             axis = Ext.create('Ext.chart.axis.Axis', {
47372                 chart: chart,
47373                 fields: [].concat(me.yField)
47374             }).calcEnds();
47375             minY = axis.from;
47376             maxY = axis.to;
47377         }
47378
47379         if (isNaN(minX)) {
47380             minX = 0;
47381             xScale = bbox.width / (store.getCount() - 1);
47382         }
47383         else {
47384             xScale = bbox.width / (maxX - minX);
47385         }
47386
47387         if (isNaN(minY)) {
47388             minY = 0;
47389             yScale = bbox.height / (store.getCount() - 1);
47390         } 
47391         else {
47392             yScale = bbox.height / (maxY - minY);
47393         }
47394
47395         store.each(function(record, i) {
47396             xValue = record.get(me.xField);
47397             yValue = record.get(me.yField);
47398             
47399             if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
47400                 if (Ext.isDefined(Ext.global.console)) {
47401                     Ext.global.console.warn("[Ext.chart.series.Line]  Skipping a store element with an undefined value at ", record, xValue, yValue);
47402                 }
47403                 return;
47404             }
47405             
47406             if (typeof xValue == 'string' || typeof xValue == 'object'
47407                 
47408                 || (me.axis != 'top' && me.axis != 'bottom')) {
47409                 xValue = i;
47410             }
47411             if (typeof yValue == 'string' || typeof yValue == 'object'
47412                 
47413                 || (me.axis != 'left' && me.axis != 'right')) {
47414                 yValue = i;
47415             }
47416             xValues.push(xValue);
47417             yValues.push(yValue);
47418         }, me);
47419
47420         ln = xValues.length;
47421         if (ln > bbox.width) {
47422             coords = me.shrink(xValues, yValues, bbox.width);
47423             xValues = coords.x;
47424             yValues = coords.y;
47425         }
47426
47427         me.items = [];
47428
47429         ln = xValues.length;
47430         for (i = 0; i < ln; i++) {
47431             xValue = xValues[i];
47432             yValue = yValues[i];
47433             if (yValue === false) {
47434                 if (path.length == 1) {
47435                     path = [];
47436                 }
47437                 onbreak = true;
47438                 me.items.push(false);
47439                 continue;
47440             } else {
47441                 x = (bbox.x + (xValue - minX) * xScale).toFixed(2);
47442                 y = ((bbox.y + bbox.height) - (yValue - minY) * yScale).toFixed(2);
47443                 if (onbreak) {
47444                     onbreak = false;
47445                     path.push('M');
47446                 } 
47447                 path = path.concat([x, y]);
47448             }
47449             if ((typeof firstY == 'undefined') && (typeof y != 'undefined')) {
47450                 firstY = y;
47451             }
47452             
47453             if (!me.line || chart.resizing) {
47454                 dummyPath = dummyPath.concat([x, bbox.y + bbox.height / 2]);
47455             }
47456
47457             
47458             if (chart.animate && chart.resizing && me.line) {
47459                 me.line.setAttributes({
47460                     path: dummyPath
47461                 }, true);
47462                 if (me.fillPath) {
47463                     me.fillPath.setAttributes({
47464                         path: dummyPath,
47465                         opacity: 0.2
47466                     }, true);
47467                 }
47468                 if (me.line.shadows) {
47469                     shadows = me.line.shadows;
47470                     for (j = 0, lnsh = shadows.length; j < lnsh; j++) {
47471                         shadow = shadows[j];
47472                         shadow.setAttributes({
47473                             path: dummyPath
47474                         }, true);
47475                     }
47476                 }
47477             }
47478             if (showMarkers) {
47479                 marker = markerGroup.getAt(i);
47480                 if (!marker) {
47481                     marker = Ext.chart.Shape[type](surface, Ext.apply({
47482                         group: [group, markerGroup],
47483                         x: 0, y: 0,
47484                         translate: {
47485                             x: prevX || x, 
47486                             y: prevY || (bbox.y + bbox.height / 2)
47487                         },
47488                         value: '"' + xValue + ', ' + yValue + '"'
47489                     }, endMarkerStyle));
47490                     marker._to = {
47491                         translate: {
47492                             x: x,
47493                             y: y
47494                         }
47495                     };
47496                 } else {
47497                     marker.setAttributes({
47498                         value: '"' + xValue + ', ' + yValue + '"',
47499                         x: 0, y: 0,
47500                         hidden: false
47501                     }, true);
47502                     marker._to = {
47503                         translate: {
47504                             x: x, y: y
47505                         }
47506                     };
47507                 }
47508             }
47509             me.items.push({
47510                 series: me,
47511                 value: [xValue, yValue],
47512                 point: [x, y],
47513                 sprite: marker,
47514                 storeItem: store.getAt(i)
47515             });
47516             prevX = x;
47517             prevY = y;
47518         }
47519         
47520         if (path.length <= 1) {
47521             
47522             return;    
47523         }
47524         
47525         if (me.smooth) {
47526             path = Ext.draw.Draw.smooth(path, 6);
47527         }
47528         
47529         
47530         if (chart.markerIndex && me.previousPath) {
47531             fromPath = me.previousPath;
47532             fromPath.splice(1, 2);
47533         } else {
47534             fromPath = path;
47535         }
47536
47537         
47538         if (!me.line) {
47539             me.line = surface.add(Ext.apply({
47540                 type: 'path',
47541                 group: group,
47542                 path: dummyPath,
47543                 stroke: endLineStyle.stroke || endLineStyle.fill
47544             }, endLineStyle || {}));
47545             
47546             me.line.setAttributes({
47547                 fill: 'none'
47548             });
47549             if (!endLineStyle.stroke && colorArrayLength) {
47550                 me.line.setAttributes({
47551                     stroke: colorArrayStyle[seriesIdx % colorArrayLength]
47552                 }, true);
47553             }
47554             if (enableShadows) {
47555                 
47556                 shadows = me.line.shadows = [];                
47557                 for (shindex = 0; shindex < lnsh; shindex++) {
47558                     shadowBarAttr = shadowAttributes[shindex];
47559                     shadowBarAttr = Ext.apply({}, shadowBarAttr, { path: dummyPath });
47560                     shadow = chart.surface.add(Ext.apply({}, {
47561                         type: 'path',
47562                         group: shadowGroups[shindex]
47563                     }, shadowBarAttr));
47564                     shadows.push(shadow);
47565                 }
47566             }
47567         }
47568         if (me.fill) {
47569             fillPath = path.concat([
47570                 ["L", x, bbox.y + bbox.height],
47571                 ["L", bbox.x, bbox.y + bbox.height],
47572                 ["L", bbox.x, firstY]
47573             ]);
47574             if (!me.fillPath) {
47575                 me.fillPath = surface.add({
47576                     group: group,
47577                     type: 'path',
47578                     opacity: endLineStyle.opacity || 0.3,
47579                     fill: colorArrayStyle[seriesIdx % colorArrayLength] || endLineStyle.fill,
47580                     path: dummyPath
47581                 });
47582             }
47583         }
47584         markerCount = showMarkers && markerGroup.getCount();
47585         if (chart.animate) {
47586             fill = me.fill;
47587             line = me.line;
47588             
47589             rendererAttributes = me.renderer(line, false, { path: path }, i, store);
47590             Ext.apply(rendererAttributes, endLineStyle || {}, {
47591                 stroke: endLineStyle.stroke || endLineStyle.fill
47592             });
47593             
47594             delete rendererAttributes.fill;
47595             if (chart.markerIndex && me.previousPath) {
47596                 me.animation = animation = me.onAnimate(line, {
47597                     to: rendererAttributes,
47598                     from: {
47599                         path: fromPath
47600                     }
47601                 });
47602             } else {
47603                 me.animation = animation = me.onAnimate(line, {
47604                     to: rendererAttributes
47605                 });
47606             }
47607             
47608             if (enableShadows) {
47609                 shadows = line.shadows;
47610                 for(j = 0; j < lnsh; j++) {
47611                     if (chart.markerIndex && me.previousPath) {
47612                         me.onAnimate(shadows[j], {
47613                             to: { path: path },
47614                             from: { path: fromPath }
47615                         });
47616                     } else {
47617                         me.onAnimate(shadows[j], {
47618                             to: { path: path }
47619                         });
47620                     }
47621                 }
47622             }
47623             
47624             if (fill) {
47625                 me.onAnimate(me.fillPath, {
47626                     to: Ext.apply({}, {
47627                         path: fillPath,
47628                         fill: colorArrayStyle[seriesIdx % colorArrayLength] || endLineStyle.fill
47629                     }, endLineStyle || {})
47630                 });
47631             }
47632             
47633             if (showMarkers) {
47634                 for(i = 0; i < ln; i++) {
47635                     item = markerGroup.getAt(i);
47636                     if (item) {
47637                         if (me.items[i]) {
47638                             rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
47639                             me.onAnimate(item, {
47640                                 to: Ext.apply(rendererAttributes, endMarkerStyle || {})
47641                             });
47642                         } else {
47643                             item.setAttributes(Ext.apply({
47644                                 hidden: true 
47645                             }, item._to), true);
47646                         }
47647                     }
47648                 }
47649                 for(; i < markerCount; i++) {
47650                     item = markerGroup.getAt(i);
47651                     item.hide(true);
47652                 }
47653
47654
47655
47656
47657             }
47658         } else {
47659             rendererAttributes = me.renderer(me.line, false, { path: path, hidden: false }, i, store);
47660             Ext.apply(rendererAttributes, endLineStyle || {}, {
47661                 stroke: endLineStyle.stroke || endLineStyle.fill
47662             });
47663             
47664             delete rendererAttributes.fill;
47665             me.line.setAttributes(rendererAttributes, true);
47666             
47667             if (enableShadows) {
47668                 shadows = me.line.shadows;
47669                 for(j = 0; j < lnsh; j++) {
47670                     shadows[j].setAttributes({
47671                         path: path
47672                     }, true);
47673                 }
47674             }
47675             if (me.fill) {
47676                 me.fillPath.setAttributes({
47677                     path: fillPath
47678                 }, true);
47679             }
47680             if (showMarkers) {
47681                 for(i = 0; i < ln; i++) {
47682                     item = markerGroup.getAt(i);
47683                     if (item) {
47684                         if (me.items[i]) {
47685                             rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
47686                             item.setAttributes(Ext.apply(endMarkerStyle || {}, rendererAttributes || {}), true);
47687                         } else {
47688                             item.hide(true);
47689                         }
47690                     }
47691                 }
47692                 for(; i < markerCount; i++) {
47693                     item = markerGroup.getAt(i);
47694                     item.hide(true);
47695                 }
47696             }
47697         }
47698
47699         if (chart.markerIndex) {
47700             path.splice(1, 0, path[1], path[2]);
47701             me.previousPath = path;
47702         }
47703         me.renderLabels();
47704         me.renderCallouts();
47705     },
47706     
47707     
47708     onCreateLabel: function(storeItem, item, i, display) {
47709         var me = this,
47710             group = me.labelsGroup,
47711             config = me.label,
47712             bbox = me.bbox,
47713             endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
47714
47715         return me.chart.surface.add(Ext.apply({
47716             'type': 'text',
47717             'text-anchor': 'middle',
47718             'group': group,
47719             'x': item.point[0],
47720             'y': bbox.y + bbox.height / 2
47721         }, endLabelStyle || {}));
47722     },
47723     
47724     
47725     onPlaceLabel: function(label, storeItem, item, i, display, animate) {
47726         var me = this,
47727             chart = me.chart,
47728             resizing = chart.resizing,
47729             config = me.label,
47730             format = config.renderer,
47731             field = config.field,
47732             bbox = me.bbox,
47733             x = item.point[0],
47734             y = item.point[1],
47735             radius = item.sprite.attr.radius,
47736             bb, width, height;
47737         
47738         label.setAttributes({
47739             text: format(storeItem.get(field)),
47740             hidden: true
47741         }, true);
47742         
47743         if (display == 'rotate') {
47744             label.setAttributes({
47745                 'text-anchor': 'start',
47746                 'rotation': {
47747                     x: x,
47748                     y: y,
47749                     degrees: -45
47750                 }
47751             }, true);
47752             
47753             bb = label.getBBox();
47754             width = bb.width;
47755             height = bb.height;
47756             x = x < bbox.x? bbox.x : x;
47757             x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
47758             y = (y - height < bbox.y)? bbox.y + height : y;
47759         
47760         } else if (display == 'under' || display == 'over') {
47761             
47762             bb = item.sprite.getBBox();
47763             bb.width = bb.width || (radius * 2);
47764             bb.height = bb.height || (radius * 2);
47765             y = y + (display == 'over'? -bb.height : bb.height);
47766             
47767             bb = label.getBBox();
47768             width = bb.width/2;
47769             height = bb.height/2;
47770             x = x - width < bbox.x? bbox.x + width : x;
47771             x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
47772             y = y - height < bbox.y? bbox.y + height : y;
47773             y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
47774         }
47775         
47776         if (me.chart.animate && !me.chart.resizing) {
47777             label.show(true);
47778             me.onAnimate(label, {
47779                 to: {
47780                     x: x,
47781                     y: y
47782                 }
47783             });
47784         } else {
47785             label.setAttributes({
47786                 x: x,
47787                 y: y
47788             }, true);
47789             if (resizing) {
47790                 me.animation.on('afteranimate', function() {
47791                     label.show(true);
47792                 });
47793             } else {
47794                 label.show(true);
47795             }
47796         }
47797     },
47798
47799     //@private Overriding highlights.js highlightItem method.
47800
47801     highlightItem: function() {
47802         var me = this;
47803         me.callParent(arguments);
47804         if (this.line && !this.highlighted) {
47805             if (!('__strokeWidth' in this.line)) {
47806                 this.line.__strokeWidth = this.line.attr['stroke-width'] || 0;
47807             }
47808             if (this.line.__anim) {
47809                 this.line.__anim.paused = true;
47810             }
47811             this.line.__anim = Ext.create('Ext.fx.Anim', {
47812                 target: this.line,
47813                 to: {
47814                     'stroke-width': this.line.__strokeWidth + 3
47815                 }
47816             });
47817             this.highlighted = true;
47818         }
47819     },
47820
47821     //@private Overriding highlights.js unHighlightItem method.
47822
47823     unHighlightItem: function() {
47824         var me = this;
47825         me.callParent(arguments);
47826         if (this.line && this.highlighted) {
47827             this.line.__anim = Ext.create('Ext.fx.Anim', {
47828                 target: this.line,
47829                 to: {
47830                     'stroke-width': this.line.__strokeWidth
47831                 }
47832             });
47833             this.highlighted = false;
47834         }
47835     },
47836
47837     //@private called when a callout needs to be placed.
47838
47839     onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
47840         if (!display) {
47841             return;
47842         }
47843         
47844         var me = this,
47845             chart = me.chart,
47846             surface = chart.surface,
47847             resizing = chart.resizing,
47848             config = me.callouts,
47849             items = me.items,
47850             prev = i == 0? false : items[i -1].point,
47851             next = (i == items.length -1)? false : items[i +1].point,
47852             cur = [+item.point[0], +item.point[1]],
47853             dir, norm, normal, a, aprev, anext,
47854             offsetFromViz = config.offsetFromViz || 30,
47855             offsetToSide = config.offsetToSide || 10,
47856             offsetBox = config.offsetBox || 3,
47857             boxx, boxy, boxw, boxh,
47858             p, clipRect = me.clipRect,
47859             bbox = {
47860                 width: config.styles.width || 10,
47861                 height: config.styles.height || 10
47862             },
47863             x, y;
47864
47865         
47866         if (!prev) {
47867             prev = cur;
47868         }
47869         if (!next) {
47870             next = cur;
47871         }
47872         a = (next[1] - prev[1]) / (next[0] - prev[0]);
47873         aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
47874         anext = (next[1] - cur[1]) / (next[0] - cur[0]);
47875         
47876         norm = Math.sqrt(1 + a * a);
47877         dir = [1 / norm, a / norm];
47878         normal = [-dir[1], dir[0]];
47879         
47880         
47881         if (aprev > 0 && anext < 0 && normal[1] < 0
47882             || aprev < 0 && anext > 0 && normal[1] > 0) {
47883             normal[0] *= -1;
47884             normal[1] *= -1;
47885         } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0
47886                    || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
47887             normal[0] *= -1;
47888             normal[1] *= -1;
47889         }
47890         
47891         x = cur[0] + normal[0] * offsetFromViz;
47892         y = cur[1] + normal[1] * offsetFromViz;
47893
47894         
47895         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
47896         boxy = y - bbox.height /2 - offsetBox;
47897         boxw = bbox.width + 2 * offsetBox;
47898         boxh = bbox.height + 2 * offsetBox;
47899         
47900         
47901         
47902         if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
47903             normal[0] *= -1;
47904         }
47905         if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
47906             normal[1] *= -1;
47907         }
47908
47909         
47910         x = cur[0] + normal[0] * offsetFromViz;
47911         y = cur[1] + normal[1] * offsetFromViz;
47912         
47913         
47914         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
47915         boxy = y - bbox.height /2 - offsetBox;
47916         boxw = bbox.width + 2 * offsetBox;
47917         boxh = bbox.height + 2 * offsetBox;
47918         
47919         if (chart.animate) {
47920             
47921             me.onAnimate(callout.lines, {
47922                 to: {
47923                     path: ["M", cur[0], cur[1], "L", x, y, "Z"]
47924                 }
47925             });
47926             
47927             if (callout.panel) {
47928                 callout.panel.setPosition(boxx, boxy, true);
47929             }
47930         }
47931         else {
47932             
47933             callout.lines.setAttributes({
47934                 path: ["M", cur[0], cur[1], "L", x, y, "Z"]
47935             }, true);
47936             
47937             if (callout.panel) {
47938                 callout.panel.setPosition(boxx, boxy);
47939             }
47940         }
47941         for (p in callout) {
47942             callout[p].show(true);
47943         }
47944     },
47945     
47946     isItemInPoint: function(x, y, item, i) {
47947         var me = this,
47948             items = me.items,
47949             tolerance = me.selectionTolerance,
47950             result = null,
47951             prevItem,
47952             nextItem,
47953             prevPoint,
47954             nextPoint,
47955             ln,
47956             x1,
47957             y1,
47958             x2,
47959             y2,
47960             xIntersect,
47961             yIntersect,
47962             dist1, dist2, dist, midx, midy,
47963             sqrt = Math.sqrt, abs = Math.abs;
47964         
47965         nextItem = items[i];
47966         prevItem = i && items[i - 1];
47967         
47968         if (i >= ln) {
47969             prevItem = items[ln - 1];
47970         }
47971         prevPoint = prevItem && prevItem.point;
47972         nextPoint = nextItem && nextItem.point;
47973         x1 = prevItem ? prevPoint[0] : nextPoint[0] - tolerance;
47974         y1 = prevItem ? prevPoint[1] : nextPoint[1];
47975         x2 = nextItem ? nextPoint[0] : prevPoint[0] + tolerance;
47976         y2 = nextItem ? nextPoint[1] : prevPoint[1];
47977         dist1 = sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
47978         dist2 = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
47979         dist = Math.min(dist1, dist2);
47980         
47981         if (dist <= tolerance) {
47982             return dist == dist1? prevItem : nextItem;
47983         }
47984         return false;
47985     },
47986     
47987     
47988     toggleAll: function(show) {
47989         var me = this,
47990             i, ln, shadow, shadows;
47991         if (!show) {
47992             Ext.chart.series.Line.superclass.hideAll.call(me);
47993         }
47994         else {
47995             Ext.chart.series.Line.superclass.showAll.call(me);
47996         }
47997         if (me.line) {
47998             me.line.setAttributes({
47999                 hidden: !show
48000             }, true);
48001             
48002             if (me.line.shadows) {
48003                 for (i = 0, shadows = me.line.shadows, ln = shadows.length; i < ln; i++) {
48004                     shadow = shadows[i];
48005                     shadow.setAttributes({
48006                         hidden: !show
48007                     }, true);
48008                 }
48009             }
48010         }
48011         if (me.fillPath) {
48012             me.fillPath.setAttributes({
48013                 hidden: !show
48014             }, true);
48015         }
48016     },
48017     
48018     
48019     hideAll: function() {
48020         this.toggleAll(false);
48021     },
48022     
48023     
48024     showAll: function() {
48025         this.toggleAll(true);
48026     }
48027 });
48028
48029 Ext.define('Ext.chart.series.Pie', {
48030
48031     
48032
48033     alternateClassName: ['Ext.chart.PieSeries', 'Ext.chart.PieChart'],
48034
48035     extend: 'Ext.chart.series.Series',
48036
48037     
48038
48039     type: "pie",
48040     
48041     alias: 'series.pie',
48042
48043     rad: Math.PI / 180,
48044
48045     
48046     highlightDuration: 150,
48047
48048     
48049     angleField: false,
48050
48051     
48052     lengthField: false,
48053
48054     
48055     donut: false,
48056
48057     
48058     showInLegend: false,
48059
48060     
48061     
48062     
48063     style: {},
48064     
48065     constructor: function(config) {
48066         this.callParent(arguments);
48067         var me = this,
48068             chart = me.chart,
48069             surface = chart.surface,
48070             store = chart.store,
48071             shadow = chart.shadow, i, l, cfg;
48072         Ext.applyIf(me, {
48073             highlightCfg: {
48074                 segment: {
48075                     margin: 20
48076                 }
48077             }
48078         });
48079         Ext.apply(me, config, {            
48080             shadowAttributes: [{
48081                 "stroke-width": 6,
48082                 "stroke-opacity": 1,
48083                 stroke: 'rgb(200, 200, 200)',
48084                 translate: {
48085                     x: 1.2,
48086                     y: 2
48087                 }
48088             },
48089             {
48090                 "stroke-width": 4,
48091                 "stroke-opacity": 1,
48092                 stroke: 'rgb(150, 150, 150)',
48093                 translate: {
48094                     x: 0.9,
48095                     y: 1.5
48096                 }
48097             },
48098             {
48099                 "stroke-width": 2,
48100                 "stroke-opacity": 1,
48101                 stroke: 'rgb(100, 100, 100)',
48102                 translate: {
48103                     x: 0.6,
48104                     y: 1
48105                 }
48106             }]
48107         });
48108         me.group = surface.getGroup(me.seriesId);
48109         if (shadow) {
48110             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
48111                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
48112             }
48113         }
48114         surface.customAttributes.segment = function(opt) {
48115             return me.getSegment(opt);
48116         };
48117     },
48118     
48119     //@private updates some onbefore render parameters.
48120
48121     initialize: function() {
48122         var me = this,
48123             store = me.chart.substore || me.chart.store;
48124         
48125         me.yField = [];
48126         if (me.label.field) {
48127             store.each(function(rec) {
48128                 me.yField.push(rec.get(me.label.field));
48129             });
48130         }
48131     },
48132
48133     
48134     getSegment: function(opt) {
48135         var me = this,
48136             rad = me.rad,
48137             cos = Math.cos,
48138             sin = Math.sin,
48139             abs = Math.abs,
48140             x = me.centerX,
48141             y = me.centerY,
48142             x1 = 0, x2 = 0, x3 = 0, x4 = 0,
48143             y1 = 0, y2 = 0, y3 = 0, y4 = 0,
48144             delta = 1e-2,
48145             r = opt.endRho - opt.startRho,
48146             startAngle = opt.startAngle,
48147             endAngle = opt.endAngle,
48148             midAngle = (startAngle + endAngle) / 2 * rad,
48149             margin = opt.margin || 0,
48150             flag = abs(endAngle - startAngle) > 180,
48151             a1 = Math.min(startAngle, endAngle) * rad,
48152             a2 = Math.max(startAngle, endAngle) * rad,
48153             singleSlice = false;
48154
48155         x += margin * cos(midAngle);
48156         y += margin * sin(midAngle);
48157
48158         x1 = x + opt.startRho * cos(a1);
48159         y1 = y + opt.startRho * sin(a1);
48160
48161         x2 = x + opt.endRho * cos(a1);
48162         y2 = y + opt.endRho * sin(a1);
48163
48164         x3 = x + opt.startRho * cos(a2);
48165         y3 = y + opt.startRho * sin(a2);
48166
48167         x4 = x + opt.endRho * cos(a2);
48168         y4 = y + opt.endRho * sin(a2);
48169
48170         if (abs(x1 - x3) <= delta && abs(y1 - y3) <= delta) {
48171             singleSlice = true;
48172         }
48173         
48174         if (singleSlice) {
48175             return {
48176                 path: [
48177                 ["M", x1, y1],
48178                 ["L", x2, y2],
48179                 ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
48180                 ["Z"]]
48181             };
48182         } else {
48183             return {
48184                 path: [
48185                 ["M", x1, y1],
48186                 ["L", x2, y2],
48187                 ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
48188                 ["L", x3, y3],
48189                 ["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
48190                 ["Z"]]
48191             };
48192         }
48193     },
48194
48195     
48196     calcMiddle: function(item) {
48197         var me = this,
48198             rad = me.rad,
48199             slice = item.slice,
48200             x = me.centerX,
48201             y = me.centerY,
48202             startAngle = slice.startAngle,
48203             endAngle = slice.endAngle,
48204             donut = +me.donut,
48205             a1 = Math.min(startAngle, endAngle) * rad,
48206             a2 = Math.max(startAngle, endAngle) * rad,
48207             midAngle = -(a1 + (a2 - a1) / 2),
48208             xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle),
48209             ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle);
48210
48211         item.middle = {
48212             x: xm,
48213             y: ym
48214         };
48215     },
48216
48217     
48218     drawSeries: function() {
48219         var me = this,
48220             store = me.chart.substore || me.chart.store,
48221             group = me.group,
48222             animate = me.chart.animate,
48223             field = me.angleField || me.field || me.xField,
48224             lenField = [].concat(me.lengthField),
48225             totalLenField = 0,
48226             colors = me.colorSet,
48227             chart = me.chart,
48228             surface = chart.surface,
48229             chartBBox = chart.chartBBox,
48230             enableShadows = chart.shadow,
48231             shadowGroups = me.shadowGroups,
48232             shadowAttributes = me.shadowAttributes,
48233             lnsh = shadowGroups.length,
48234             rad = me.rad,
48235             layers = lenField.length,
48236             rhoAcum = 0,
48237             donut = +me.donut,
48238             layerTotals = [],
48239             values = {},
48240             fieldLength,
48241             items = [],
48242             passed = false,
48243             totalField = 0,
48244             maxLenField = 0,
48245             cut = 9,
48246             defcut = true,
48247             angle = 0,
48248             seriesStyle = me.seriesStyle,
48249             seriesLabelStyle = me.seriesLabelStyle,
48250             colorArrayStyle = me.colorArrayStyle,
48251             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
48252             gutterX = chart.maxGutter[0],
48253             gutterY = chart.maxGutter[1],
48254             rendererAttributes,
48255             shadowGroup,
48256             shadowAttr,
48257             shadows,
48258             shadow,
48259             shindex,
48260             centerX,
48261             centerY,
48262             deltaRho,
48263             first = 0,
48264             slice,
48265             slices,
48266             sprite,
48267             value,
48268             item,
48269             lenValue,
48270             ln,
48271             record,
48272             i,
48273             j,
48274             startAngle,
48275             endAngle,
48276             middleAngle,
48277             sliceLength,
48278             path,
48279             p,
48280             spriteOptions, bbox;
48281         
48282         Ext.apply(seriesStyle, me.style || {});
48283
48284         me.setBBox();
48285         bbox = me.bbox;
48286
48287         
48288         if (me.colorSet) {
48289             colorArrayStyle = me.colorSet;
48290             colorArrayLength = colorArrayStyle.length;
48291         }
48292         
48293         
48294         if (!store || !store.getCount()) {
48295             return;
48296         }
48297         
48298         me.unHighlightItem();
48299         me.cleanHighlights();
48300
48301         centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
48302         centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
48303         me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
48304         me.slices = slices = [];
48305         me.items = items = [];
48306
48307         store.each(function(record, i) {
48308             if (this.__excludes && this.__excludes[i]) {
48309                 
48310                 return;
48311             }
48312             totalField += +record.get(field);
48313             if (lenField[0]) {
48314                 for (j = 0, totalLenField = 0; j < layers; j++) {
48315                     totalLenField += +record.get(lenField[j]);
48316                 }
48317                 layerTotals[i] = totalLenField;
48318                 maxLenField = Math.max(maxLenField, totalLenField);
48319             }
48320         }, this);
48321
48322         store.each(function(record, i) {
48323             if (this.__excludes && this.__excludes[i]) {
48324                 
48325                 return;
48326             } 
48327             value = record.get(field);
48328             middleAngle = angle - 360 * value / totalField / 2;
48329             
48330             if (isNaN(middleAngle)) {
48331                 middleAngle = 360;
48332                 value = 1;
48333                 totalField = 1;
48334             }
48335             
48336             if (!i || first == 0) {
48337                 angle = 360 - middleAngle;
48338                 me.firstAngle = angle;
48339                 middleAngle = angle - 360 * value / totalField / 2;
48340             }
48341             endAngle = angle - 360 * value / totalField;
48342             slice = {
48343                 series: me,
48344                 value: value,
48345                 startAngle: angle,
48346                 endAngle: endAngle,
48347                 storeItem: record
48348             };
48349             if (lenField[0]) {
48350                 lenValue = layerTotals[i];
48351                 slice.rho = me.radius * (lenValue / maxLenField);
48352             } else {
48353                 slice.rho = me.radius;
48354             }
48355             slices[i] = slice;
48356             if((slice.startAngle % 360) == (slice.endAngle % 360)) {
48357                 slice.startAngle -= 0.0001;
48358             }
48359             angle = endAngle;
48360             first++;
48361         }, me);
48362         
48363         
48364         if (enableShadows) {
48365             for (i = 0, ln = slices.length; i < ln; i++) {
48366                 if (this.__excludes && this.__excludes[i]) {
48367                     
48368                     continue;
48369                 }
48370                 slice = slices[i];
48371                 slice.shadowAttrs = [];
48372                 for (j = 0, rhoAcum = 0, shadows = []; j < layers; j++) {
48373                     sprite = group.getAt(i * layers + j);
48374                     deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho;
48375                     
48376                     rendererAttributes = {
48377                         segment: {
48378                             startAngle: slice.startAngle,
48379                             endAngle: slice.endAngle,
48380                             margin: 0,
48381                             rho: slice.rho,
48382                             startRho: rhoAcum + (deltaRho * donut / 100),
48383                             endRho: rhoAcum + deltaRho
48384                         }
48385                     };
48386                     
48387                     for (shindex = 0, shadows = []; shindex < lnsh; shindex++) {
48388                         shadowAttr = shadowAttributes[shindex];
48389                         shadow = shadowGroups[shindex].getAt(i);
48390                         if (!shadow) {
48391                             shadow = chart.surface.add(Ext.apply({},
48392                             {
48393                                 type: 'path',
48394                                 group: shadowGroups[shindex],
48395                                 strokeLinejoin: "round"
48396                             },
48397                             rendererAttributes, shadowAttr));
48398                         }
48399                         if (animate) {
48400                             rendererAttributes = me.renderer(shadow, store.getAt(i), Ext.apply({},
48401                             rendererAttributes, shadowAttr), i, store);
48402                             me.onAnimate(shadow, {
48403                                 to: rendererAttributes
48404                             });
48405                         } else {
48406                             rendererAttributes = me.renderer(shadow, store.getAt(i), Ext.apply(shadowAttr, {
48407                                 hidden: false
48408                             }), i, store);
48409                             shadow.setAttributes(rendererAttributes, true);
48410                         }
48411                         shadows.push(shadow);
48412                     }
48413                     slice.shadowAttrs[j] = shadows;
48414                 }
48415             }
48416         }
48417         
48418         for (i = 0, ln = slices.length; i < ln; i++) {
48419             if (this.__excludes && this.__excludes[i]) {
48420                 
48421                 continue;
48422             }
48423             slice = slices[i];
48424             for (j = 0, rhoAcum = 0; j < layers; j++) {
48425                 sprite = group.getAt(i * layers + j);
48426                 deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho;
48427                 
48428                 rendererAttributes = Ext.apply({
48429                     segment: {
48430                         startAngle: slice.startAngle,
48431                         endAngle: slice.endAngle,
48432                         margin: 0,
48433                         rho: slice.rho,
48434                         startRho: rhoAcum + (deltaRho * donut / 100),
48435                         endRho: rhoAcum + deltaRho
48436                     } 
48437                 }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {}));
48438                 item = Ext.apply({},
48439                 rendererAttributes.segment, {
48440                     slice: slice,
48441                     series: me,
48442                     storeItem: slice.storeItem,
48443                     index: i
48444                 });
48445                 me.calcMiddle(item);
48446                 if (enableShadows) {
48447                     item.shadows = slice.shadowAttrs[j];
48448                 }
48449                 items[i] = item;
48450                 
48451                 if (!sprite) {
48452                     spriteOptions = Ext.apply({
48453                         type: "path",
48454                         group: group,
48455                         middle: item.middle
48456                     }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {}));
48457                     sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
48458                 }
48459                 slice.sprite = slice.sprite || [];
48460                 item.sprite = sprite;
48461                 slice.sprite.push(sprite);
48462                 slice.point = [item.middle.x, item.middle.y];
48463                 if (animate) {
48464                     rendererAttributes = me.renderer(sprite, store.getAt(i), rendererAttributes, i, store);
48465                     sprite._to = rendererAttributes;
48466                     sprite._animating = true;
48467                     me.onAnimate(sprite, {
48468                         to: rendererAttributes,
48469                         listeners: {
48470                             afteranimate: {
48471                                 fn: function() {
48472                                     this._animating = false;
48473                                 },
48474                                 scope: sprite
48475                             }
48476                         }
48477                     });
48478                 } else {
48479                     rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(rendererAttributes, {
48480                         hidden: false
48481                     }), i, store);
48482                     sprite.setAttributes(rendererAttributes, true);
48483                 }
48484                 rhoAcum += deltaRho;
48485             }
48486         }
48487         
48488         
48489         ln = group.getCount();
48490         for (i = 0; i < ln; i++) {
48491             if (!slices[(i / layers) >> 0] && group.getAt(i)) {
48492                 group.getAt(i).hide(true);
48493             }
48494         }
48495         if (enableShadows) {
48496             lnsh = shadowGroups.length;
48497             for (shindex = 0; shindex < ln; shindex++) {
48498                 if (!slices[(shindex / layers) >> 0]) {
48499                     for (j = 0; j < lnsh; j++) {
48500                         if (shadowGroups[j].getAt(shindex)) {
48501                             shadowGroups[j].getAt(shindex).hide(true);
48502                         }
48503                     }
48504                 }
48505             }
48506         }
48507         me.renderLabels();
48508         me.renderCallouts();
48509     },
48510
48511     
48512     onCreateLabel: function(storeItem, item, i, display) {
48513         var me = this,
48514             group = me.labelsGroup,
48515             config = me.label,
48516             centerX = me.centerX,
48517             centerY = me.centerY,
48518             middle = item.middle,
48519             endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config || {});
48520         
48521         return me.chart.surface.add(Ext.apply({
48522             'type': 'text',
48523             'text-anchor': 'middle',
48524             'group': group,
48525             'x': middle.x,
48526             'y': middle.y
48527         }, endLabelStyle));
48528     },
48529
48530     
48531     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
48532         var me = this,
48533             chart = me.chart,
48534             resizing = chart.resizing,
48535             config = me.label,
48536             format = config.renderer,
48537             field = [].concat(config.field),
48538             centerX = me.centerX,
48539             centerY = me.centerY,
48540             middle = item.middle,
48541             opt = {
48542                 x: middle.x,
48543                 y: middle.y
48544             },
48545             x = middle.x - centerX,
48546             y = middle.y - centerY,
48547             from = {},
48548             rho = 1,
48549             theta = Math.atan2(y, x || 1),
48550             dg = theta * 180 / Math.PI,
48551             prevDg;
48552         
48553         function fixAngle(a) {
48554             if (a < 0) a += 360;
48555             return a % 360;
48556         }
48557
48558         label.setAttributes({
48559             text: format(storeItem.get(field[index]))
48560         }, true);
48561
48562         switch (display) {
48563         case 'outside':
48564             rho = Math.sqrt(x * x + y * y) * 2;
48565             
48566             opt.x = rho * Math.cos(theta) + centerX;
48567             opt.y = rho * Math.sin(theta) + centerY;
48568             break;
48569
48570         case 'rotate':
48571             dg = fixAngle(dg);
48572             dg = (dg > 90 && dg < 270) ? dg + 180: dg;
48573
48574             prevDg = label.attr.rotation.degrees;
48575             if (prevDg != null && Math.abs(prevDg - dg) > 180) {
48576                 if (dg > prevDg) {
48577                     dg -= 360;
48578                 } else {
48579                     dg += 360;
48580                 }
48581                 dg = dg % 360;
48582             } else {
48583                 dg = fixAngle(dg);
48584             }
48585             
48586             opt.rotate = {
48587                 degrees: dg,
48588                 x: opt.x,
48589                 y: opt.y
48590             };
48591             break;
48592
48593         default:
48594             break;
48595         }
48596         
48597         opt.translate = {
48598             x: 0, y: 0    
48599         };
48600         if (animate && !resizing && (display != 'rotate' || prevDg != null)) {
48601             me.onAnimate(label, {
48602                 to: opt
48603             });
48604         } else {
48605             label.setAttributes(opt, true);
48606         }
48607         label._from = from;
48608     },
48609
48610     
48611     onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
48612         var me = this,
48613             chart = me.chart,
48614             resizing = chart.resizing,
48615             config = me.callouts,
48616             centerX = me.centerX,
48617             centerY = me.centerY,
48618             middle = item.middle,
48619             opt = {
48620                 x: middle.x,
48621                 y: middle.y
48622             },
48623             x = middle.x - centerX,
48624             y = middle.y - centerY,
48625             rho = 1,
48626             rhoCenter,
48627             theta = Math.atan2(y, x || 1),
48628             bbox = callout.label.getBBox(),
48629             offsetFromViz = 20,
48630             offsetToSide = 10,
48631             offsetBox = 10,
48632             p;
48633
48634         
48635         rho = item.endRho + offsetFromViz;
48636         rhoCenter = (item.endRho + item.startRho) / 2 + (item.endRho - item.startRho) / 3;
48637         
48638         opt.x = rho * Math.cos(theta) + centerX;
48639         opt.y = rho * Math.sin(theta) + centerY;
48640
48641         x = rhoCenter * Math.cos(theta);
48642         y = rhoCenter * Math.sin(theta);
48643
48644         if (chart.animate) {
48645             
48646             me.onAnimate(callout.lines, {
48647                 to: {
48648                     path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"]
48649                 }
48650             });
48651             
48652             me.onAnimate(callout.box, {
48653                 to: {
48654                     x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)),
48655                     y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)),
48656                     width: bbox.width + 2 * offsetBox,
48657                     height: bbox.height + 2 * offsetBox
48658                 }
48659             });
48660             
48661             me.onAnimate(callout.label, {
48662                 to: {
48663                     x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)),
48664                     y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4)
48665                 }
48666             });
48667         } else {
48668             
48669             callout.lines.setAttributes({
48670                 path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"]
48671             },
48672             true);
48673             
48674             callout.box.setAttributes({
48675                 x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)),
48676                 y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)),
48677                 width: bbox.width + 2 * offsetBox,
48678                 height: bbox.height + 2 * offsetBox
48679             },
48680             true);
48681             
48682             callout.label.setAttributes({
48683                 x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)),
48684                 y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4)
48685             },
48686             true);
48687         }
48688         for (p in callout) {
48689             callout[p].show(true);
48690         }
48691     },
48692
48693     
48694     onAnimate: function(sprite, attr) {
48695         sprite.show();
48696         return this.callParent(arguments);
48697     },
48698
48699     isItemInPoint: function(x, y, item, i) {
48700         var me = this,
48701             cx = me.centerX,
48702             cy = me.centerY,
48703             abs = Math.abs,
48704             dx = abs(x - cx),
48705             dy = abs(y - cy),
48706             startAngle = item.startAngle,
48707             endAngle = item.endAngle,
48708             rho = Math.sqrt(dx * dx + dy * dy),
48709             angle = Math.atan2(y - cy, x - cx) / me.rad + 360;
48710         
48711         
48712         if (angle > me.firstAngle) {
48713             angle -= 360;
48714         }
48715         return (angle <= startAngle && angle > endAngle
48716                 && rho >= item.startRho && rho <= item.endRho);
48717     },
48718     
48719     
48720     hideAll: function() {
48721         var i, l, shadow, shadows, sh, lsh, sprite;
48722         if (!isNaN(this._index)) {
48723             this.__excludes = this.__excludes || [];
48724             this.__excludes[this._index] = true;
48725             sprite = this.slices[this._index].sprite;
48726             for (sh = 0, lsh = sprite.length; sh < lsh; sh++) {
48727                 sprite[sh].setAttributes({
48728                     hidden: true
48729                 }, true);
48730             }
48731             if (this.slices[this._index].shadowAttrs) {
48732                 for (i = 0, shadows = this.slices[this._index].shadowAttrs, l = shadows.length; i < l; i++) {
48733                     shadow = shadows[i];
48734                     for (sh = 0, lsh = shadow.length; sh < lsh; sh++) {
48735                         shadow[sh].setAttributes({
48736                             hidden: true
48737                         }, true);
48738                     }
48739                 }
48740             }
48741             this.drawSeries();
48742         }
48743     },
48744     
48745     
48746     showAll: function() {
48747         if (!isNaN(this._index)) {
48748             this.__excludes[this._index] = false;
48749             this.drawSeries();
48750         }
48751     },
48752
48753     
48754     highlightItem: function(item) {
48755         var me = this,
48756             rad = me.rad;
48757         item = item || this.items[this._index];
48758         
48759         
48760         
48761         
48762         
48763         this.unHighlightItem();
48764         
48765         if (!item || item.sprite && item.sprite._animating) {
48766             return;
48767         }
48768         me.callParent([item]);
48769         if (!me.highlight) {
48770             return;
48771         }
48772         if ('segment' in me.highlightCfg) {
48773             var highlightSegment = me.highlightCfg.segment,
48774                 animate = me.chart.animate,
48775                 attrs, i, shadows, shadow, ln, to, itemHighlightSegment, prop;
48776             
48777             if (me.labelsGroup) {
48778                 var group = me.labelsGroup,
48779                     display = me.label.display,
48780                     label = group.getAt(item.index),
48781                     middle = (item.startAngle + item.endAngle) / 2 * rad,
48782                     r = highlightSegment.margin || 0,
48783                     x = r * Math.cos(middle),
48784                     y = r * Math.sin(middle);
48785
48786                 
48787                 
48788                 
48789                 
48790                 
48791                 if (Math.abs(x) < 1e-10) {
48792                     x = 0;
48793                 }
48794                 if (Math.abs(y) < 1e-10) {
48795                     y = 0;
48796                 }
48797                 
48798                 if (animate) {
48799                     label.stopAnimation();
48800                     label.animate({
48801                         to: {
48802                             translate: {
48803                                 x: x,
48804                                 y: y
48805                             }
48806                         },
48807                         duration: me.highlightDuration
48808                     });
48809                 }
48810                 else {
48811                     label.setAttributes({
48812                         translate: {
48813                             x: x,
48814                             y: y
48815                         }
48816                     }, true);
48817                 }
48818             }
48819             
48820             if (me.chart.shadow && item.shadows) {
48821                 i = 0;
48822                 shadows = item.shadows;
48823                 ln = shadows.length;
48824                 for (; i < ln; i++) {
48825                     shadow = shadows[i];
48826                     to = {};
48827                     itemHighlightSegment = item.sprite._from.segment;
48828                     for (prop in itemHighlightSegment) {
48829                         if (! (prop in highlightSegment)) {
48830                             to[prop] = itemHighlightSegment[prop];
48831                         }
48832                     }
48833                     attrs = {
48834                         segment: Ext.applyIf(to, me.highlightCfg.segment)
48835                     };
48836                     if (animate) {
48837                         shadow.stopAnimation();
48838                         shadow.animate({
48839                             to: attrs,
48840                             duration: me.highlightDuration
48841                         });
48842                     }
48843                     else {
48844                         shadow.setAttributes(attrs, true);
48845                     }
48846                 }
48847             }
48848         }
48849     },
48850
48851     
48852     unHighlightItem: function() {
48853         var me = this;
48854         if (!me.highlight) {
48855             return;
48856         }
48857
48858         if (('segment' in me.highlightCfg) && me.items) {
48859             var items = me.items,
48860                 animate = me.chart.animate,
48861                 shadowsEnabled = !!me.chart.shadow,
48862                 group = me.labelsGroup,
48863                 len = items.length,
48864                 i = 0,
48865                 j = 0,
48866                 display = me.label.display,
48867                 shadowLen, p, to, ihs, hs, sprite, shadows, shadow, item, label, attrs;
48868
48869             for (; i < len; i++) {
48870                 item = items[i];
48871                 if (!item) {
48872                     continue;
48873                 }
48874                 sprite = item.sprite;
48875                 if (sprite && sprite._highlighted) {
48876                     
48877                     if (group) {
48878                         label = group.getAt(item.index);
48879                         attrs = Ext.apply({
48880                             translate: {
48881                                 x: 0,
48882                                 y: 0
48883                             }
48884                         },
48885                         display == 'rotate' ? {
48886                             rotate: {
48887                                 x: label.attr.x,
48888                                 y: label.attr.y,
48889                                 degrees: label.attr.rotation.degrees
48890                             }
48891                         }: {});
48892                         if (animate) {
48893                             label.stopAnimation();
48894                             label.animate({
48895                                 to: attrs,
48896                                 duration: me.highlightDuration
48897                             });
48898                         }
48899                         else {
48900                             label.setAttributes(attrs, true);
48901                         }
48902                     }
48903                     if (shadowsEnabled) {
48904                         shadows = item.shadows;
48905                         shadowLen = shadows.length;
48906                         for (; j < shadowLen; j++) {
48907                             to = {};
48908                             ihs = item.sprite._to.segment;
48909                             hs = item.sprite._from.segment;
48910                             Ext.apply(to, hs);
48911                             for (p in ihs) {
48912                                 if (! (p in hs)) {
48913                                     to[p] = ihs[p];
48914                                 }
48915                             }
48916                             shadow = shadows[j];
48917                             if (animate) {
48918                                 shadow.stopAnimation();
48919                                 shadow.animate({
48920                                     to: {
48921                                         segment: to
48922                                     },
48923                                     duration: me.highlightDuration
48924                                 });
48925                             }
48926                             else {
48927                                 shadow.setAttributes({ segment: to }, true);
48928                             }
48929                         }
48930                     }
48931                 }
48932             }
48933         }
48934         me.callParent(arguments);
48935     },
48936     
48937     
48938     getLegendColor: function(index) {
48939         var me = this;
48940         return me.colorArrayStyle[index % me.colorArrayStyle.length];
48941     }
48942 });
48943
48944
48945
48946 Ext.define('Ext.chart.series.Radar', {
48947
48948     
48949
48950     extend: 'Ext.chart.series.Series',
48951
48952     requires: ['Ext.chart.Shape', 'Ext.fx.Anim'],
48953
48954     
48955
48956     type: "radar",
48957     alias: 'series.radar',
48958
48959     
48960     rad: Math.PI / 180,
48961
48962     showInLegend: false,
48963
48964     
48965     style: {},
48966     
48967     constructor: function(config) {
48968         this.callParent(arguments);
48969         var me = this,
48970             surface = me.chart.surface, i, l;
48971         me.group = surface.getGroup(me.seriesId);
48972         if (me.showMarkers) {
48973             me.markerGroup = surface.getGroup(me.seriesId + '-markers');
48974         }
48975     },
48976
48977     
48978     drawSeries: function() {
48979         var me = this,
48980             store = me.chart.substore || me.chart.store,
48981             group = me.group,
48982             sprite,
48983             chart = me.chart,
48984             animate = chart.animate,
48985             field = me.field || me.yField,
48986             surface = chart.surface,
48987             chartBBox = chart.chartBBox,
48988             rendererAttributes,
48989             centerX, centerY,
48990             items,
48991             radius,
48992             maxValue = 0,
48993             fields = [],
48994             max = Math.max,
48995             cos = Math.cos,
48996             sin = Math.sin,
48997             pi2 = Math.PI * 2,
48998             l = store.getCount(),
48999             startPath, path, x, y, rho,
49000             i, nfields,
49001             seriesStyle = me.seriesStyle,
49002             seriesLabelStyle = me.seriesLabelStyle,
49003             first = chart.resizing || !me.radar,
49004             axis = chart.axes && chart.axes.get(0),
49005             aggregate = !(axis && axis.maximum);
49006         
49007         me.setBBox();
49008
49009         maxValue = aggregate? 0 : (axis.maximum || 0);
49010         
49011         Ext.apply(seriesStyle, me.style || {});
49012         
49013         
49014         if (!store || !store.getCount()) {
49015             return;
49016         }
49017         
49018         me.unHighlightItem();
49019         me.cleanHighlights();
49020
49021         centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
49022         centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
49023         me.radius = radius = Math.min(chartBBox.width, chartBBox.height) /2;
49024         me.items = items = [];
49025
49026         if (aggregate) {
49027             
49028             chart.series.each(function(series) {
49029                 fields.push(series.yField);
49030             });
49031             
49032             store.each(function(record, i) {
49033                 for (i = 0, nfields = fields.length; i < nfields; i++) {
49034                     maxValue = max(+record.get(fields[i]), maxValue);
49035                 }
49036             });
49037         }
49038         
49039         maxValue = maxValue || 1;
49040         
49041         startPath = []; path = [];
49042         store.each(function(record, i) {
49043             rho = radius * record.get(field) / maxValue;
49044             x = rho * cos(i / l * pi2);
49045             y = rho * sin(i / l * pi2);
49046             if (i == 0) {
49047                 path.push('M', x + centerX, y + centerY);
49048                 startPath.push('M', 0.01 * x + centerX, 0.01 * y + centerY);
49049             } else {
49050                 path.push('L', x + centerX, y + centerY);
49051                 startPath.push('L', 0.01 * x + centerX, 0.01 * y + centerY);
49052             }
49053             items.push({
49054                 sprite: false, 
49055                 point: [centerX + x, centerY + y],
49056                 series: me
49057             });
49058         });
49059         path.push('Z');
49060         
49061         if (!me.radar) {
49062             me.radar = surface.add(Ext.apply({
49063                 type: 'path',
49064                 group: group,
49065                 path: startPath
49066             }, seriesStyle || {}));
49067         }
49068         
49069         if (chart.resizing) {
49070             me.radar.setAttributes({
49071                 path: startPath
49072             }, true);
49073         }
49074         
49075         if (chart.animate) {
49076             me.onAnimate(me.radar, {
49077                 to: Ext.apply({
49078                     path: path
49079                 }, seriesStyle || {})
49080             });
49081         } else {
49082             me.radar.setAttributes(Ext.apply({
49083                 path: path
49084             }, seriesStyle || {}), true);
49085         }
49086         
49087         if (me.showMarkers) {
49088             me.drawMarkers();
49089         }
49090         me.renderLabels();
49091         me.renderCallouts();
49092     },
49093     
49094     
49095     drawMarkers: function() {
49096         var me = this,
49097             chart = me.chart,
49098             surface = chart.surface,
49099             markerStyle = Ext.apply({}, me.markerStyle || {}),
49100             endMarkerStyle = Ext.apply(markerStyle, me.markerConfig),
49101             items = me.items, 
49102             type = endMarkerStyle.type,
49103             markerGroup = me.markerGroup,
49104             centerX = me.centerX,
49105             centerY = me.centerY,
49106             item, i, l, marker;
49107         
49108         delete endMarkerStyle.type;
49109         
49110         for (i = 0, l = items.length; i < l; i++) {
49111             item = items[i];
49112             marker = markerGroup.getAt(i);
49113             if (!marker) {
49114                 marker = Ext.chart.Shape[type](surface, Ext.apply({
49115                     group: markerGroup,
49116                     x: 0,
49117                     y: 0,
49118                     translate: {
49119                         x: centerX,
49120                         y: centerY
49121                     }
49122                 }, endMarkerStyle));
49123             }
49124             else {
49125                 marker.show();
49126             }
49127             if (chart.resizing) {
49128                 marker.setAttributes({
49129                     x: 0,
49130                     y: 0,
49131                     translate: {
49132                         x: centerX,
49133                         y: centerY
49134                     }
49135                 }, true);
49136             }
49137             marker._to = {
49138                 translate: {
49139                     x: item.point[0],
49140                     y: item.point[1]
49141                 }
49142             };
49143             
49144             if (chart.animate) {
49145                 me.onAnimate(marker, {
49146                     to: marker._to
49147                 });
49148             }
49149             else {
49150                 marker.setAttributes(Ext.apply(marker._to, endMarkerStyle || {}), true);
49151             }
49152         }
49153     },
49154     
49155     isItemInPoint: function(x, y, item) {
49156         var point,
49157             tolerance = 10,
49158             abs = Math.abs;
49159         point = item.point;
49160         return (abs(point[0] - x) <= tolerance &&
49161                 abs(point[1] - y) <= tolerance);
49162     },
49163
49164     
49165     onCreateLabel: function(storeItem, item, i, display) {
49166         var me = this,
49167             group = me.labelsGroup,
49168             config = me.label,
49169             centerX = me.centerX,
49170             centerY = me.centerY,
49171             point = item.point,
49172             endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config);
49173         
49174         return me.chart.surface.add(Ext.apply({
49175             'type': 'text',
49176             'text-anchor': 'middle',
49177             'group': group,
49178             'x': centerX,
49179             'y': centerY
49180         }, config || {}));
49181     },
49182
49183     
49184     onPlaceLabel: function(label, storeItem, item, i, display, animate) {
49185         var me = this,
49186             chart = me.chart,
49187             resizing = chart.resizing,
49188             config = me.label,
49189             format = config.renderer,
49190             field = config.field,
49191             centerX = me.centerX,
49192             centerY = me.centerY,
49193             opt = {
49194                 x: item.point[0],
49195                 y: item.point[1]
49196             },
49197             x = opt.x - centerX,
49198             y = opt.y - centerY;
49199
49200         label.setAttributes({
49201             text: format(storeItem.get(field)),
49202             hidden: true
49203         },
49204         true);
49205         
49206         if (resizing) {
49207             label.setAttributes({
49208                 x: centerX,
49209                 y: centerY
49210             }, true);
49211         }
49212         
49213         if (animate) {
49214             label.show(true);
49215             me.onAnimate(label, {
49216                 to: opt
49217             });
49218         } else {
49219             label.setAttributes(opt, true);
49220             label.show(true);
49221         }
49222     },
49223
49224     
49225     toggleAll: function(show) {
49226         var me = this,
49227             i, ln, shadow, shadows;
49228         if (!show) {
49229             Ext.chart.series.Radar.superclass.hideAll.call(me);
49230         }
49231         else {
49232             Ext.chart.series.Radar.superclass.showAll.call(me);
49233         }
49234         if (me.radar) {
49235             me.radar.setAttributes({
49236                 hidden: !show
49237             }, true);
49238             
49239             if (me.radar.shadows) {
49240                 for (i = 0, shadows = me.radar.shadows, ln = shadows.length; i < ln; i++) {
49241                     shadow = shadows[i];
49242                     shadow.setAttributes({
49243                         hidden: !show
49244                     }, true);
49245                 }
49246             }
49247         }
49248     },
49249     
49250     
49251     hideAll: function() {
49252         this.toggleAll(false);
49253         this.hideMarkers(0);
49254     },
49255     
49256     
49257     showAll: function() {
49258         this.toggleAll(true);
49259     },
49260     
49261     
49262     hideMarkers: function(index) {
49263         var me = this,
49264             count = me.markerGroup && me.markerGroup.getCount() || 0,
49265             i = index || 0;
49266         for (; i < count; i++) {
49267             me.markerGroup.getAt(i).hide(true);
49268         }
49269     }
49270 });
49271
49272
49273
49274 Ext.define('Ext.chart.series.Scatter', {
49275
49276     
49277
49278     extend: 'Ext.chart.series.Cartesian',
49279
49280     requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.fx.Anim'],
49281
49282     
49283
49284     type: 'scatter',
49285     alias: 'series.scatter',
49286
49287     
49288     
49289     
49290
49291     constructor: function(config) {
49292         this.callParent(arguments);
49293         var me = this,
49294             shadow = me.chart.shadow,
49295             surface = me.chart.surface, i, l;
49296         Ext.apply(me, config, {
49297             style: {},
49298             markerConfig: {},
49299             shadowAttributes: [{
49300                 "stroke-width": 6,
49301                 "stroke-opacity": 0.05,
49302                 stroke: 'rgb(0, 0, 0)'
49303             }, {
49304                 "stroke-width": 4,
49305                 "stroke-opacity": 0.1,
49306                 stroke: 'rgb(0, 0, 0)'
49307             }, {
49308                 "stroke-width": 2,
49309                 "stroke-opacity": 0.15,
49310                 stroke: 'rgb(0, 0, 0)'
49311             }]
49312         });
49313         me.group = surface.getGroup(me.seriesId);
49314         if (shadow) {
49315             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
49316                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
49317             }
49318         }
49319     },
49320
49321     
49322     getBounds: function() {
49323         var me = this,
49324             chart = me.chart,
49325             store = chart.substore || chart.store,
49326             axes = [].concat(me.axis),
49327             bbox, xScale, yScale, ln, minX, minY, maxX, maxY, i, axis, ends;
49328
49329         me.setBBox();
49330         bbox = me.bbox;
49331
49332         for (i = 0, ln = axes.length; i < ln; i++) { 
49333             axis = chart.axes.get(axes[i]);
49334             if (axis) {
49335                 ends = axis.calcEnds();
49336                 if (axis.position == 'top' || axis.position == 'bottom') {
49337                     minX = ends.from;
49338                     maxX = ends.to;
49339                 }
49340                 else {
49341                     minY = ends.from;
49342                     maxY = ends.to;
49343                 }
49344             }
49345         }
49346         
49347         if (me.xField && !Ext.isNumber(minX)) {
49348             axis = Ext.create('Ext.chart.axis.Axis', {
49349                 chart: chart,
49350                 fields: [].concat(me.xField)
49351             }).calcEnds();
49352             minX = axis.from;
49353             maxX = axis.to;
49354         }
49355         if (me.yField && !Ext.isNumber(minY)) {
49356             axis = Ext.create('Ext.chart.axis.Axis', {
49357                 chart: chart,
49358                 fields: [].concat(me.yField)
49359             }).calcEnds();
49360             minY = axis.from;
49361             maxY = axis.to;
49362         }
49363
49364         if (isNaN(minX)) {
49365             minX = 0;
49366             maxX = store.getCount() - 1;
49367             xScale = bbox.width / (store.getCount() - 1);
49368         }
49369         else {
49370             xScale = bbox.width / (maxX - minX);
49371         }
49372
49373         if (isNaN(minY)) {
49374             minY = 0;
49375             maxY = store.getCount() - 1;
49376             yScale = bbox.height / (store.getCount() - 1);
49377         } 
49378         else {
49379             yScale = bbox.height / (maxY - minY);
49380         }
49381
49382         return {
49383             bbox: bbox,
49384             minX: minX,
49385             minY: minY,
49386             xScale: xScale,
49387             yScale: yScale
49388         };
49389     },
49390
49391     
49392     getPaths: function() {
49393         var me = this,
49394             chart = me.chart,
49395             enableShadows = chart.shadow,
49396             store = chart.substore || chart.store,
49397             group = me.group,
49398             bounds = me.bounds = me.getBounds(),
49399             bbox = me.bbox,
49400             xScale = bounds.xScale,
49401             yScale = bounds.yScale,
49402             minX = bounds.minX,
49403             minY = bounds.minY,
49404             boxX = bbox.x,
49405             boxY = bbox.y,
49406             boxHeight = bbox.height,
49407             items = me.items = [],
49408             attrs = [],
49409             x, y, xValue, yValue, sprite;
49410
49411         store.each(function(record, i) {
49412             xValue = record.get(me.xField);
49413             yValue = record.get(me.yField);
49414             
49415             if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
49416                 if (Ext.isDefined(Ext.global.console)) {
49417                     Ext.global.console.warn("[Ext.chart.series.Scatter]  Skipping a store element with an undefined value at ", record, xValue, yValue);
49418                 }
49419                 return;
49420             }
49421             
49422             if (typeof xValue == 'string' || typeof xValue == 'object') {
49423                 xValue = i;
49424             }
49425             if (typeof yValue == 'string' || typeof yValue == 'object') {
49426                 yValue = i;
49427             }
49428             x = boxX + (xValue - minX) * xScale;
49429             y = boxY + boxHeight - (yValue - minY) * yScale;
49430             attrs.push({
49431                 x: x,
49432                 y: y
49433             });
49434
49435             me.items.push({
49436                 series: me,
49437                 value: [xValue, yValue],
49438                 point: [x, y],
49439                 storeItem: record
49440             });
49441
49442             
49443             if (chart.animate && chart.resizing) {
49444                 sprite = group.getAt(i);
49445                 if (sprite) {
49446                     me.resetPoint(sprite);
49447                     if (enableShadows) {
49448                         me.resetShadow(sprite);
49449                     }
49450                 }
49451             }
49452         });
49453         return attrs;
49454     },
49455
49456     
49457     resetPoint: function(sprite) {
49458         var bbox = this.bbox;
49459         sprite.setAttributes({
49460             translate: {
49461                 x: (bbox.x + bbox.width) / 2,
49462                 y: (bbox.y + bbox.height) / 2
49463             }
49464         }, true);
49465     },
49466
49467     
49468     resetShadow: function(sprite) {
49469         var me = this,
49470             shadows = sprite.shadows,
49471             shadowAttributes = me.shadowAttributes,
49472             ln = me.shadowGroups.length,
49473             bbox = me.bbox,
49474             i, attr;
49475         for (i = 0; i < ln; i++) {
49476             attr = Ext.apply({}, shadowAttributes[i]);
49477             if (attr.translate) {
49478                 attr.translate.x += (bbox.x + bbox.width) / 2;
49479                 attr.translate.y += (bbox.y + bbox.height) / 2;
49480             }
49481             else {
49482                 attr.translate = {
49483                     x: (bbox.x + bbox.width) / 2,
49484                     y: (bbox.y + bbox.height) / 2
49485                 };
49486             }
49487             shadows[i].setAttributes(attr, true);
49488         }
49489     },
49490
49491     
49492     createPoint: function(attr, type) {
49493         var me = this,
49494             chart = me.chart,
49495             group = me.group,
49496             bbox = me.bbox;
49497
49498         return Ext.chart.Shape[type](chart.surface, Ext.apply({}, {
49499             x: 0,
49500             y: 0,
49501             group: group,
49502             translate: {
49503                 x: (bbox.x + bbox.width) / 2,
49504                 y: (bbox.y + bbox.height) / 2
49505             }
49506         }, attr));
49507     },
49508
49509     
49510     createShadow: function(sprite, endMarkerStyle, type) {
49511         var me = this,
49512             chart = me.chart,
49513             shadowGroups = me.shadowGroups,
49514             shadowAttributes = me.shadowAttributes,
49515             lnsh = shadowGroups.length,
49516             bbox = me.bbox,
49517             i, shadow, shadows, attr;
49518
49519         sprite.shadows = shadows = [];
49520
49521         for (i = 0; i < lnsh; i++) {
49522             attr = Ext.apply({}, shadowAttributes[i]);
49523             if (attr.translate) {
49524                 attr.translate.x += (bbox.x + bbox.width) / 2;
49525                 attr.translate.y += (bbox.y + bbox.height) / 2;
49526             }
49527             else {
49528                 Ext.apply(attr, {
49529                     translate: {
49530                         x: (bbox.x + bbox.width) / 2,
49531                         y: (bbox.y + bbox.height) / 2
49532                     }
49533                 });
49534             }
49535             Ext.apply(attr, endMarkerStyle);
49536             shadow = Ext.chart.Shape[type](chart.surface, Ext.apply({}, {
49537                 x: 0,
49538                 y: 0,
49539                 group: shadowGroups[i]
49540             }, attr));
49541             shadows.push(shadow);
49542         }
49543     },
49544
49545     
49546     drawSeries: function() {
49547         var me = this,
49548             chart = me.chart,
49549             store = chart.substore || chart.store,
49550             group = me.group,
49551             enableShadows = chart.shadow,
49552             shadowGroups = me.shadowGroups,
49553             shadowAttributes = me.shadowAttributes,
49554             lnsh = shadowGroups.length,
49555             sprite, attrs, attr, ln, i, endMarkerStyle, shindex, type, shadows,
49556             rendererAttributes, shadowAttribute;
49557
49558         endMarkerStyle = Ext.apply(me.markerStyle, me.markerConfig);
49559         type = endMarkerStyle.type;
49560         delete endMarkerStyle.type;
49561
49562         
49563         if (!store || !store.getCount()) {
49564             return;
49565         }
49566
49567         me.unHighlightItem();
49568         me.cleanHighlights();
49569
49570         attrs = me.getPaths();
49571         ln = attrs.length;
49572         for (i = 0; i < ln; i++) {
49573             attr = attrs[i];
49574             sprite = group.getAt(i);
49575             Ext.apply(attr, endMarkerStyle);
49576
49577             
49578             if (!sprite) {
49579                 sprite = me.createPoint(attr, type);
49580                 if (enableShadows) {
49581                     me.createShadow(sprite, endMarkerStyle, type);
49582                 }
49583             }
49584
49585             shadows = sprite.shadows;
49586             if (chart.animate) {
49587                 rendererAttributes = me.renderer(sprite, store.getAt(i), { translate: attr }, i, store);
49588                 sprite._to = rendererAttributes;
49589                 me.onAnimate(sprite, {
49590                     to: rendererAttributes
49591                 });
49592                 
49593                 for (shindex = 0; shindex < lnsh; shindex++) {
49594                     shadowAttribute = Ext.apply({}, shadowAttributes[shindex]);
49595                     rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({}, { 
49596                         translate: {
49597                             x: attr.x + (shadowAttribute.translate? shadowAttribute.translate.x : 0),
49598                             y: attr.y + (shadowAttribute.translate? shadowAttribute.translate.y : 0)
49599                         } 
49600                     }, shadowAttribute), i, store);
49601                     me.onAnimate(shadows[shindex], { to: rendererAttributes });
49602                 }
49603             }
49604             else {
49605                 rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply({ translate: attr }, { hidden: false }), i, store);
49606                 sprite.setAttributes(rendererAttributes, true);
49607                 
49608                 for (shindex = 0; shindex < lnsh; shindex++) {
49609                     shadowAttribute = shadowAttributes[shindex];
49610                     rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({ 
49611                         x: attr.x,
49612                         y: attr.y
49613                     }, shadowAttribute), i, store);
49614                     shadows[shindex].setAttributes(rendererAttributes, true);
49615                 }
49616             }
49617             me.items[i].sprite = sprite;
49618         }
49619
49620         
49621         ln = group.getCount();
49622         for (i = attrs.length; i < ln; i++) {
49623             group.getAt(i).hide(true);
49624         }
49625         me.renderLabels();
49626         me.renderCallouts();
49627     },
49628     
49629     
49630     onCreateLabel: function(storeItem, item, i, display) {
49631         var me = this,
49632             group = me.labelsGroup,
49633             config = me.label,
49634             endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle),
49635             bbox = me.bbox;
49636         
49637         return me.chart.surface.add(Ext.apply({
49638             type: 'text',
49639             group: group,
49640             x: item.point[0],
49641             y: bbox.y + bbox.height / 2
49642         }, endLabelStyle));
49643     },
49644     
49645     
49646     onPlaceLabel: function(label, storeItem, item, i, display, animate) {
49647         var me = this,
49648             chart = me.chart,
49649             resizing = chart.resizing,
49650             config = me.label,
49651             format = config.renderer,
49652             field = config.field,
49653             bbox = me.bbox,
49654             x = item.point[0],
49655             y = item.point[1],
49656             radius = item.sprite.attr.radius,
49657             bb, width, height, anim;
49658         
49659         label.setAttributes({
49660             text: format(storeItem.get(field)),
49661             hidden: true
49662         }, true);
49663         
49664         if (display == 'rotate') {
49665             label.setAttributes({
49666                 'text-anchor': 'start',
49667                 'rotation': {
49668                     x: x,
49669                     y: y,
49670                     degrees: -45
49671                 }
49672             }, true);
49673             
49674             bb = label.getBBox();
49675             width = bb.width;
49676             height = bb.height;
49677             x = x < bbox.x? bbox.x : x;
49678             x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
49679             y = (y - height < bbox.y)? bbox.y + height : y;
49680         
49681         } else if (display == 'under' || display == 'over') {
49682             
49683             bb = item.sprite.getBBox();
49684             bb.width = bb.width || (radius * 2);
49685             bb.height = bb.height || (radius * 2);
49686             y = y + (display == 'over'? -bb.height : bb.height);
49687             
49688             bb = label.getBBox();
49689             width = bb.width/2;
49690             height = bb.height/2;
49691             x = x - width < bbox.x ? bbox.x + width : x;
49692             x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
49693             y = y - height < bbox.y? bbox.y + height : y;
49694             y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
49695         }
49696
49697         if (!chart.animate) {
49698             label.setAttributes({
49699                 x: x,
49700                 y: y
49701             }, true);
49702             label.show(true);
49703         }
49704         else {
49705             if (resizing) {
49706                 anim = item.sprite.getActiveAnimation();
49707                 if (anim) {
49708                     anim.on('afteranimate', function() {
49709                         label.setAttributes({
49710                             x: x,
49711                             y: y
49712                         }, true);
49713                         label.show(true);
49714                     });   
49715                 }
49716                 else {
49717                     label.show(true);
49718                 }
49719             }
49720             else {
49721                 me.onAnimate(label, {
49722                     to: {
49723                         x: x,
49724                         y: y
49725                     }
49726                 });
49727             }
49728         }
49729     },
49730     
49731     
49732     onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
49733         var me = this,
49734             chart = me.chart,
49735             surface = chart.surface,
49736             resizing = chart.resizing,
49737             config = me.callouts,
49738             items = me.items,
49739             cur = item.point,
49740             normal,
49741             bbox = callout.label.getBBox(),
49742             offsetFromViz = 30,
49743             offsetToSide = 10,
49744             offsetBox = 3,
49745             boxx, boxy, boxw, boxh,
49746             p, clipRect = me.bbox,
49747             x, y;
49748     
49749         
49750         normal = [Math.cos(Math.PI /4), -Math.sin(Math.PI /4)];
49751         x = cur[0] + normal[0] * offsetFromViz;
49752         y = cur[1] + normal[1] * offsetFromViz;
49753         
49754         
49755         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
49756         boxy = y - bbox.height /2 - offsetBox;
49757         boxw = bbox.width + 2 * offsetBox;
49758         boxh = bbox.height + 2 * offsetBox;
49759         
49760         
49761         
49762         if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
49763             normal[0] *= -1;
49764         }
49765         if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
49766             normal[1] *= -1;
49767         }
49768     
49769         
49770         x = cur[0] + normal[0] * offsetFromViz;
49771         y = cur[1] + normal[1] * offsetFromViz;
49772         
49773         
49774         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
49775         boxy = y - bbox.height /2 - offsetBox;
49776         boxw = bbox.width + 2 * offsetBox;
49777         boxh = bbox.height + 2 * offsetBox;
49778         
49779         if (chart.animate) {
49780             
49781             me.onAnimate(callout.lines, {
49782                 to: {
49783                     path: ["M", cur[0], cur[1], "L", x, y, "Z"]
49784                 }
49785             }, true);
49786             
49787             me.onAnimate(callout.box, {
49788                 to: {
49789                     x: boxx,
49790                     y: boxy,
49791                     width: boxw,
49792                     height: boxh
49793                 }
49794             }, true);
49795             
49796             me.onAnimate(callout.label, {
49797                 to: {
49798                     x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
49799                     y: y
49800                 }
49801             }, true);
49802         } else {
49803             
49804             callout.lines.setAttributes({
49805                 path: ["M", cur[0], cur[1], "L", x, y, "Z"]
49806             }, true);
49807             
49808             callout.box.setAttributes({
49809                 x: boxx,
49810                 y: boxy,
49811                 width: boxw,
49812                 height: boxh
49813             }, true);
49814             
49815             callout.label.setAttributes({
49816                 x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
49817                 y: y
49818             }, true);
49819         }
49820         for (p in callout) {
49821             callout[p].show(true);
49822         }
49823     },
49824
49825     
49826     onAnimate: function(sprite, attr) {
49827         sprite.show();
49828         return this.callParent(arguments);
49829     },
49830
49831     isItemInPoint: function(x, y, item) {
49832         var point,
49833             tolerance = 10,
49834             abs = Math.abs;
49835
49836         function dist(point) {
49837             var dx = abs(point[0] - x),
49838                 dy = abs(point[1] - y);
49839             return Math.sqrt(dx * dx + dy * dy);
49840         }
49841         point = item.point;
49842         return (point[0] - tolerance <= x && point[0] + tolerance >= x &&
49843             point[1] - tolerance <= y && point[1] + tolerance >= y);
49844     }
49845 });
49846
49847
49848
49849 Ext.define('Ext.chart.theme.Base', {
49850
49851     
49852
49853     requires: ['Ext.chart.theme.Theme'],
49854
49855     
49856
49857     constructor: function(config) {
49858         Ext.chart.theme.call(this, config, {
49859             background: false,
49860             axis: {
49861                 stroke: '#444',
49862                 'stroke-width': 1
49863             },
49864             axisLabelTop: {
49865                 fill: '#444',
49866                 font: '12px Arial, Helvetica, sans-serif',
49867                 spacing: 2,
49868                 padding: 5,
49869                 renderer: function(v) { return v; }
49870             },
49871             axisLabelRight: {
49872                 fill: '#444',
49873                 font: '12px Arial, Helvetica, sans-serif',
49874                 spacing: 2,
49875                 padding: 5,
49876                 renderer: function(v) { return v; }
49877             },
49878             axisLabelBottom: {
49879                 fill: '#444',
49880                 font: '12px Arial, Helvetica, sans-serif',
49881                 spacing: 2,
49882                 padding: 5,
49883                 renderer: function(v) { return v; }
49884             },
49885             axisLabelLeft: {
49886                 fill: '#444',
49887                 font: '12px Arial, Helvetica, sans-serif',
49888                 spacing: 2,
49889                 padding: 5,
49890                 renderer: function(v) { return v; }
49891             },
49892             axisTitleTop: {
49893                 font: 'bold 18px Arial',
49894                 fill: '#444'
49895             },
49896             axisTitleRight: {
49897                 font: 'bold 18px Arial',
49898                 fill: '#444',
49899                 rotate: {
49900                     x:0, y:0,
49901                     degrees: 270
49902                 }
49903             },
49904             axisTitleBottom: {
49905                 font: 'bold 18px Arial',
49906                 fill: '#444'
49907             },
49908             axisTitleLeft: {
49909                 font: 'bold 18px Arial',
49910                 fill: '#444',
49911                 rotate: {
49912                     x:0, y:0,
49913                     degrees: 270
49914                 }
49915             },
49916             series: {
49917                 'stroke-width': 0
49918             },
49919             seriesLabel: {
49920                 font: '12px Arial',
49921                 fill: '#333'
49922             },
49923             marker: {
49924                 stroke: '#555',
49925                 fill: '#000',
49926                 radius: 3,
49927                 size: 3
49928             },
49929             colors: [ "#94ae0a", "#115fa6","#a61120", "#ff8809", "#ffd13e", "#a61187", "#24ad9a", "#7c7474", "#a66111"],
49930             seriesThemes: [{
49931                 fill: "#115fa6"
49932             }, {
49933                 fill: "#94ae0a"
49934             }, {
49935                 fill: "#a61120"
49936             }, {
49937                 fill: "#ff8809"
49938             }, {
49939                 fill: "#ffd13e"
49940             }, {
49941                 fill: "#a61187"
49942             }, {
49943                 fill: "#24ad9a"
49944             }, {
49945                 fill: "#7c7474"
49946             }, {
49947                 fill: "#a66111"
49948             }],
49949             markerThemes: [{
49950                 fill: "#115fa6",
49951                 type: 'circle' 
49952             }, {
49953                 fill: "#94ae0a",
49954                 type: 'cross'
49955             }, {
49956                 fill: "#a61120",
49957                 type: 'plus'
49958             }]
49959         });
49960     }
49961 }, function() {
49962     var palette = ['#b1da5a', '#4ce0e7', '#e84b67', '#da5abd', '#4d7fe6', '#fec935'],
49963         names = ['Green', 'Sky', 'Red', 'Purple', 'Blue', 'Yellow'],
49964         i = 0, j = 0, l = palette.length, themes = Ext.chart.theme,
49965         categories = [['#f0a50a', '#c20024', '#2044ba', '#810065', '#7eae29'],
49966                       ['#6d9824', '#87146e', '#2a9196', '#d39006', '#1e40ac'],
49967                       ['#fbbc29', '#ce2e4e', '#7e0062', '#158b90', '#57880e'],
49968                       ['#ef5773', '#fcbd2a', '#4f770d', '#1d3eaa', '#9b001f'],
49969                       ['#7eae29', '#fdbe2a', '#910019', '#27b4bc', '#d74dbc'],
49970                       ['#44dce1', '#0b2592', '#996e05', '#7fb325', '#b821a1']],
49971         cats = categories.length;
49972     
49973     
49974     for (; i < l; i++) {
49975         themes[names[i]] = (function(color) {
49976             return Ext.extend(themes.Base, {
49977                 constructor: function(config) {
49978                     themes.Base.prototype.constructor.call(this, Ext.apply({
49979                         baseColor: color
49980                     }, config));
49981                 }
49982             });
49983         })(palette[i]);
49984     }
49985     
49986     
49987     for (i = 0; i < cats; i++) {
49988         themes['Category' + (i + 1)] = (function(category) {
49989             return Ext.extend(themes.Base, {
49990                 constructor: function(config) {
49991                     themes.Base.prototype.constructor.call(this, Ext.apply({
49992                         colors: category
49993                     }, config));
49994                 }
49995             });
49996         })(categories[i]);
49997     }
49998 });
49999
50000
50001 Ext.define('Ext.data.ArrayStore', {
50002     extend: 'Ext.data.Store',
50003     alias: 'store.array',
50004     uses: ['Ext.data.reader.Array'],
50005
50006     
50007     constructor: function(config) {
50008         config = config || {};
50009
50010         Ext.applyIf(config, {
50011             proxy: {
50012                 type: 'memory',
50013                 reader: 'array'
50014             }
50015         });
50016
50017         this.callParent([config]);
50018     },
50019
50020     loadData: function(data, append) {
50021         if (this.expandData === true) {
50022             var r = [],
50023                 i = 0,
50024                 ln = data.length;
50025
50026             for (; i < ln; i++) {
50027                 r[r.length] = [data[i]];
50028             }
50029
50030             data = r;
50031         }
50032
50033         this.callParent([data, append]);
50034     }
50035 }, function() {
50036     
50037     Ext.data.SimpleStore = Ext.data.ArrayStore;
50038     
50039 });
50040
50041
50042 Ext.define('Ext.data.Batch', {
50043     mixins: {
50044         observable: 'Ext.util.Observable'
50045     },
50046     
50047     
50048     autoStart: false,
50049     
50050     
50051     current: -1,
50052     
50053     
50054     total: 0,
50055     
50056     
50057     isRunning: false,
50058     
50059     
50060     isComplete: false,
50061     
50062     
50063     hasException: false,
50064     
50065     
50066     pauseOnException: true,
50067     
50068     constructor: function(config) {   
50069         var me = this;
50070                      
50071         me.addEvents(
50072           
50073           'complete',
50074           
50075           
50076           'exception',
50077           
50078           
50079           'operationcomplete'
50080         );
50081         
50082         me.mixins.observable.constructor.call(me, config);
50083         
50084         
50085         me.operations = [];
50086     },
50087     
50088     
50089     add: function(operation) {
50090         this.total++;
50091         
50092         operation.setBatch(this);
50093         
50094         this.operations.push(operation);
50095     },
50096     
50097     
50098     start: function() {
50099         this.hasException = false;
50100         this.isRunning = true;
50101         
50102         this.runNextOperation();
50103     },
50104     
50105     
50106     runNextOperation: function() {
50107         this.runOperation(this.current + 1);
50108     },
50109     
50110     
50111     pause: function() {
50112         this.isRunning = false;
50113     },
50114     
50115     
50116     runOperation: function(index) {
50117         var me = this,
50118             operations = me.operations,
50119             operation  = operations[index],
50120             onProxyReturn;
50121         
50122         if (operation === undefined) {
50123             me.isRunning  = false;
50124             me.isComplete = true;
50125             me.fireEvent('complete', me, operations[operations.length - 1]);
50126         } else {
50127             me.current = index;
50128             
50129             onProxyReturn = function(operation) {
50130                 var hasException = operation.hasException();
50131                 
50132                 if (hasException) {
50133                     me.hasException = true;
50134                     me.fireEvent('exception', me, operation);
50135                 } else {
50136                     me.fireEvent('operationcomplete', me, operation);
50137                 }
50138
50139                 if (hasException && me.pauseOnException) {
50140                     me.pause();
50141                 } else {
50142                     operation.setCompleted();
50143                     me.runNextOperation();
50144                 }
50145             };
50146             
50147             operation.setStarted();
50148             
50149             me.proxy[operation.action](operation, onProxyReturn, me);
50150         }
50151     }
50152 });
50153
50154 Ext.define('Ext.data.BelongsToAssociation', {
50155     extend: 'Ext.data.Association',
50156
50157     alias: 'association.belongsto',
50158
50159     
50160
50161     
50162
50163     
50164     
50165     
50166
50167     constructor: function(config) {
50168         this.callParent(arguments);
50169
50170         var me             = this,
50171             ownerProto     = me.ownerModel.prototype,
50172             associatedName = me.associatedName,
50173             getterName     = me.getterName || 'get' + associatedName,
50174             setterName     = me.setterName || 'set' + associatedName;
50175
50176         Ext.applyIf(me, {
50177             name        : associatedName,
50178             foreignKey  : associatedName.toLowerCase() + "_id",
50179             instanceName: associatedName + 'BelongsToInstance',
50180             associationKey: associatedName.toLowerCase()
50181         });
50182
50183         ownerProto[getterName] = me.createGetter();
50184         ownerProto[setterName] = me.createSetter();
50185     },
50186
50187     
50188     createSetter: function() {
50189         var me              = this,
50190             ownerModel      = me.ownerModel,
50191             associatedModel = me.associatedModel,
50192             foreignKey      = me.foreignKey,
50193             primaryKey      = me.primaryKey;
50194
50195         
50196         return function(value, options, scope) {
50197             this.set(foreignKey, value);
50198
50199             if (typeof options == 'function') {
50200                 options = {
50201                     callback: options,
50202                     scope: scope || this
50203                 };
50204             }
50205
50206             if (Ext.isObject(options)) {
50207                 return this.save(options);
50208             }
50209         };
50210     },
50211
50212     
50213     createGetter: function() {
50214         var me              = this,
50215             ownerModel      = me.ownerModel,
50216             associatedName  = me.associatedName,
50217             associatedModel = me.associatedModel,
50218             foreignKey      = me.foreignKey,
50219             primaryKey      = me.primaryKey,
50220             instanceName    = me.instanceName;
50221
50222         
50223         return function(options, scope) {
50224             options = options || {};
50225
50226             var foreignKeyId = this.get(foreignKey),
50227                 instance, callbackFn;
50228
50229             if (this[instanceName] === undefined) {
50230                 instance = Ext.ModelManager.create({}, associatedName);
50231                 instance.set(primaryKey, foreignKeyId);
50232
50233                 if (typeof options == 'function') {
50234                     options = {
50235                         callback: options,
50236                         scope: scope || this
50237                     };
50238                 }
50239
50240                 associatedModel.load(foreignKeyId, options);
50241             } else {
50242                 instance = this[instanceName];
50243
50244                 
50245                 
50246                 
50247                 if (typeof options == 'function') {
50248                     options.call(scope || this, instance);
50249                 }
50250
50251                 if (options.success) {
50252                     options.success.call(scope || this, instance);
50253                 }
50254
50255                 if (options.callback) {
50256                     options.callback.call(scope || this, instance);
50257                 }
50258
50259                 return instance;
50260             }
50261         };
50262     },
50263
50264     
50265     read: function(record, reader, associationData){
50266         record[this.instanceName] = reader.read([associationData]).records[0];
50267     }
50268 });
50269
50270
50271 Ext.define('Ext.data.BufferStore', {
50272     extend: 'Ext.data.Store',
50273     alias: 'store.buffer',
50274     sortOnLoad: false,
50275     filterOnLoad: false,
50276     
50277     constructor: function() {
50278         Ext.Error.raise('The BufferStore class has been deprecated. Instead, specify the buffered config option on Ext.data.Store');
50279     }
50280 });
50281
50282
50283 Ext.define('Ext.direct.Manager', {
50284     
50285     
50286     singleton: true,
50287    
50288     mixins: {
50289         observable: 'Ext.util.Observable'
50290     },
50291     
50292     requires: ['Ext.util.MixedCollection'],
50293     
50294     statics: {
50295         exceptions: {
50296             TRANSPORT: 'xhr',
50297             PARSE: 'parse',
50298             LOGIN: 'login',
50299             SERVER: 'exception'
50300         }
50301     },
50302     
50303     
50304    
50305     constructor: function(){
50306         var me = this;
50307        
50308         me.addEvents(
50309             
50310             'event',
50311             
50312             'exception'
50313         );
50314         me.transactions = Ext.create('Ext.util.MixedCollection');
50315         me.providers = Ext.create('Ext.util.MixedCollection');
50316         
50317         me.mixins.observable.constructor.call(me);
50318     },
50319     
50320     
50321     addProvider : function(provider){
50322         var me = this,
50323             args = arguments,
50324             i = 0,
50325             len;
50326             
50327         if (args.length > 1) {
50328             for (len = args.length; i < len; ++i) {
50329                 me.addProvider(args[i]);
50330             }
50331             return;
50332         }
50333
50334         
50335         if (!provider.isProvider) {
50336             provider = Ext.create('direct.' + provider.type + 'provider', provider);
50337         }
50338         me.providers.add(provider);
50339         provider.on('data', me.onProviderData, me);
50340
50341
50342         if (!provider.isConnected()) {
50343             provider.connect();
50344         }
50345
50346         return provider;
50347     },
50348     
50349     
50350     getProvider : function(id){
50351         return id.isProvider ? id : this.providers.get(id);
50352     },
50353     
50354     
50355     removeProvider : function(provider){
50356         var me = this,
50357             providers = me.providers,
50358             provider = provider.isProvider ? provider : providers.get(provider);
50359             
50360         if (provider) {
50361             provider.un('data', me.onProviderData, me);
50362             providers.remove(provider);
50363             return provider;
50364         }
50365         return null;
50366     },
50367     
50368     
50369     addTransaction: function(transaction){
50370         this.transactions.add(transaction);
50371         return transaction;
50372     },
50373
50374     
50375     removeTransaction: function(transaction){
50376         transaction = this.getTransaction(transaction);
50377         this.transactions.remove(transaction);
50378         return transaction;
50379     },
50380
50381     
50382     getTransaction: function(transaction){
50383         return transaction.isTransaction ? transaction : this.transactions.get(transaction);
50384     },
50385     
50386     onProviderData : function(provider, event){
50387         var me = this,
50388             i = 0,
50389             len;
50390             
50391         if (Ext.isArray(event)) {
50392             for (len = event.length; i < len; ++i) {
50393                 me.onProviderData(provider, event[i]);
50394             }
50395             return;
50396         }
50397         if (event.name && event.name != 'event' && event.name != 'exception') {
50398             me.fireEvent(event.name, event);
50399         } else if (event.type == 'exception') {
50400             me.fireEvent('exception', event);
50401         }
50402         me.fireEvent('event', event, provider);
50403     }
50404 }, function(){
50405     
50406     Ext.Direct = Ext.direct.Manager;
50407 });
50408
50409
50410 Ext.define('Ext.data.proxy.Direct', {
50411     
50412     
50413     extend: 'Ext.data.proxy.Server',
50414     alternateClassName: 'Ext.data.DirectProxy',
50415     
50416     alias: 'proxy.direct',
50417     
50418     requires: ['Ext.direct.Manager'],
50419     
50420     
50421    
50422    
50423     paramOrder: undefined,
50424
50425     
50426     paramsAsHash: true,
50427
50428     
50429     directFn : undefined,
50430     
50431     
50432     
50433     
50434     
50435     
50436     paramOrderRe: /[\s,|]/,
50437     
50438     constructor: function(config){
50439         var me = this;
50440         
50441         Ext.apply(me, config);
50442         if (Ext.isString(me.paramOrder)) {
50443             me.paramOrder = me.paramOrder.split(me.paramOrderRe);
50444         }
50445         me.callParent(arguments);
50446     },
50447     
50448     doRequest: function(operation, callback, scope) {
50449         var me = this,
50450             writer = me.getWriter(),
50451             request = me.buildRequest(operation, callback, scope),
50452             fn = me.api[request.action]  || me.directFn,
50453             args = [],
50454             params = request.params,
50455             paramOrder = me.paramOrder,
50456             method,
50457             i = 0,
50458             len;
50459             
50460         if (!fn) {
50461             Ext.Error.raise('No direct function specified for this proxy');
50462         }
50463             
50464         if (operation.allowWrite()) {
50465             request = writer.write(request);
50466         }
50467         
50468         if (operation.action == 'read') {
50469             
50470             method = fn.directCfg.method;
50471             
50472             if (method.ordered) {
50473                 if (method.len > 0) {
50474                     if (paramOrder) {
50475                         for (len = paramOrder.length; i < len; ++i) {
50476                             args.push(params[paramOrder[i]]);
50477                         }
50478                     } else if (me.paramsAsHash) {
50479                         args.push(params);
50480                     }
50481                 }
50482             } else {
50483                 args.push(params);
50484             }
50485         } else {
50486             args.push(request.jsonData);
50487         }
50488         
50489         Ext.apply(request, {
50490             args: args,
50491             directFn: fn
50492         });
50493         args.push(me.createRequestCallback(request, operation, callback, scope), me);
50494         fn.apply(window, args);
50495     },
50496     
50497     
50498     applyEncoding: function(value){
50499         return value;
50500     },
50501     
50502     createRequestCallback: function(request, operation, callback, scope){
50503         var me = this;
50504         
50505         return function(data, event){
50506             me.processResponse(event.status, operation, request, event, callback, scope);
50507         };
50508     },
50509     
50510     
50511     extractResponseData: function(response){
50512         return Ext.isDefined(response.result) ? response.result : response.data;
50513     },
50514     
50515     
50516     setException: function(operation, response) {
50517         operation.setException(response.message);
50518     },
50519     
50520     
50521     buildUrl: function(){
50522         return '';
50523     }
50524 });
50525
50526
50527
50528 Ext.define('Ext.data.DirectStore', {
50529     
50530     
50531     extend: 'Ext.data.Store',
50532     
50533     alias: 'store.direct',
50534     
50535     requires: ['Ext.data.proxy.Direct'],
50536    
50537     
50538    
50539    constructor : function(config){
50540         config = Ext.apply({}, config);
50541         if (!config.proxy) {
50542             var proxy = {
50543                 type: 'direct',
50544                 reader: {
50545                     type: 'json'
50546                 }
50547             };
50548             Ext.copyTo(proxy, config, 'paramOrder,paramsAsHash,directFn,api,simpleSortMode');
50549             Ext.copyTo(proxy.reader, config, 'totalProperty,root,idProperty');
50550             config.proxy = proxy;
50551         }
50552         this.callParent([config]);
50553     }    
50554 });
50555
50556
50557
50558 Ext.define('Ext.util.Inflector', {
50559
50560     
50561
50562     singleton: true,
50563
50564     
50565
50566     
50567     plurals: [
50568         [(/(quiz)$/i),                "$1zes"  ],
50569         [(/^(ox)$/i),                 "$1en"   ],
50570         [(/([m|l])ouse$/i),           "$1ice"  ],
50571         [(/(matr|vert|ind)ix|ex$/i),  "$1ices" ],
50572         [(/(x|ch|ss|sh)$/i),          "$1es"   ],
50573         [(/([^aeiouy]|qu)y$/i),       "$1ies"  ],
50574         [(/(hive)$/i),                "$1s"    ],
50575         [(/(?:([^f])fe|([lr])f)$/i),  "$1$2ves"],
50576         [(/sis$/i),                   "ses"    ],
50577         [(/([ti])um$/i),              "$1a"    ],
50578         [(/(buffal|tomat|potat)o$/i), "$1oes"  ],
50579         [(/(bu)s$/i),                 "$1ses"  ],
50580         [(/(alias|status|sex)$/i),    "$1es"   ],
50581         [(/(octop|vir)us$/i),         "$1i"    ],
50582         [(/(ax|test)is$/i),           "$1es"   ],
50583         [(/^person$/),                "people" ],
50584         [(/^man$/),                   "men"    ],
50585         [(/^(child)$/),               "$1ren"  ],
50586         [(/s$/i),                     "s"      ],
50587         [(/$/),                       "s"      ]
50588     ],
50589     
50590     
50591     singulars: [
50592       [(/(quiz)zes$/i),                                                    "$1"     ],
50593       [(/(matr)ices$/i),                                                   "$1ix"   ],
50594       [(/(vert|ind)ices$/i),                                               "$1ex"   ],
50595       [(/^(ox)en/i),                                                       "$1"     ],
50596       [(/(alias|status)es$/i),                                             "$1"     ],
50597       [(/(octop|vir)i$/i),                                                 "$1us"   ],
50598       [(/(cris|ax|test)es$/i),                                             "$1is"   ],
50599       [(/(shoe)s$/i),                                                      "$1"     ],
50600       [(/(o)es$/i),                                                        "$1"     ],
50601       [(/(bus)es$/i),                                                      "$1"     ],
50602       [(/([m|l])ice$/i),                                                   "$1ouse" ],
50603       [(/(x|ch|ss|sh)es$/i),                                               "$1"     ],
50604       [(/(m)ovies$/i),                                                     "$1ovie" ],
50605       [(/(s)eries$/i),                                                     "$1eries"],
50606       [(/([^aeiouy]|qu)ies$/i),                                            "$1y"    ],
50607       [(/([lr])ves$/i),                                                    "$1f"    ],
50608       [(/(tive)s$/i),                                                      "$1"     ],
50609       [(/(hive)s$/i),                                                      "$1"     ],
50610       [(/([^f])ves$/i),                                                    "$1fe"   ],
50611       [(/(^analy)ses$/i),                                                  "$1sis"  ],
50612       [(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i), "$1$2sis"],
50613       [(/([ti])a$/i),                                                      "$1um"   ],
50614       [(/(n)ews$/i),                                                       "$1ews"  ],
50615       [(/people$/i),                                                       "person" ],
50616       [(/s$/i),                                                            ""       ]
50617     ],
50618     
50619     
50620      uncountable: [
50621         "sheep",
50622         "fish",
50623         "series",
50624         "species",
50625         "money",
50626         "rice",
50627         "information",
50628         "equipment",
50629         "grass",
50630         "mud",
50631         "offspring",
50632         "deer",
50633         "means"
50634     ],
50635     
50636     
50637     singular: function(matcher, replacer) {
50638         this.singulars.unshift([matcher, replacer]);
50639     },
50640     
50641     
50642     plural: function(matcher, replacer) {
50643         this.plurals.unshift([matcher, replacer]);
50644     },
50645     
50646     
50647     clearSingulars: function() {
50648         this.singulars = [];
50649     },
50650     
50651     
50652     clearPlurals: function() {
50653         this.plurals = [];
50654     },
50655     
50656     
50657     isTransnumeral: function(word) {
50658         return Ext.Array.indexOf(this.uncountable, word) != -1;
50659     },
50660
50661     
50662     pluralize: function(word) {
50663         if (this.isTransnumeral(word)) {
50664             return word;
50665         }
50666
50667         var plurals = this.plurals,
50668             length  = plurals.length,
50669             tuple, regex, i;
50670         
50671         for (i = 0; i < length; i++) {
50672             tuple = plurals[i];
50673             regex = tuple[0];
50674             
50675             if (regex == word || (regex.test && regex.test(word))) {
50676                 return word.replace(regex, tuple[1]);
50677             }
50678         }
50679         
50680         return word;
50681     },
50682     
50683     
50684     singularize: function(word) {
50685         if (this.isTransnumeral(word)) {
50686             return word;
50687         }
50688
50689         var singulars = this.singulars,
50690             length    = singulars.length,
50691             tuple, regex, i;
50692         
50693         for (i = 0; i < length; i++) {
50694             tuple = singulars[i];
50695             regex = tuple[0];
50696             
50697             if (regex == word || (regex.test && regex.test(word))) {
50698                 return word.replace(regex, tuple[1]);
50699             }
50700         }
50701         
50702         return word;
50703     },
50704     
50705     
50706     classify: function(word) {
50707         return Ext.String.capitalize(this.singularize(word));
50708     },
50709     
50710     
50711     ordinalize: function(number) {
50712         var parsed = parseInt(number, 10),
50713             mod10  = parsed % 10,
50714             mod100 = parsed % 100;
50715         
50716         
50717         if (11 <= mod100 && mod100 <= 13) {
50718             return number + "th";
50719         } else {
50720             switch(mod10) {
50721                 case 1 : return number + "st";
50722                 case 2 : return number + "nd";
50723                 case 3 : return number + "rd";
50724                 default: return number + "th";
50725             }
50726         }
50727     }
50728 }, function() {
50729     
50730     var irregulars = {
50731             alumnus: 'alumni',
50732             cactus : 'cacti',
50733             focus  : 'foci',
50734             nucleus: 'nuclei',
50735             radius: 'radii',
50736             stimulus: 'stimuli',
50737             ellipsis: 'ellipses',
50738             paralysis: 'paralyses',
50739             oasis: 'oases',
50740             appendix: 'appendices',
50741             index: 'indexes',
50742             beau: 'beaux',
50743             bureau: 'bureaux',
50744             tableau: 'tableaux',
50745             woman: 'women',
50746             child: 'children',
50747             man: 'men',
50748             corpus:     'corpora',
50749             criterion: 'criteria',
50750             curriculum: 'curricula',
50751             genus: 'genera',
50752             memorandum: 'memoranda',
50753             phenomenon: 'phenomena',
50754             foot: 'feet',
50755             goose: 'geese',
50756             tooth: 'teeth',
50757             antenna: 'antennae',
50758             formula: 'formulae',
50759             nebula: 'nebulae',
50760             vertebra: 'vertebrae',
50761             vita: 'vitae'
50762         },
50763         singular;
50764     
50765     for (singular in irregulars) {
50766         this.plural(singular, irregulars[singular]);
50767         this.singular(irregulars[singular], singular);
50768     }
50769 });
50770
50771 Ext.define('Ext.data.HasManyAssociation', {
50772     extend: 'Ext.data.Association',
50773     requires: ['Ext.util.Inflector'],
50774
50775     alias: 'association.hasmany',
50776
50777     
50778     
50779     
50780     
50781     
50782     
50783     
50784     
50785     
50786     
50787     
50788     
50789     constructor: function(config) {
50790         var me = this,
50791             ownerProto,
50792             name;
50793             
50794         me.callParent(arguments);
50795         
50796         me.name = me.name || Ext.util.Inflector.pluralize(me.associatedName.toLowerCase());
50797         
50798         ownerProto = me.ownerModel.prototype;
50799         name = me.name;
50800         
50801         Ext.applyIf(me, {
50802             storeName : name + "Store",
50803             foreignKey: me.ownerName.toLowerCase() + "_id"
50804         });
50805         
50806         ownerProto[name] = me.createStore();
50807     },
50808     
50809     
50810     createStore: function() {
50811         var that            = this,
50812             associatedModel = that.associatedModel,
50813             storeName       = that.storeName,
50814             foreignKey      = that.foreignKey,
50815             primaryKey      = that.primaryKey,
50816             filterProperty  = that.filterProperty,
50817             autoLoad        = that.autoLoad,
50818             storeConfig     = that.storeConfig || {};
50819         
50820         return function() {
50821             var me = this,
50822                 config, filter,
50823                 modelDefaults = {};
50824                 
50825             if (me[storeName] === undefined) {
50826                 if (filterProperty) {
50827                     filter = {
50828                         property  : filterProperty,
50829                         value     : me.get(filterProperty),
50830                         exactMatch: true
50831                     };
50832                 } else {
50833                     filter = {
50834                         property  : foreignKey,
50835                         value     : me.get(primaryKey),
50836                         exactMatch: true
50837                     };
50838                 }
50839                 
50840                 modelDefaults[foreignKey] = me.get(primaryKey);
50841                 
50842                 config = Ext.apply({}, storeConfig, {
50843                     model        : associatedModel,
50844                     filters      : [filter],
50845                     remoteFilter : false,
50846                     modelDefaults: modelDefaults
50847                 });
50848                 
50849                 me[storeName] = Ext.create('Ext.data.Store', config);
50850                 if (autoLoad) {
50851                     me[storeName].load();
50852                 }
50853             }
50854             
50855             return me[storeName];
50856         };
50857     },
50858     
50859     
50860     read: function(record, reader, associationData){
50861         var store = record[this.name](),
50862             inverse;
50863     
50864         store.add(reader.read(associationData).records);
50865     
50866         
50867         
50868         inverse = this.associatedModel.prototype.associations.findBy(function(assoc){
50869             return assoc.type === 'belongsTo' && assoc.associatedName === record.$className;
50870         });
50871     
50872         
50873         if (inverse) {
50874             store.data.each(function(associatedRecord){
50875                 associatedRecord[inverse.instanceName] = record;
50876             });
50877         }
50878     }
50879 });
50880
50881 Ext.define('Ext.data.JsonP', {
50882     
50883     
50884     
50885     singleton: true,
50886     
50887     statics: {
50888         requestCount: 0,
50889         requests: {}
50890     },
50891     
50892     
50893     
50894     
50895     timeout: 30000,
50896     
50897     
50898     disableCaching: true,
50899    
50900     
50901     disableCachingParam: '_dc',
50902    
50903     
50904     callbackKey: 'callback',
50905    
50906     
50907     request: function(options){
50908         options = Ext.apply({}, options);
50909        
50910         if (!options.url) {
50911             Ext.Error.raise('A url must be specified for a JSONP request.');
50912         }
50913         
50914         var me = this, 
50915             disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching, 
50916             cacheParam = options.disableCachingParam || me.disableCachingParam, 
50917             id = ++me.statics().requestCount, 
50918             callbackName = 'callback' + id, 
50919             callbackKey = options.callbackKey || me.callbackKey, 
50920             timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout, 
50921             params = Ext.apply({}, options.params), 
50922             url = options.url,
50923             request, 
50924             script;
50925             
50926         params[callbackKey] = 'Ext.data.JsonP.' + callbackName;
50927         if (disableCaching) {
50928             params[cacheParam] = new Date().getTime();
50929         }
50930         
50931         script = me.createScript(url, params);
50932         
50933         me.statics().requests[id] = request = {
50934             url: url,
50935             params: params,
50936             script: script,
50937             id: id,
50938             scope: options.scope,
50939             success: options.success,
50940             failure: options.failure,
50941             callback: options.callback,
50942             callbackName: callbackName
50943         };
50944         
50945         if (timeout > 0) {
50946             request.timeout = setTimeout(Ext.bind(me.handleTimeout, me, [request]), timeout);
50947         }
50948         
50949         me.setupErrorHandling(request);
50950         me[callbackName] = Ext.bind(me.handleResponse, me, [request], true);
50951         Ext.getHead().appendChild(script);
50952         return request;
50953     },
50954     
50955     
50956     abort: function(request){
50957         var requests = this.statics().requests,
50958             key;
50959             
50960         if (request) {
50961             if (!request.id) {
50962                 request = requests[request];
50963             }
50964             this.abort(request);
50965         } else {
50966             for (key in requests) {
50967                 if (requests.hasOwnProperty(key)) {
50968                     this.abort(requests[key]);
50969                 }
50970             }
50971         }
50972     },
50973     
50974     
50975     setupErrorHandling: function(request){
50976         request.script.onerror = Ext.bind(this.handleError, this, [request]);
50977     },
50978     
50979     
50980     handleAbort: function(request){
50981         request.errorType = 'abort';
50982         this.handleResponse(null, request);
50983     },
50984     
50985     
50986     handleError: function(request){
50987         request.errorType = 'error';
50988         this.handleResponse(null, request);
50989     },
50990  
50991     
50992     cleanupErrorHandling: function(request){
50993         request.script.onerror = null;
50994     },
50995  
50996     
50997     handleTimeout: function(request){
50998         request.errorType = 'timeout';
50999         this.handleResponse(null, request);
51000     },
51001  
51002     
51003     handleResponse: function(result, request){
51004  
51005         var success = true;
51006  
51007         if (request.timeout) {
51008             clearTimeout(request.timeout);
51009         }
51010         delete this[request.callbackName];
51011         delete this.statics()[request.id];
51012         this.cleanupErrorHandling(request);
51013         Ext.fly(request.script).remove();
51014  
51015         if (request.errorType) {
51016             success = false;
51017             Ext.callback(request.failure, request.scope, [request.errorType]);
51018         } else {
51019             Ext.callback(request.success, request.scope, [result]);
51020         }
51021         Ext.callback(request.callback, request.scope, [success, result, request.errorType]);
51022     },
51023     
51024     
51025     createScript: function(url, params) {
51026         var script = document.createElement('script');
51027         script.setAttribute("src", Ext.urlAppend(url, Ext.Object.toQueryString(params)));
51028         script.setAttribute("async", true);
51029         script.setAttribute("type", "text/javascript");
51030         return script;
51031     }
51032 });
51033
51034
51035 Ext.define('Ext.data.JsonPStore', {
51036     extend: 'Ext.data.Store',
51037     alias : 'store.jsonp',
51038
51039     
51040     constructor: function(config) {
51041         this.callParent(Ext.apply(config, {
51042             reader: Ext.create('Ext.data.reader.Json', config),
51043             proxy : Ext.create('Ext.data.proxy.JsonP', config)
51044         }));
51045     }
51046 });
51047
51048
51049 Ext.define('Ext.data.NodeInterface', {
51050     requires: ['Ext.data.Field'],
51051     
51052     statics: {
51053         
51054         decorate: function(record) {
51055             if (!record.isNode) {
51056                 
51057                 
51058                 var mgr = Ext.ModelManager,
51059                     modelName = record.modelName,
51060                     modelClass = mgr.getModel(modelName),
51061                     idName = modelClass.prototype.idProperty,
51062                     instances = Ext.Array.filter(mgr.all.getArray(), function(item) {
51063                         return item.modelName == modelName;
51064                     }),
51065                     iln = instances.length,
51066                     newFields = [],
51067                     i, instance, jln, j, newField;
51068
51069                 
51070                 modelClass.override(this.getPrototypeBody());
51071                 newFields = this.applyFields(modelClass, [
51072                     {name: idName,      type: 'string',  defaultValue: null},
51073                     {name: 'parentId',  type: 'string',  defaultValue: null},
51074                     {name: 'index',     type: 'int',     defaultValue: null},
51075                     {name: 'depth',     type: 'int',     defaultValue: 0}, 
51076                     {name: 'expanded',  type: 'bool',    defaultValue: false, persist: false},
51077                     {name: 'checked',   type: 'auto',    defaultValue: null},
51078                     {name: 'leaf',      type: 'bool',    defaultValue: false, persist: false},
51079                     {name: 'cls',       type: 'string',  defaultValue: null, persist: false},
51080                     {name: 'iconCls',   type: 'string',  defaultValue: null, persist: false},
51081                     {name: 'root',      type: 'boolean', defaultValue: false, persist: false},
51082                     {name: 'isLast',    type: 'boolean', defaultValue: false, persist: false},
51083                     {name: 'isFirst',   type: 'boolean', defaultValue: false, persist: false},
51084                     {name: 'allowDrop', type: 'boolean', defaultValue: true, persist: false},
51085                     {name: 'allowDrag', type: 'boolean', defaultValue: true, persist: false},
51086                     {name: 'loaded',    type: 'boolean', defaultValue: false, persist: false},
51087                     {name: 'loading',   type: 'boolean', defaultValue: false, persist: false},
51088                     {name: 'href',      type: 'string',  defaultValue: null, persist: false},
51089                     {name: 'hrefTarget',type: 'string',  defaultValue: null, persist: false},
51090                     {name: 'qtip',      type: 'string',  defaultValue: null, persist: false},
51091                     {name: 'qtitle',    type: 'string',  defaultValue: null, persist: false}
51092                 ]);
51093
51094                 jln = newFields.length;
51095                 
51096                 for (i = 0; i < iln; i++) {
51097                     instance = instances[i];
51098                     for (j = 0; j < jln; j++) {
51099                         newField = newFields[j];
51100                         if (instance.get(newField.name) === undefined) {
51101                             instance.data[newField.name] = newField.defaultValue;
51102                         }
51103                     }
51104                 }
51105             }
51106             
51107             Ext.applyIf(record, {
51108                 firstChild: null,
51109                 lastChild: null,
51110                 parentNode: null,
51111                 previousSibling: null,
51112                 nextSibling: null,
51113                 childNodes: []
51114             });
51115             
51116             record.commit(true);
51117             
51118             record.enableBubble([
51119                 
51120                 "append",
51121
51122                 
51123                 "remove",
51124
51125                 
51126                 "move",
51127
51128                 
51129                 "insert",
51130
51131                 
51132                 "beforeappend",
51133
51134                 
51135                 "beforeremove",
51136
51137                 
51138                 "beforemove",
51139
51140                  
51141                 "beforeinsert",
51142                 
51143                 
51144                 "expand",
51145                 
51146                 
51147                 "collapse",
51148                 
51149                 
51150                 "beforeexpand",
51151                 
51152                 
51153                 "beforecollapse",
51154                 
51155                 
51156                 "sort"
51157             ]);
51158             
51159             return record;
51160         },
51161         
51162         applyFields: function(modelClass, addFields) {
51163             var modelPrototype = modelClass.prototype,
51164                 fields = modelPrototype.fields,
51165                 keys = fields.keys,
51166                 ln = addFields.length,
51167                 addField, i, name,
51168                 newFields = [];
51169                 
51170             for (i = 0; i < ln; i++) {
51171                 addField = addFields[i];
51172                 if (!Ext.Array.contains(keys, addField.name)) {
51173                     addField = Ext.create('data.field', addField);
51174                     
51175                     newFields.push(addField);
51176                     fields.add(addField);
51177                 }
51178             }
51179             
51180             return newFields;
51181         },
51182         
51183         getPrototypeBody: function() {
51184             return {
51185                 isNode: true,
51186
51187                 
51188                 createNode: function(node) {
51189                     if (Ext.isObject(node) && !node.isModel) {
51190                         node = Ext.ModelManager.create(node, this.modelName);
51191                     }
51192                     
51193                     return Ext.data.NodeInterface.decorate(node);
51194                 },
51195                 
51196                 
51197                 isLeaf : function() {
51198                     return this.get('leaf') === true;
51199                 },
51200
51201                 
51202                 setFirstChild : function(node) {
51203                     this.firstChild = node;
51204                 },
51205
51206                 
51207                 setLastChild : function(node) {
51208                     this.lastChild = node;
51209                 },
51210
51211                 
51212                 updateInfo: function(silent) {
51213                     var me = this,
51214                         isRoot = me.isRoot(),
51215                         parentNode = me.parentNode,
51216                         isFirst = (!parentNode ? true : parentNode.firstChild == me),
51217                         isLast = (!parentNode ? true : parentNode.lastChild == me),
51218                         depth = 0,
51219                         parent = me,
51220                         children = me.childNodes,
51221                         len = children.length,
51222                         i = 0;
51223
51224                     while (parent.parentNode) {
51225                         ++depth;
51226                         parent = parent.parentNode;
51227                     }                                            
51228                     
51229                     me.beginEdit();
51230                     me.set({
51231                         isFirst: isFirst,
51232                         isLast: isLast,
51233                         depth: depth,
51234                         index: parentNode ? parentNode.indexOf(me) : 0,
51235                         parentId: parentNode ? parentNode.getId() : null
51236                     });
51237                     me.endEdit(silent);
51238                     if (silent) {
51239                         me.commit();
51240                     }
51241                     
51242                     for (i = 0; i < len; i++) {
51243                         children[i].updateInfo(silent);
51244                     }
51245                 },
51246
51247                 
51248                 isLast : function() {
51249                    return this.get('isLast');
51250                 },
51251
51252                 
51253                 isFirst : function() {
51254                    return this.get('isFirst');
51255                 },
51256
51257                 
51258                 hasChildNodes : function() {
51259                     return !this.isLeaf() && this.childNodes.length > 0;
51260                 },
51261
51262                 
51263                 isExpandable : function() {
51264                     return this.get('expandable') || this.hasChildNodes();
51265                 },
51266
51267                 
51268                 appendChild : function(node, suppressEvents, suppressNodeUpdate) {
51269                     var me = this,
51270                         i, ln,
51271                         index,
51272                         oldParent,
51273                         ps;
51274
51275                     
51276                     if (Ext.isArray(node)) {
51277                         for (i = 0, ln = node.length; i < ln; i++) {
51278                             me.appendChild(node[i]);
51279                         }
51280                     } else {
51281                         
51282                         node = me.createNode(node);
51283                         
51284                         if (suppressEvents !== true && me.fireEvent("beforeappend", me, node) === false) {
51285                             return false;                         
51286                         }
51287
51288                         index = me.childNodes.length;
51289                         oldParent = node.parentNode;
51290
51291                         
51292                         if (oldParent) {
51293                             if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index) === false) {
51294                                 return false;
51295                             }
51296                             oldParent.removeChild(node, null, false, true);
51297                         }
51298
51299                         index = me.childNodes.length;
51300                         if (index === 0) {
51301                             me.setFirstChild(node);
51302                         }
51303
51304                         me.childNodes.push(node);
51305                         node.parentNode = me;
51306                         node.nextSibling = null;
51307
51308                         me.setLastChild(node);
51309                                                 
51310                         ps = me.childNodes[index - 1];
51311                         if (ps) {
51312                             node.previousSibling = ps;
51313                             ps.nextSibling = node;
51314                             ps.updateInfo(suppressNodeUpdate);
51315                         } else {
51316                             node.previousSibling = null;
51317                         }
51318
51319                         node.updateInfo(suppressNodeUpdate);
51320                         
51321                         
51322                         if (!me.isLoaded()) {
51323                             me.set('loaded', true);                            
51324                         }
51325                         
51326                         else if (me.childNodes.length === 1) {
51327                             me.set('loaded', me.isLoaded());
51328                         }
51329                         
51330                         if (suppressEvents !== true) {
51331                             me.fireEvent("append", me, node, index);
51332
51333                             if (oldParent) {
51334                                 node.fireEvent("move", node, oldParent, me, index);
51335                             }                            
51336                         }
51337
51338                         return node;
51339                     }
51340                 },
51341                 
51342                 
51343                 getBubbleTarget: function() {
51344                     return this.parentNode;
51345                 },
51346
51347                 
51348                 removeChild : function(node, destroy, suppressEvents, suppressNodeUpdate) {
51349                     var me = this,
51350                         index = me.indexOf(node);
51351                     
51352                     if (index == -1 || (suppressEvents !== true && me.fireEvent("beforeremove", me, node) === false)) {
51353                         return false;
51354                     }
51355
51356                     
51357                     me.childNodes.splice(index, 1);
51358
51359                     
51360                     if (me.firstChild == node) {
51361                         me.setFirstChild(node.nextSibling);
51362                     }
51363                     if (me.lastChild == node) {
51364                         me.setLastChild(node.previousSibling);
51365                     }
51366                     
51367                     
51368                     if (node.previousSibling) {
51369                         node.previousSibling.nextSibling = node.nextSibling;
51370                         node.previousSibling.updateInfo(suppressNodeUpdate);
51371                     }
51372                     if (node.nextSibling) {
51373                         node.nextSibling.previousSibling = node.previousSibling;
51374                         node.nextSibling.updateInfo(suppressNodeUpdate);
51375                     }
51376
51377                     if (suppressEvents !== true) {
51378                         me.fireEvent("remove", me, node);
51379                     }
51380                     
51381                     
51382                     
51383                     if (!me.childNodes.length) {
51384                         me.set('loaded', me.isLoaded());
51385                     }
51386                     
51387                     if (destroy) {
51388                         node.destroy(true);
51389                     } else {
51390                         node.clear();
51391                     }
51392
51393                     return node;
51394                 },
51395
51396                 
51397                 copy: function(newId, deep) {
51398                     var me = this,
51399                         result = me.callOverridden(arguments),
51400                         len = me.childNodes ? me.childNodes.length : 0,
51401                         i;
51402
51403                     
51404                     if (deep) {
51405                         for (i = 0; i < len; i++) {
51406                             result.appendChild(me.childNodes[i].copy(true));
51407                         }
51408                     }
51409                     return result;
51410                 },
51411
51412                 
51413                 clear : function(destroy) {
51414                     var me = this;
51415                     
51416                     
51417                     me.parentNode = me.previousSibling = me.nextSibling = null;
51418                     if (destroy) {
51419                         me.firstChild = me.lastChild = null;
51420                     }
51421                 },
51422
51423                 
51424                 destroy : function(silent) {
51425                     
51426                     var me = this;
51427                     
51428                     if (silent === true) {
51429                         me.clear(true);
51430                         Ext.each(me.childNodes, function(n) {
51431                             n.destroy(true);
51432                         });
51433                         me.childNodes = null;
51434                     } else {
51435                         me.remove(true);
51436                     }
51437
51438                     me.callOverridden();
51439                 },
51440
51441                 
51442                 insertBefore : function(node, refNode, suppressEvents) {
51443                     var me = this,
51444                         index     = me.indexOf(refNode),
51445                         oldParent = node.parentNode,
51446                         refIndex  = index,
51447                         ps;
51448                     
51449                     if (!refNode) { 
51450                         return me.appendChild(node);
51451                     }
51452                     
51453                     
51454                     if (node == refNode) {
51455                         return false;
51456                     }
51457
51458                     
51459                     node = me.createNode(node);
51460                     
51461                     if (suppressEvents !== true && me.fireEvent("beforeinsert", me, node, refNode) === false) {
51462                         return false;
51463                     }
51464                     
51465                     
51466                     if (oldParent == me && me.indexOf(node) < index) {
51467                         refIndex--;
51468                     }
51469
51470                     
51471                     if (oldParent) {
51472                         if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index, refNode) === false) {
51473                             return false;
51474                         }
51475                         oldParent.removeChild(node);
51476                     }
51477
51478                     if (refIndex === 0) {
51479                         me.setFirstChild(node);
51480                     }
51481
51482                     me.childNodes.splice(refIndex, 0, node);
51483                     node.parentNode = me;
51484                     
51485                     node.nextSibling = refNode;
51486                     refNode.previousSibling = node;
51487                     
51488                     ps = me.childNodes[refIndex - 1];
51489                     if (ps) {
51490                         node.previousSibling = ps;
51491                         ps.nextSibling = node;
51492                         ps.updateInfo();
51493                     } else {
51494                         node.previousSibling = null;
51495                     }
51496                     
51497                     node.updateInfo();
51498                     
51499                     if (!me.isLoaded()) {
51500                         me.set('loaded', true);                            
51501                     }    
51502                     
51503                     else if (me.childNodes.length === 1) {
51504                         me.set('loaded', me.isLoaded());
51505                     }
51506
51507                     if (suppressEvents !== true) {
51508                         me.fireEvent("insert", me, node, refNode);
51509
51510                         if (oldParent) {
51511                             node.fireEvent("move", node, oldParent, me, refIndex, refNode);
51512                         }                        
51513                     }
51514
51515                     return node;
51516                 },
51517                 
51518                     
51519                 insertChild: function(index, node) {
51520                     var sibling = this.childNodes[index];
51521                     if (sibling) {
51522                         return this.insertBefore(node, sibling);
51523                     }
51524                     else {
51525                         return this.appendChild(node);
51526                     }
51527                 },
51528
51529                 
51530                 remove : function(destroy, suppressEvents) {
51531                     var parentNode = this.parentNode;
51532
51533                     if (parentNode) {
51534                         parentNode.removeChild(this, destroy, suppressEvents, true);
51535                     }
51536                     return this;
51537                 },
51538
51539                 
51540                 removeAll : function(destroy, suppressEvents) {
51541                     var cn = this.childNodes,
51542                         n;
51543
51544                     while ((n = cn[0])) {
51545                         this.removeChild(n, destroy, suppressEvents);
51546                     }
51547                     return this;
51548                 },
51549
51550                 
51551                 getChildAt : function(index) {
51552                     return this.childNodes[index];
51553                 },
51554
51555                 
51556                 replaceChild : function(newChild, oldChild, suppressEvents) {
51557                     var s = oldChild ? oldChild.nextSibling : null;
51558                     
51559                     this.removeChild(oldChild, suppressEvents);
51560                     this.insertBefore(newChild, s, suppressEvents);
51561                     return oldChild;
51562                 },
51563
51564                 
51565                 indexOf : function(child) {
51566                     return Ext.Array.indexOf(this.childNodes, child);
51567                 },
51568
51569                 
51570                 getDepth : function() {
51571                     return this.get('depth');
51572                 },
51573
51574                 
51575                 bubble : function(fn, scope, args) {
51576                     var p = this;
51577                     while (p) {
51578                         if (fn.apply(scope || p, args || [p]) === false) {
51579                             break;
51580                         }
51581                         p = p.parentNode;
51582                     }
51583                 },
51584
51585                 cascade: function() {
51586                     if (Ext.isDefined(Ext.global.console)) {
51587                         Ext.global.console.warn('Ext.data.Node: cascade has been deprecated. Please use cascadeBy instead.');
51588                     }
51589                     return this.cascadeBy.apply(this, arguments);
51590                 },
51591
51592                 
51593                 cascadeBy : function(fn, scope, args) {
51594                     if (fn.apply(scope || this, args || [this]) !== false) {
51595                         var childNodes = this.childNodes,
51596                             length     = childNodes.length,
51597                             i;
51598
51599                         for (i = 0; i < length; i++) {
51600                             childNodes[i].cascadeBy(fn, scope, args);
51601                         }
51602                     }
51603                 },
51604
51605                 
51606                 eachChild : function(fn, scope, args) {
51607                     var childNodes = this.childNodes,
51608                         length     = childNodes.length,
51609                         i;
51610
51611                     for (i = 0; i < length; i++) {
51612                         if (fn.apply(scope || this, args || [childNodes[i]]) === false) {
51613                             break;
51614                         }
51615                     }
51616                 },
51617
51618                 
51619                 findChild : function(attribute, value, deep) {
51620                     return this.findChildBy(function() {
51621                         return this.get(attribute) == value;
51622                     }, null, deep);
51623                 },
51624
51625                 
51626                 findChildBy : function(fn, scope, deep) {
51627                     var cs = this.childNodes,
51628                         len = cs.length,
51629                         i = 0, n, res;
51630
51631                     for (; i < len; i++) {
51632                         n = cs[i];
51633                         if (fn.call(scope || n, n) === true) {
51634                             return n;
51635                         }
51636                         else if (deep) {
51637                             res = n.findChildBy(fn, scope, deep);
51638                             if (res !== null) {
51639                                 return res;
51640                             }
51641                         }
51642                     }
51643
51644                     return null;
51645                 },
51646
51647                 
51648                 contains : function(node) {
51649                     return node.isAncestor(this);
51650                 },
51651
51652                 
51653                 isAncestor : function(node) {
51654                     var p = this.parentNode;
51655                     while (p) {
51656                         if (p == node) {
51657                             return true;
51658                         }
51659                         p = p.parentNode;
51660                     }
51661                     return false;
51662                 },
51663
51664                 
51665                 sort : function(sortFn, recursive, suppressEvent) {
51666                     var cs  = this.childNodes,
51667                         ln = cs.length,
51668                         i, n;
51669                     
51670                     if (ln > 0) {
51671                         Ext.Array.sort(cs, sortFn);
51672                         for (i = 0; i < ln; i++) {
51673                             n = cs[i];
51674                             n.previousSibling = cs[i-1];
51675                             n.nextSibling = cs[i+1];
51676                         
51677                             if (i === 0) {
51678                                 this.setFirstChild(n);
51679                                 n.updateInfo();
51680                             }
51681                             if (i == ln - 1) {
51682                                 this.setLastChild(n);
51683                                 n.updateInfo();
51684                             }
51685                             if (recursive && !n.isLeaf()) {
51686                                 n.sort(sortFn, true, true);
51687                             }
51688                         }
51689                         
51690                         if (suppressEvent !== true) {
51691                             this.fireEvent('sort', this, cs);
51692                         }
51693                     }
51694                 },
51695                         
51696                         
51697                 isExpanded: function() {
51698                     return this.get('expanded');
51699                 },
51700                 
51701                  
51702                 isLoaded: function() {
51703                     return this.get('loaded');
51704                 },
51705
51706                  
51707                 isLoading: function() {
51708                     return this.get('loading');
51709                 },
51710                                 
51711                  
51712                 isRoot: function() {
51713                     return !this.parentNode;
51714                 },
51715                 
51716                  
51717                 isVisible: function() {
51718                     var parent = this.parentNode;
51719                     while (parent) {
51720                         if (!parent.isExpanded()) {
51721                             return false;
51722                         }
51723                         parent = parent.parentNode;
51724                     }
51725                     return true;
51726                 },
51727                 
51728                 
51729                 expand: function(recursive, callback, scope) {
51730                     var me = this;
51731
51732                     
51733                     
51734
51735                     
51736                     if (!me.isLeaf()) {
51737                         
51738                         if (!me.isLoading() && !me.isExpanded()) {
51739                             
51740                             
51741                             
51742                             
51743                             me.fireEvent('beforeexpand', me, function(records) {
51744                                 me.set('expanded', true); 
51745                                 me.fireEvent('expand', me, me.childNodes, false);
51746                                 
51747                                 
51748                                 if (recursive) {
51749                                     me.expandChildren(true, callback, scope);
51750                                 }
51751                                 else {
51752                                     Ext.callback(callback, scope || me, [me.childNodes]);                                
51753                                 }
51754                             }, me);                            
51755                         }
51756                         
51757                         else if (recursive) {
51758                             me.expandChildren(true, callback, scope);
51759                         }
51760                         else {
51761                             Ext.callback(callback, scope || me, [me.childNodes]);
51762                         }
51763
51764                         
51765                         
51766                         
51767                     }
51768                     
51769                     else {
51770                         Ext.callback(callback, scope || me); 
51771                     }
51772                 },
51773                 
51774                 
51775                 expandChildren: function(recursive, callback, scope) {
51776                     var me = this,
51777                         i = 0,
51778                         nodes = me.childNodes,
51779                         ln = nodes.length,
51780                         node,
51781                         expanding = 0;
51782
51783                     for (; i < ln; ++i) {
51784                         node = nodes[i];
51785                         if (!node.isLeaf() && !node.isExpanded()) {
51786                             expanding++;
51787                             nodes[i].expand(recursive, function () {
51788                                 expanding--;
51789                                 if (callback && !expanding) {
51790                                     Ext.callback(callback, scope || me, me.childNodes); 
51791                                 }
51792                             });                            
51793                         }
51794                     }
51795                     
51796                     if (!expanding && callback) {
51797                         Ext.callback(callback, scope || me, me.childNodes);
51798                     }
51799                 },
51800
51801                 
51802                 collapse: function(recursive, callback, scope) {
51803                     var me = this;
51804
51805                     
51806                     if (!me.isLeaf()) {
51807                         
51808                         if (!me.collapsing && me.isExpanded()) {
51809                             me.fireEvent('beforecollapse', me, function(records) {
51810                                 me.set('expanded', false); 
51811                                 me.fireEvent('collapse', me, me.childNodes, false);
51812                                 
51813                                 
51814                                 if (recursive) {
51815                                     me.collapseChildren(true, callback, scope);
51816                                 }
51817                                 else {
51818                                     Ext.callback(callback, scope || me, [me.childNodes]);                                
51819                                 }
51820                             }, me);                            
51821                         }
51822                         
51823                         else if (recursive) {
51824                             me.collapseChildren(true, callback, scope);
51825                         }
51826                     }
51827                     
51828                     else {
51829                         Ext.callback(callback, scope || me, me.childNodes); 
51830                     }
51831                 },
51832                 
51833                 
51834                 collapseChildren: function(recursive, callback, scope) {
51835                     var me = this,
51836                         i = 0,
51837                         nodes = me.childNodes,
51838                         ln = nodes.length,
51839                         node,
51840                         collapsing = 0;
51841
51842                     for (; i < ln; ++i) {
51843                         node = nodes[i];
51844                         if (!node.isLeaf() && node.isExpanded()) {
51845                             collapsing++;
51846                             nodes[i].collapse(recursive, function () {
51847                                 collapsing--;
51848                                 if (callback && !collapsing) {
51849                                     Ext.callback(callback, scope || me, me.childNodes); 
51850                                 }
51851                             });                            
51852                         }
51853                     }
51854                     
51855                     if (!collapsing && callback) {
51856                         Ext.callback(callback, scope || me, me.childNodes);
51857                     }
51858                 }
51859             };
51860         }
51861     }
51862 });
51863
51864 Ext.define('Ext.data.NodeStore', {
51865     extend: 'Ext.data.Store',
51866     alias: 'store.node',
51867     requires: ['Ext.data.NodeInterface'],
51868     
51869     
51870     node: null,
51871     
51872     
51873     recursive: false,
51874     
51875         
51876     rootVisible: false,
51877     
51878     constructor: function(config) {
51879         var me = this,
51880             node;
51881             
51882         config = config || {};
51883         Ext.apply(me, config);
51884         
51885         if (Ext.isDefined(me.proxy)) {
51886             Ext.Error.raise("A NodeStore cannot be bound to a proxy. Instead bind it to a record " +
51887                             "decorated with the NodeInterface by setting the node config.");
51888         }
51889
51890         config.proxy = {type: 'proxy'};
51891         me.callParent([config]);
51892
51893         me.addEvents('expand', 'collapse', 'beforeexpand', 'beforecollapse');
51894         
51895         node = me.node;
51896         if (node) {
51897             me.node = null;
51898             me.setNode(node);
51899         }
51900     },
51901     
51902     setNode: function(node) {
51903         var me = this;
51904         
51905         if (me.node && me.node != node) {
51906             
51907             me.mun(me.node, {
51908                 expand: me.onNodeExpand,
51909                 collapse: me.onNodeCollapse,
51910                 append: me.onNodeAppend,
51911                 insert: me.onNodeInsert,
51912                 remove: me.onNodeRemove,
51913                 sort: me.onNodeSort,
51914                 scope: me
51915             });
51916             me.node = null;
51917         }
51918         
51919         if (node) {
51920             Ext.data.NodeInterface.decorate(node);
51921             me.removeAll();
51922             if (me.rootVisible) {
51923                 me.add(node);
51924             }
51925             me.mon(node, {
51926                 expand: me.onNodeExpand,
51927                 collapse: me.onNodeCollapse,
51928                 append: me.onNodeAppend,
51929                 insert: me.onNodeInsert,
51930                 remove: me.onNodeRemove,
51931                 sort: me.onNodeSort,
51932                 scope: me
51933             });
51934             me.node = node;
51935             if (node.isExpanded() && node.isLoaded()) {
51936                 me.onNodeExpand(node, node.childNodes, true);
51937             }
51938         }
51939     },
51940     
51941     onNodeSort: function(node, childNodes) {
51942         var me = this;
51943         
51944         if ((me.indexOf(node) !== -1 || (node === me.node && !me.rootVisible) && node.isExpanded())) {
51945             me.onNodeCollapse(node, childNodes, true);
51946             me.onNodeExpand(node, childNodes, true);
51947         }
51948     },
51949     
51950     onNodeExpand: function(parent, records, suppressEvent) {
51951         var me = this,
51952             insertIndex = me.indexOf(parent) + 1,
51953             ln = records ? records.length : 0,
51954             i, record;
51955             
51956         if (!me.recursive && parent !== me.node) {
51957             return;
51958         }
51959         
51960         if (!me.isVisible(parent)) {
51961             return;
51962         }
51963
51964         if (!suppressEvent && me.fireEvent('beforeexpand', parent, records, insertIndex) === false) {
51965             return;
51966         }
51967         
51968         if (ln) {
51969             me.insert(insertIndex, records);
51970             for (i = 0; i < ln; i++) {
51971                 record = records[i];
51972                 if (record.isExpanded()) {
51973                     if (record.isLoaded()) {
51974                         
51975                         me.onNodeExpand(record, record.childNodes, true);
51976                     }
51977                     else {
51978                         record.set('expanded', false);
51979                         record.expand();
51980                     }
51981                 }
51982             }
51983         }
51984
51985         if (!suppressEvent) {
51986             me.fireEvent('expand', parent, records);
51987         }
51988     },
51989
51990     onNodeCollapse: function(parent, records, suppressEvent) {
51991         var me = this,
51992             ln = records.length,
51993             collapseIndex = me.indexOf(parent) + 1,
51994             i, record;
51995             
51996         if (!me.recursive && parent !== me.node) {
51997             return;
51998         }
51999         
52000         if (!suppressEvent && me.fireEvent('beforecollapse', parent, records, collapseIndex) === false) {
52001             return;
52002         }
52003
52004         for (i = 0; i < ln; i++) {
52005             record = records[i];
52006             me.remove(record);
52007             if (record.isExpanded()) {
52008                 me.onNodeCollapse(record, record.childNodes, true);
52009             }
52010         }
52011         
52012         if (!suppressEvent) {
52013             me.fireEvent('collapse', parent, records, collapseIndex);
52014         }
52015     },
52016     
52017     onNodeAppend: function(parent, node, index) {
52018         var me = this,
52019             refNode, sibling;
52020
52021         if (me.isVisible(node)) {
52022             if (index === 0) {
52023                 refNode = parent;
52024             } else {
52025                 sibling = node.previousSibling;
52026                 while (sibling.isExpanded() && sibling.lastChild) {
52027                     sibling = sibling.lastChild;
52028                 }
52029                 refNode = sibling;
52030             }
52031             me.insert(me.indexOf(refNode) + 1, node);
52032             if (!node.isLeaf() && node.isExpanded()) {
52033                 if (node.isLoaded()) {
52034                     
52035                     me.onNodeExpand(node, node.childNodes, true);
52036                 }
52037                 else {
52038                     node.set('expanded', false);
52039                     node.expand();
52040                 }
52041             }
52042         } 
52043     },
52044     
52045     onNodeInsert: function(parent, node, refNode) {
52046         var me = this,
52047             index = this.indexOf(refNode);
52048             
52049         if (index != -1 && me.isVisible(node)) {
52050             me.insert(index, node);
52051             if (!node.isLeaf() && node.isExpanded()) {
52052                 if (node.isLoaded()) {
52053                     
52054                     me.onNodeExpand(node, node.childNodes, true);
52055                 }
52056                 else {
52057                     node.set('expanded', false);
52058                     node.expand();
52059                 }
52060             }
52061         }
52062     },
52063     
52064     onNodeRemove: function(parent, node, index) {
52065         var me = this;
52066         if (me.indexOf(node) != -1) {
52067             if (!node.isLeaf() && node.isExpanded()) {
52068                 me.onNodeCollapse(node, node.childNodes, true);
52069             }            
52070             me.remove(node);
52071         }
52072     },
52073     
52074     isVisible: function(node) {
52075         var parent = node.parentNode;
52076         while (parent) {
52077             if (parent === this.node && !this.rootVisible && parent.isExpanded()) {
52078                 return true;
52079             }
52080             
52081             if (this.indexOf(parent) === -1 || !parent.isExpanded()) {
52082                 return false;
52083             }
52084             
52085             parent = parent.parentNode;
52086         }
52087         return true;
52088     }
52089 });
52090
52091 Ext.define('Ext.data.Request', {
52092     
52093     action: undefined,
52094     
52095     
52096     params: undefined,
52097     
52098     
52099     method: 'GET',
52100     
52101     
52102     url: undefined,
52103
52104     constructor: function(config) {
52105         Ext.apply(this, config);
52106     }
52107 });
52108
52109 Ext.define('Ext.data.Tree', {
52110     alias: 'data.tree',
52111     
52112     mixins: {
52113         observable: "Ext.util.Observable"
52114     },
52115
52116     
52117     root: null,
52118         
52119     constructor: function(root) {
52120         var me = this;
52121         
52122         me.nodeHash = {};
52123
52124         me.mixins.observable.constructor.call(me);
52125                         
52126         if (root) {
52127             me.setRootNode(root);
52128         }
52129     },
52130
52131     
52132     getRootNode : function() {
52133         return this.root;
52134     },
52135
52136     
52137     setRootNode : function(node) {
52138         var me = this;
52139         
52140         me.root = node;
52141         Ext.data.NodeInterface.decorate(node);
52142         
52143         if (me.fireEvent('beforeappend', null, node) !== false) {
52144             node.set('root', true);
52145             node.updateInfo();
52146             
52147             me.relayEvents(node, [
52148                 
52149                 "append",
52150
52151                 
52152                 "remove",
52153
52154                 
52155                 "move",
52156
52157                 
52158                 "insert",
52159
52160                 
52161                 "beforeappend",
52162
52163                 
52164                 "beforeremove",
52165
52166                 
52167                 "beforemove",
52168
52169                 
52170                 "beforeinsert",
52171
52172                  
52173                  "expand",
52174
52175                  
52176                  "collapse",
52177
52178                  
52179                  "beforeexpand",
52180
52181                  
52182                  "beforecollapse" ,
52183
52184                  
52185                  "rootchange"
52186             ]);
52187             
52188             node.on({
52189                 scope: me,
52190                 insert: me.onNodeInsert,
52191                 append: me.onNodeAppend,
52192                 remove: me.onNodeRemove
52193             });
52194
52195             me.registerNode(node);        
52196             me.fireEvent('append', null, node);
52197             me.fireEvent('rootchange', node);
52198         }
52199             
52200         return node;
52201     },
52202     
52203     
52204     flatten: function(){
52205         var nodes = [],
52206             hash = this.nodeHash,
52207             key;
52208             
52209         for (key in hash) {
52210             if (hash.hasOwnProperty(key)) {
52211                 nodes.push(hash[key]);
52212             }
52213         }
52214         return nodes;
52215     },
52216     
52217     
52218     onNodeInsert: function(parent, node) {
52219         this.registerNode(node);
52220     },
52221     
52222     
52223     onNodeAppend: function(parent, node) {
52224         this.registerNode(node);
52225     },
52226     
52227     
52228     onNodeRemove: function(parent, node) {
52229         this.unregisterNode(node);
52230     },
52231
52232     
52233     getNodeById : function(id) {
52234         return this.nodeHash[id];
52235     },
52236
52237     
52238     registerNode : function(node) {
52239         this.nodeHash[node.getId() || node.internalId] = node;
52240     },
52241
52242     
52243     unregisterNode : function(node) {
52244         delete this.nodeHash[node.getId() || node.internalId];
52245     },
52246     
52247     
52248     sort: function(sorterFn, recursive) {
52249         this.getRootNode().sort(sorterFn, recursive);
52250     },
52251     
52252      
52253     filter: function(filters, recursive) {
52254         this.getRootNode().filter(filters, recursive);
52255     }
52256 });
52257
52258 Ext.define('Ext.data.TreeStore', {
52259     extend: 'Ext.data.AbstractStore',
52260     alias: 'store.tree',
52261     requires: ['Ext.data.Tree', 'Ext.data.NodeInterface', 'Ext.data.NodeStore'],
52262
52263     
52264     clearOnLoad : true,
52265
52266     
52267     nodeParam: 'node',
52268
52269     
52270     defaultRootId: 'root',
52271     
52272     
52273     defaultRootProperty: 'children',
52274
52275     
52276     folderSort: false,
52277     
52278     constructor: function(config) {
52279         var me = this, 
52280             root,
52281             fields;
52282             
52283         
52284         config = Ext.apply({}, config);
52285         
52286         
52287         fields = config.fields || me.fields;
52288         if (!fields) {
52289             config.fields = [{name: 'text', type: 'string'}];
52290         }
52291
52292         me.callParent([config]);
52293         
52294         
52295         me.tree = Ext.create('Ext.data.Tree');
52296         
52297         me.tree.on({
52298             scope: me,
52299             remove: me.onNodeRemove,
52300             beforeexpand: me.onBeforeNodeExpand,
52301             beforecollapse: me.onBeforeNodeCollapse,
52302             append: me.onNodeAdded,
52303             insert: me.onNodeAdded
52304         });
52305
52306         me.onBeforeSort();
52307                 
52308         root = me.root;
52309         if (root) {
52310             delete me.root;
52311             me.setRootNode(root);            
52312         }
52313
52314         me.relayEvents(me.tree, [
52315             
52316             "append",
52317             
52318             
52319             "remove",
52320             
52321             
52322             "move",
52323             
52324             
52325             "insert",
52326             
52327             
52328             "beforeappend",
52329             
52330             
52331             "beforeremove",
52332             
52333             
52334             "beforemove",
52335             
52336             
52337             "beforeinsert",
52338              
52339              
52340              "expand",
52341              
52342              
52343              "collapse",
52344              
52345              
52346              "beforeexpand",
52347              
52348              
52349              "beforecollapse",
52350
52351                           
52352              "sort",
52353              
52354              
52355              "rootchange"
52356         ]);
52357         
52358         me.addEvents(
52359             
52360             'rootchange'
52361         );
52362         
52363         if (Ext.isDefined(me.nodeParameter)) {
52364             if (Ext.isDefined(Ext.global.console)) {
52365                 Ext.global.console.warn('Ext.data.TreeStore: nodeParameter has been deprecated. Please use nodeParam instead.');
52366             }
52367             me.nodeParam = me.nodeParameter;
52368             delete me.nodeParameter;
52369         }
52370     },
52371     
52372     
52373     setProxy: function(proxy) {
52374         var reader,
52375             needsRoot;
52376         
52377         if (proxy instanceof Ext.data.proxy.Proxy) {
52378             
52379             needsRoot = Ext.isEmpty(proxy.getReader().root);
52380         } else if (Ext.isString(proxy)) {
52381             
52382             needsRoot = true;
52383         } else {
52384             
52385             reader = proxy.reader;
52386             needsRoot = !(reader && !Ext.isEmpty(reader.root));
52387         }
52388         proxy = this.callParent(arguments);
52389         if (needsRoot) {
52390             reader = proxy.getReader();
52391             reader.root = this.defaultRootProperty;
52392             
52393             reader.buildExtractors(true);
52394         }
52395     },
52396     
52397     
52398     onBeforeSort: function() {
52399         if (this.folderSort) {
52400             this.sort({
52401                 property: 'leaf',
52402                 direction: 'ASC'
52403             }, 'prepend', false);    
52404         }
52405     },
52406     
52407     
52408     onBeforeNodeExpand: function(node, callback, scope) {
52409         if (node.isLoaded()) {
52410             Ext.callback(callback, scope || node, [node.childNodes]);
52411         }
52412         else if (node.isLoading()) {
52413             this.on('load', function() {
52414                 Ext.callback(callback, scope || node, [node.childNodes]);
52415             }, this, {single: true});
52416         }
52417         else {
52418             this.read({
52419                 node: node,
52420                 callback: function() {
52421                     Ext.callback(callback, scope || node, [node.childNodes]);
52422                 }
52423             });            
52424         }
52425     },
52426     
52427     
52428     getNewRecords: function() {
52429         return Ext.Array.filter(this.tree.flatten(), this.filterNew);
52430     },
52431
52432     
52433     getUpdatedRecords: function() {
52434         return Ext.Array.filter(this.tree.flatten(), this.filterUpdated);
52435     },
52436     
52437     
52438     onBeforeNodeCollapse: function(node, callback, scope) {
52439         callback.call(scope || node, node.childNodes);
52440     },
52441     
52442     onNodeRemove: function(parent, node) {
52443         var removed = this.removed;
52444         
52445         if (!node.isReplace && Ext.Array.indexOf(removed, node) == -1) {
52446             removed.push(node);
52447         }
52448     },
52449     
52450     onNodeAdded: function(parent, node) {
52451         var proxy = this.getProxy(),
52452             reader = proxy.getReader(),
52453             data = node.raw || node.data,
52454             dataRoot, children;
52455             
52456         Ext.Array.remove(this.removed, node); 
52457         
52458         if (!node.isLeaf() && !node.isLoaded()) {
52459             dataRoot = reader.getRoot(data);
52460             if (dataRoot) {
52461                 this.fillNode(node, reader.extractData(dataRoot));
52462                 delete data[reader.root];
52463             }
52464         }
52465     },
52466         
52467     
52468     setRootNode: function(root) {
52469         var me = this;
52470
52471         root = root || {};        
52472         if (!root.isNode) {
52473             
52474             Ext.applyIf(root, {
52475                 id: me.defaultRootId,
52476                 text: 'Root',
52477                 allowDrag: false
52478             });
52479             root = Ext.ModelManager.create(root, me.model);
52480         }
52481         Ext.data.NodeInterface.decorate(root);
52482
52483         
52484         
52485         me.getProxy().getReader().buildExtractors(true);
52486         
52487         
52488         me.tree.setRootNode(root);
52489         
52490         
52491         if (!root.isLoaded() && root.isExpanded()) {
52492             me.load({
52493                 node: root
52494             });
52495         }
52496         
52497         return root;
52498     },
52499         
52500     
52501     getRootNode: function() {
52502         return this.tree.getRootNode();
52503     },
52504
52505     
52506     getNodeById: function(id) {
52507         return this.tree.getNodeById(id);
52508     },
52509
52510     
52511     load: function(options) {
52512         options = options || {};
52513         options.params = options.params || {};
52514         
52515         var me = this,
52516             node = options.node || me.tree.getRootNode(),
52517             root;
52518             
52519         
52520         
52521         if (!node) {
52522             node = me.setRootNode({
52523                 expanded: true
52524             });
52525         }
52526         
52527         if (me.clearOnLoad) {
52528             node.removeAll();
52529         }
52530         
52531         Ext.applyIf(options, {
52532             node: node
52533         });
52534         options.params[me.nodeParam] = node ? node.getId() : 'root';
52535         
52536         if (node) {
52537             node.set('loading', true);
52538         }
52539         
52540         return me.callParent([options]);
52541     },
52542         
52543
52544     
52545     fillNode: function(node, records) {
52546         var me = this,
52547             ln = records ? records.length : 0,
52548             i = 0, sortCollection;
52549
52550         if (ln && me.sortOnLoad && !me.remoteSort && me.sorters && me.sorters.items) {
52551             sortCollection = Ext.create('Ext.util.MixedCollection');
52552             sortCollection.addAll(records);
52553             sortCollection.sort(me.sorters.items);
52554             records = sortCollection.items;
52555         }
52556         
52557         node.set('loaded', true);
52558         for (; i < ln; i++) {
52559             node.appendChild(records[i], undefined, true);
52560         }
52561         
52562         return records;
52563     },
52564
52565     
52566     onProxyLoad: function(operation) {
52567         var me = this,
52568             successful = operation.wasSuccessful(),
52569             records = operation.getRecords(),
52570             node = operation.node;
52571
52572         node.set('loading', false);
52573         if (successful) {
52574             records = me.fillNode(node, records);
52575         }
52576         
52577         me.fireEvent('read', me, operation.node, records, successful);
52578         me.fireEvent('load', me, operation.node, records, successful);
52579         
52580         Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
52581     },
52582     
52583     
52584     onCreateRecords: function(records, operation, success) {
52585         if (success) {
52586             var i = 0,
52587                 length = records.length,
52588                 originalRecords = operation.records,
52589                 parentNode,
52590                 record,
52591                 original,
52592                 index;
52593
52594             
52595             for (; i < length; ++i) {
52596                 record = records[i];
52597                 original = originalRecords[i];
52598                 if (original) {
52599                     parentNode = original.parentNode;
52600                     if (parentNode) {
52601                         
52602                         original.isReplace = true;
52603                         parentNode.replaceChild(record, original);
52604                         delete original.isReplace;
52605                     }
52606                     record.phantom = false;
52607                 }
52608             }
52609         }
52610     },
52611
52612     
52613     onUpdateRecords: function(records, operation, success){
52614         if (success) {
52615             var me = this,
52616                 i = 0,
52617                 length = records.length,
52618                 data = me.data,
52619                 original,
52620                 parentNode,
52621                 record;
52622
52623             for (; i < length; ++i) {
52624                 record = records[i];
52625                 original = me.tree.getNodeById(record.getId());
52626                 parentNode = original.parentNode;
52627                 if (parentNode) {
52628                     
52629                     original.isReplace = true;
52630                     parentNode.replaceChild(record, original);
52631                     original.isReplace = false;
52632                 }
52633             }
52634         }
52635     },
52636
52637     
52638     onDestroyRecords: function(records, operation, success){
52639         if (success) {
52640             this.removed = [];
52641         }
52642     },
52643
52644     
52645     removeAll: function() {
52646         this.getRootNode().destroy();
52647         this.fireEvent('clear', this);
52648     },
52649
52650     
52651     doSort: function(sorterFn) {
52652         var me = this;
52653         if (me.remoteSort) {
52654             
52655             me.load();
52656         } else {
52657             me.tree.sort(sorterFn, true);
52658             me.fireEvent('datachanged', me);
52659         }   
52660         me.fireEvent('sort', me);
52661     }
52662 });
52663
52664 Ext.define('Ext.data.XmlStore', {
52665     extend: 'Ext.data.Store',
52666     alternateClassName: 'Ext.data.XmlStore',
52667     alias: 'store.xml',
52668
52669     
52670     constructor: function(config){
52671         config = config || {};
52672         config = config || {};
52673
52674         Ext.applyIf(config, {
52675             proxy: {
52676                 type: 'ajax',
52677                 reader: 'xml',
52678                 writer: 'xml'
52679             }
52680         });
52681
52682         this.callParent([config]);
52683     }
52684 });
52685
52686
52687 Ext.define('Ext.data.proxy.Client', {
52688     extend: 'Ext.data.proxy.Proxy',
52689     alternateClassName: 'Ext.data.ClientProxy',
52690     
52691     
52692     clear: function() {
52693         Ext.Error.raise("The Ext.data.proxy.Client subclass that you are using has not defined a 'clear' function. See src/data/ClientProxy.js for details.");
52694     }
52695 });
52696
52697 Ext.define('Ext.data.proxy.JsonP', {
52698     extend: 'Ext.data.proxy.Server',
52699     alternateClassName: 'Ext.data.ScriptTagProxy',
52700     alias: ['proxy.jsonp', 'proxy.scripttag'],
52701     requires: ['Ext.data.JsonP'],
52702
52703     defaultWriterType: 'base',
52704
52705     
52706     callbackKey : 'callback',
52707
52708     
52709     recordParam: 'records',
52710
52711     
52712     autoAppendParams: true,
52713
52714     constructor: function(){
52715         this.addEvents(
52716             
52717             'exception'
52718         );
52719         this.callParent(arguments);
52720     },
52721
52722     
52723     doRequest: function(operation, callback, scope) {
52724         
52725         var me      = this,
52726             writer  = me.getWriter(),
52727             request = me.buildRequest(operation),
52728             params = request.params;
52729
52730         if (operation.allowWrite()) {
52731             request = writer.write(request);
52732         }
52733
52734         
52735         Ext.apply(request, {
52736             callbackKey: me.callbackKey,
52737             timeout: me.timeout,
52738             scope: me,
52739             disableCaching: false, 
52740             callback: me.createRequestCallback(request, operation, callback, scope)
52741         });
52742         
52743         
52744         if (me.autoAppendParams) {
52745             request.params = {};
52746         }
52747         
52748         request.jsonp = Ext.data.JsonP.request(request);
52749         
52750         request.params = params;
52751         operation.setStarted();
52752         me.lastRequest = request;
52753
52754         return request;
52755     },
52756
52757     
52758     createRequestCallback: function(request, operation, callback, scope) {
52759         var me = this;
52760
52761         return function(success, response, errorType) {
52762             delete me.lastRequest;
52763             me.processResponse(success, operation, request, response, callback, scope);
52764         };
52765     },
52766     
52767     
52768     setException: function(operation, response) {
52769         operation.setException(operation.request.jsonp.errorType);
52770     },
52771
52772
52773     
52774     buildUrl: function(request) {
52775         var me      = this,
52776             url     = me.callParent(arguments),
52777             params  = Ext.apply({}, request.params),
52778             filters = params.filters,
52779             records,
52780             filter, i;
52781
52782         delete params.filters;
52783  
52784         if (me.autoAppendParams) {
52785             url = Ext.urlAppend(url, Ext.Object.toQueryString(params));
52786         }
52787
52788         if (filters && filters.length) {
52789             for (i = 0; i < filters.length; i++) {
52790                 filter = filters[i];
52791
52792                 if (filter.value) {
52793                     url = Ext.urlAppend(url, filter.property + "=" + filter.value);
52794                 }
52795             }
52796         }
52797
52798         
52799         records = request.records;
52800
52801         if (Ext.isArray(records) && records.length > 0) {
52802             url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.recordParam, me.encodeRecords(records)));
52803         }
52804
52805         return url;
52806     },
52807
52808     
52809     destroy: function() {
52810         this.abort();
52811         this.callParent();
52812     },
52813
52814     
52815     abort: function() {
52816         var lastRequest = this.lastRequest;
52817         if (lastRequest) {
52818             Ext.data.JsonP.abort(lastRequest.jsonp);
52819         }
52820     },
52821
52822     
52823     encodeRecords: function(records) {
52824         var encoded = "",
52825             i = 0,
52826             len = records.length;
52827
52828         for (; i < len; i++) {
52829             encoded += Ext.Object.toQueryString(records[i].data);
52830         }
52831
52832         return encoded;
52833     }
52834 });
52835
52836
52837 Ext.define('Ext.data.proxy.WebStorage', {
52838     extend: 'Ext.data.proxy.Client',
52839     alternateClassName: 'Ext.data.WebStorageProxy',
52840     
52841     
52842     id: undefined,
52843
52844     
52845     constructor: function(config) {
52846         this.callParent(arguments);
52847         
52848         
52849         this.cache = {};
52850
52851         if (this.getStorageObject() === undefined) {
52852             Ext.Error.raise("Local Storage is not supported in this browser, please use another type of data proxy");
52853         }
52854
52855         
52856         this.id = this.id || (this.store ? this.store.storeId : undefined);
52857
52858         if (this.id === undefined) {
52859             Ext.Error.raise("No unique id was provided to the local storage proxy. See Ext.data.proxy.LocalStorage documentation for details");
52860         }
52861
52862         this.initialize();
52863     },
52864
52865     
52866     create: function(operation, callback, scope) {
52867         var records = operation.records,
52868             length  = records.length,
52869             ids     = this.getIds(),
52870             id, record, i;
52871         
52872         operation.setStarted();
52873
52874         for (i = 0; i < length; i++) {
52875             record = records[i];
52876
52877             if (record.phantom) {
52878                 record.phantom = false;
52879                 id = this.getNextId();
52880             } else {
52881                 id = record.getId();
52882             }
52883
52884             this.setRecord(record, id);
52885             ids.push(id);
52886         }
52887
52888         this.setIds(ids);
52889
52890         operation.setCompleted();
52891         operation.setSuccessful();
52892
52893         if (typeof callback == 'function') {
52894             callback.call(scope || this, operation);
52895         }
52896     },
52897
52898     
52899     read: function(operation, callback, scope) {
52900         
52901
52902         var records = [],
52903             ids     = this.getIds(),
52904             length  = ids.length,
52905             i, recordData, record;
52906         
52907         
52908         if (operation.id) {
52909             record = this.getRecord(operation.id);
52910             
52911             if (record) {
52912                 records.push(record);
52913                 operation.setSuccessful();
52914             }
52915         } else {
52916             for (i = 0; i < length; i++) {
52917                 records.push(this.getRecord(ids[i]));
52918             }
52919             operation.setSuccessful();
52920         }
52921         
52922         operation.setCompleted();
52923
52924         operation.resultSet = Ext.create('Ext.data.ResultSet', {
52925             records: records,
52926             total  : records.length,
52927             loaded : true
52928         });
52929
52930         if (typeof callback == 'function') {
52931             callback.call(scope || this, operation);
52932         }
52933     },
52934
52935     
52936     update: function(operation, callback, scope) {
52937         var records = operation.records,
52938             length  = records.length,
52939             ids     = this.getIds(),
52940             record, id, i;
52941
52942         operation.setStarted();
52943
52944         for (i = 0; i < length; i++) {
52945             record = records[i];
52946             this.setRecord(record);
52947             
52948             
52949             
52950             id = record.getId();
52951             if (id !== undefined && Ext.Array.indexOf(ids, id) == -1) {
52952                 ids.push(id);
52953             }
52954         }
52955         this.setIds(ids);
52956
52957         operation.setCompleted();
52958         operation.setSuccessful();
52959
52960         if (typeof callback == 'function') {
52961             callback.call(scope || this, operation);
52962         }
52963     },
52964
52965     
52966     destroy: function(operation, callback, scope) {
52967         var records = operation.records,
52968             length  = records.length,
52969             ids     = this.getIds(),
52970
52971             
52972             newIds  = [].concat(ids),
52973             i;
52974
52975         for (i = 0; i < length; i++) {
52976             Ext.Array.remove(newIds, records[i].getId());
52977             this.removeRecord(records[i], false);
52978         }
52979
52980         this.setIds(newIds);
52981         
52982         operation.setCompleted();
52983         operation.setSuccessful();
52984
52985         if (typeof callback == 'function') {
52986             callback.call(scope || this, operation);
52987         }
52988     },
52989
52990     
52991     getRecord: function(id) {
52992         if (this.cache[id] === undefined) {
52993             var rawData = Ext.decode(this.getStorageObject().getItem(this.getRecordKey(id))),
52994                 data    = {},
52995                 Model   = this.model,
52996                 fields  = Model.prototype.fields.items,
52997                 length  = fields.length,
52998                 i, field, name, record;
52999
53000             for (i = 0; i < length; i++) {
53001                 field = fields[i];
53002                 name  = field.name;
53003
53004                 if (typeof field.decode == 'function') {
53005                     data[name] = field.decode(rawData[name]);
53006                 } else {
53007                     data[name] = rawData[name];
53008                 }
53009             }
53010
53011             record = new Model(data, id);
53012             record.phantom = false;
53013
53014             this.cache[id] = record;
53015         }
53016         
53017         return this.cache[id];
53018     },
53019
53020     
53021     setRecord: function(record, id) {
53022         if (id) {
53023             record.setId(id);
53024         } else {
53025             id = record.getId();
53026         }
53027
53028         var me = this,
53029             rawData = record.data,
53030             data    = {},
53031             model   = me.model,
53032             fields  = model.prototype.fields.items,
53033             length  = fields.length,
53034             i = 0,
53035             field, name, obj, key;
53036
53037         for (; i < length; i++) {
53038             field = fields[i];
53039             name  = field.name;
53040
53041             if (typeof field.encode == 'function') {
53042                 data[name] = field.encode(rawData[name], record);
53043             } else {
53044                 data[name] = rawData[name];
53045             }
53046         }
53047
53048         obj = me.getStorageObject();
53049         key = me.getRecordKey(id);
53050         
53051         
53052         me.cache[id] = record;
53053         
53054         
53055         obj.removeItem(key);
53056         obj.setItem(key, Ext.encode(data));
53057     },
53058
53059     
53060     removeRecord: function(id, updateIds) {
53061         var me = this,
53062             ids;
53063             
53064         if (id.isModel) {
53065             id = id.getId();
53066         }
53067
53068         if (updateIds !== false) {
53069             ids = me.getIds();
53070             Ext.Array.remove(ids, id);
53071             me.setIds(ids);
53072         }
53073
53074         me.getStorageObject().removeItem(me.getRecordKey(id));
53075     },
53076
53077     
53078     getRecordKey: function(id) {
53079         if (id.isModel) {
53080             id = id.getId();
53081         }
53082
53083         return Ext.String.format("{0}-{1}", this.id, id);
53084     },
53085
53086     
53087     getRecordCounterKey: function() {
53088         return Ext.String.format("{0}-counter", this.id);
53089     },
53090
53091     
53092     getIds: function() {
53093         var ids    = (this.getStorageObject().getItem(this.id) || "").split(","),
53094             length = ids.length,
53095             i;
53096
53097         if (length == 1 && ids[0] === "") {
53098             ids = [];
53099         } else {
53100             for (i = 0; i < length; i++) {
53101                 ids[i] = parseInt(ids[i], 10);
53102             }
53103         }
53104
53105         return ids;
53106     },
53107
53108     
53109     setIds: function(ids) {
53110         var obj = this.getStorageObject(),
53111             str = ids.join(",");
53112         
53113         obj.removeItem(this.id);
53114         
53115         if (!Ext.isEmpty(str)) {
53116             obj.setItem(this.id, str);
53117         }
53118     },
53119
53120     
53121     getNextId: function() {
53122         var obj  = this.getStorageObject(),
53123             key  = this.getRecordCounterKey(),
53124             last = obj.getItem(key),
53125             ids, id;
53126         
53127         if (last === null) {
53128             ids = this.getIds();
53129             last = ids[ids.length - 1] || 0;
53130         }
53131         
53132         id = parseInt(last, 10) + 1;
53133         obj.setItem(key, id);
53134         
53135         return id;
53136     },
53137
53138     
53139     initialize: function() {
53140         var storageObject = this.getStorageObject();
53141         storageObject.setItem(this.id, storageObject.getItem(this.id) || "");
53142     },
53143
53144     
53145     clear: function() {
53146         var obj = this.getStorageObject(),
53147             ids = this.getIds(),
53148             len = ids.length,
53149             i;
53150
53151         
53152         for (i = 0; i < len; i++) {
53153             this.removeRecord(ids[i]);
53154         }
53155
53156         
53157         obj.removeItem(this.getRecordCounterKey());
53158         obj.removeItem(this.id);
53159     },
53160
53161     
53162     getStorageObject: function() {
53163         Ext.Error.raise("The getStorageObject function has not been defined in your Ext.data.proxy.WebStorage subclass");
53164     }
53165 });
53166
53167 Ext.define('Ext.data.proxy.LocalStorage', {
53168     extend: 'Ext.data.proxy.WebStorage',
53169     alias: 'proxy.localstorage',
53170     alternateClassName: 'Ext.data.LocalStorageProxy',
53171     
53172     
53173     getStorageObject: function() {
53174         return window.localStorage;
53175     }
53176 });
53177
53178 Ext.define('Ext.data.proxy.Memory', {
53179     extend: 'Ext.data.proxy.Client',
53180     alias: 'proxy.memory',
53181     alternateClassName: 'Ext.data.MemoryProxy',
53182
53183     
53184
53185     constructor: function(config) {
53186         this.callParent([config]);
53187
53188         
53189         this.setReader(this.reader);
53190     },
53191
53192     
53193     read: function(operation, callback, scope) {
53194         var me     = this,
53195             reader = me.getReader(),
53196             result = reader.read(me.data);
53197
53198         Ext.apply(operation, {
53199             resultSet: result
53200         });
53201
53202         operation.setCompleted();
53203         operation.setSuccessful();
53204         Ext.callback(callback, scope || me, [operation]);
53205     },
53206
53207     clear: Ext.emptyFn
53208 });
53209
53210
53211 Ext.define('Ext.data.proxy.Rest', {
53212     extend: 'Ext.data.proxy.Ajax',
53213     alternateClassName: 'Ext.data.RestProxy',
53214     alias : 'proxy.rest',
53215     
53216     
53217     appendId: true,
53218     
53219     
53220     
53221     
53222     batchActions: false,
53223     
53224     
53225     buildUrl: function(request) {
53226         var me        = this,
53227             operation = request.operation,
53228             records   = operation.records || [],
53229             record    = records[0],
53230             format    = me.format,
53231             url       = me.getUrl(request),
53232             id        = record ? record.getId() : operation.id;
53233         
53234         if (me.appendId && id) {
53235             if (!url.match(/\/$/)) {
53236                 url += '/';
53237             }
53238             
53239             url += id;
53240         }
53241         
53242         if (format) {
53243             if (!url.match(/\.$/)) {
53244                 url += '.';
53245             }
53246             
53247             url += format;
53248         }
53249         
53250         request.url = url;
53251         
53252         return me.callParent(arguments);
53253     }
53254 }, function() {
53255     Ext.apply(this.prototype, {
53256         
53257         actionMethods: {
53258             create : 'POST',
53259             read   : 'GET',
53260             update : 'PUT',
53261             destroy: 'DELETE'
53262         }
53263     });
53264 });
53265
53266
53267 Ext.define('Ext.data.proxy.SessionStorage', {
53268     extend: 'Ext.data.proxy.WebStorage',
53269     alias: 'proxy.sessionstorage',
53270     alternateClassName: 'Ext.data.SessionStorageProxy',
53271     
53272     
53273     getStorageObject: function() {
53274         return window.sessionStorage;
53275     }
53276 });
53277
53278
53279 Ext.define('Ext.data.reader.Array', {
53280     extend: 'Ext.data.reader.Json',
53281     alternateClassName: 'Ext.data.ArrayReader',
53282     alias : 'reader.array',
53283
53284     
53285     buildExtractors: function() {
53286         this.callParent(arguments);
53287         
53288         var fields = this.model.prototype.fields.items,
53289             length = fields.length,
53290             extractorFunctions = [],
53291             i;
53292         
53293         for (i = 0; i < length; i++) {
53294             extractorFunctions.push(function(index) {
53295                 return function(data) {
53296                     return data[index];
53297                 };
53298             }(fields[i].mapping || i));
53299         }
53300         
53301         this.extractorFunctions = extractorFunctions;
53302     }
53303 });
53304
53305
53306 Ext.define('Ext.data.reader.Xml', {
53307     extend: 'Ext.data.reader.Reader',
53308     alternateClassName: 'Ext.data.XmlReader',
53309     alias : 'reader.xml',
53310     
53311     
53312
53313     
53314
53315     createAccessor: function() {
53316         var selectValue = function(expr, root){
53317             var node = Ext.DomQuery.selectNode(expr, root),
53318                 val;
53319                 
53320             
53321             
53322         };
53323
53324         return function(expr) {
53325             var me = this;
53326             
53327             if (Ext.isEmpty(expr)) {
53328                 return Ext.emptyFn;
53329             }
53330             
53331             if (Ext.isFunction(expr)) {
53332                 return expr;
53333             }
53334             
53335             return function(root) {
53336                 var node = Ext.DomQuery.selectNode(expr, root),
53337                     val = me.getNodeValue(node);
53338                     
53339                 return Ext.isEmpty(val) ? null : val;
53340             };
53341         };
53342     }(),
53343     
53344     getNodeValue: function(node) {
53345         var val;
53346         if (node && node.firstChild) {
53347             val = node.firstChild.nodeValue;
53348         }
53349         return val || null;
53350     },
53351
53352     
53353     getResponseData: function(response) {
53354         var xml = response.responseXML;
53355
53356         if (!xml) {
53357             Ext.Error.raise({
53358                 response: response,
53359                 msg: 'XML data not found in the response'
53360             });
53361         }
53362
53363         return xml;
53364     },
53365
53366     
53367     getData: function(data) {
53368         return data.documentElement || data;
53369     },
53370
53371     
53372     getRoot: function(data) {
53373         var nodeName = data.nodeName,
53374             root     = this.root;
53375         
53376         if (!root || (nodeName && nodeName == root)) {
53377             return data;
53378         } else if (Ext.DomQuery.isXml(data)) {
53379             
53380             
53381             
53382             return Ext.DomQuery.selectNode(root, data);
53383         }
53384     },
53385
53386     
53387     extractData: function(root) {
53388         var recordName = this.record;
53389         
53390         if (!recordName) {
53391             Ext.Error.raise('Record is a required parameter');
53392         }
53393         
53394         if (recordName != root.nodeName) {
53395             root = Ext.DomQuery.select(recordName, root);
53396         } else {
53397             root = [root];
53398         }
53399         return this.callParent([root]);
53400     },
53401     
53402     
53403     getAssociatedDataRoot: function(data, associationName) {
53404         return Ext.DomQuery.select(associationName, data)[0];
53405     },
53406
53407     
53408     readRecords: function(doc) {
53409         
53410         if (Ext.isArray(doc)) {
53411             doc = doc[0];
53412         }
53413         
53414         
53415         this.xmlData = doc;
53416         return this.callParent([doc]);
53417     }
53418 });
53419
53420
53421 Ext.define('Ext.data.writer.Xml', {
53422     
53423     
53424     
53425     extend: 'Ext.data.writer.Writer',
53426     alternateClassName: 'Ext.data.XmlWriter',
53427     
53428     alias: 'writer.xml',
53429     
53430     
53431     
53432     
53433     documentRoot: 'xmlData',
53434     
53435     
53436     defaultDocumentRoot: 'xmlData',
53437
53438     
53439     header: '',
53440
53441     
53442     record: 'record',
53443
53444     
53445     writeRecords: function(request, data) {
53446         var me = this,
53447             xml = [],
53448             i = 0,
53449             len = data.length,
53450             root = me.documentRoot,
53451             record = me.record,
53452             needsRoot = data.length !== 1,
53453             item,
53454             key;
53455             
53456         
53457         xml.push(me.header || '');
53458         
53459         if (!root && needsRoot) {
53460             root = me.defaultDocumentRoot;
53461         }
53462         
53463         if (root) {
53464             xml.push('<', root, '>');
53465         }
53466             
53467         for (; i < len; ++i) {
53468             item = data[i];
53469             xml.push('<', record, '>');
53470             for (key in item) {
53471                 if (item.hasOwnProperty(key)) {
53472                     xml.push('<', key, '>', item[key], '</', key, '>');
53473                 }
53474             }
53475             xml.push('</', record, '>');
53476         }
53477         
53478         if (root) {
53479             xml.push('</', root, '>');
53480         }
53481             
53482         request.xmlData = xml.join('');
53483         return request;
53484     }
53485 });
53486
53487
53488 Ext.define('Ext.direct.Event', {
53489     
53490     
53491    
53492     alias: 'direct.event',
53493     
53494     requires: ['Ext.direct.Manager'],
53495     
53496     
53497    
53498     status: true,
53499     
53500     constructor: function(config) {
53501         Ext.apply(this, config);
53502     },
53503     
53504     
53505     getData: function(){
53506         return this.data;
53507     }
53508 });
53509
53510
53511 Ext.define('Ext.direct.RemotingEvent', {
53512     
53513     
53514    
53515     extend: 'Ext.direct.Event',
53516     
53517     alias: 'direct.rpc',
53518     
53519     
53520     
53521     
53522     getTransaction: function(){
53523         return this.transaction || Ext.direct.Manager.getTransaction(this.tid);
53524     }
53525 });
53526
53527
53528 Ext.define('Ext.direct.ExceptionEvent', {
53529     
53530     
53531    
53532     extend: 'Ext.direct.RemotingEvent',
53533     
53534     alias: 'direct.exception',
53535     
53536     
53537    
53538    status: false
53539 });
53540
53541
53542 Ext.define('Ext.direct.Provider', {
53543     
53544     
53545    
53546    alias: 'direct.provider',
53547    
53548     mixins: {
53549         observable: 'Ext.util.Observable'   
53550     },
53551    
53552     
53553    
53554    
53555     
53556     constructor : function(config){
53557         var me = this;
53558         
53559         Ext.apply(me, config);
53560         me.addEvents(
53561                         
53562             'connect',
53563                         
53564             'disconnect',
53565                         
53566             'data',
53567                                     
53568             'exception'
53569         );
53570         me.mixins.observable.constructor.call(me, config);
53571     },
53572     
53573     
53574     isConnected: function(){
53575         return false;
53576     },
53577
53578     
53579     connect: Ext.emptyFn,
53580     
53581     
53582     disconnect: Ext.emptyFn
53583 });
53584
53585
53586
53587 Ext.define('Ext.direct.JsonProvider', {
53588     
53589     
53590     
53591     extend: 'Ext.direct.Provider',
53592     
53593     alias: 'direct.jsonprovider',
53594     
53595     uses: ['Ext.direct.ExceptionEvent'],
53596     
53597     
53598    
53599    
53600    parseResponse: function(response){
53601         if (!Ext.isEmpty(response.responseText)) {
53602             if (Ext.isObject(response.responseText)) {
53603                 return response.responseText;
53604             }
53605             return Ext.decode(response.responseText);
53606         }
53607         return null;
53608     },
53609
53610     
53611     createEvents: function(response){
53612         var data = null,
53613             events = [],
53614             event,
53615             i = 0,
53616             len;
53617             
53618         try{
53619             data = this.parseResponse(response);
53620         } catch(e) {
53621             event = Ext.create('Ext.direct.ExceptionEvent', {
53622                 data: e,
53623                 xhr: response,
53624                 code: Ext.direct.Manager.self.exceptions.PARSE,
53625                 message: 'Error parsing json response: \n\n ' + data
53626             });
53627             return [event];
53628         }
53629         
53630         if (Ext.isArray(data)) {
53631             for (len = data.length; i < len; ++i) {
53632                 events.push(this.createEvent(data[i]));
53633             }
53634         } else {
53635             events.push(this.createEvent(data));
53636         }
53637         return events;
53638     },
53639     
53640     
53641     createEvent: function(response){
53642         return Ext.create('direct.' + response.type, response);
53643     }
53644 });
53645
53646 Ext.define('Ext.direct.PollingProvider', {
53647     
53648     
53649     
53650     extend: 'Ext.direct.JsonProvider',
53651     
53652     alias: 'direct.pollingprovider',
53653     
53654     uses: ['Ext.direct.ExceptionEvent'],
53655     
53656     requires: ['Ext.Ajax', 'Ext.util.DelayedTask'],
53657     
53658     
53659     
53660     
53661     interval: 3000,
53662
53663     
53664     
53665     
53666
53667     
53668     constructor : function(config){
53669         this.callParent(arguments);
53670         this.addEvents(
53671             
53672             'beforepoll',            
53673             
53674             'poll'
53675         );
53676     },
53677
53678     
53679     isConnected: function(){
53680         return !!this.pollTask;
53681     },
53682
53683     
53684     connect: function(){
53685         var me = this, url = me.url;
53686         
53687         if (url && !me.pollTask) {
53688             me.pollTask = Ext.TaskManager.start({
53689                 run: function(){
53690                     if (me.fireEvent('beforepoll', me) !== false) {
53691                         if (Ext.isFunction(url)) {
53692                             url(me.baseParams);
53693                         } else {
53694                             Ext.Ajax.request({
53695                                 url: url,
53696                                 callback: me.onData,
53697                                 scope: me,
53698                                 params: me.baseParams
53699                             });
53700                         }
53701                     }
53702                 },
53703                 interval: me.interval,
53704                 scope: me
53705             });
53706             me.fireEvent('connect', me);
53707         } else if (!url) {
53708             Ext.Error.raise('Error initializing PollingProvider, no url configured.');
53709         }
53710     },
53711
53712     
53713     disconnect: function(){
53714         var me = this;
53715         
53716         if (me.pollTask) {
53717             Ext.TaskManager.stop(me.pollTask);
53718             delete me.pollTask;
53719             me.fireEvent('disconnect', me);
53720         }
53721     },
53722
53723     
53724     onData: function(opt, success, response){
53725         var me = this, 
53726             i = 0, 
53727             len,
53728             events;
53729         
53730         if (success) {
53731             events = me.createEvents(response);
53732             for (len = events.length; i < len; ++i) {
53733                 me.fireEvent('data', me, events[i]);
53734             }
53735         } else {
53736             me.fireEvent('data', me, Ext.create('Ext.direct.ExceptionEvent', {
53737                 data: null,
53738                 code: Ext.direct.Manager.self.exceptions.TRANSPORT,
53739                 message: 'Unable to connect to the server.',
53740                 xhr: response
53741             }));
53742         }
53743     }
53744 });
53745
53746 Ext.define('Ext.direct.RemotingMethod', {
53747     
53748     constructor: function(config){
53749         var me = this,
53750             params = Ext.isDefined(config.params) ? config.params : config.len,
53751             name;
53752             
53753         me.name = config.name;
53754         me.formHandler = config.formHandler;
53755         if (Ext.isNumber(params)) {
53756             
53757             me.len = params;
53758             me.ordered = true;
53759         } else {
53760             
53761             me.params = [];
53762             Ext.each(params, function(param){
53763                 name = Ext.isObject(param) ? param.name : param;
53764                 me.params.push(name);
53765             });
53766         }
53767     },
53768     
53769     
53770     getCallData: function(args){
53771         var me = this,
53772             data = null,
53773             len  = me.len,
53774             params = me.params,
53775             callback,
53776             scope,
53777             name;
53778             
53779         if (me.ordered) {
53780             callback = args[len];
53781             scope = args[len + 1];
53782             if (len !== 0) {
53783                 data = args.slice(0, len);
53784             }
53785         } else {
53786             data = Ext.apply({}, args[0]);
53787             callback = args[1];
53788             scope = args[2];
53789             
53790             
53791             for (name in data) {
53792                 if (data.hasOwnProperty(name)) {
53793                     if (!Ext.Array.contains(params, name)) {
53794                         delete data[name];
53795                     }
53796                 }
53797             }
53798         }
53799         
53800         return {
53801             data: data,
53802             callback: callback,
53803             scope: scope    
53804         };
53805     }
53806 });
53807
53808
53809 Ext.define('Ext.direct.Transaction', {
53810     
53811     
53812    
53813     alias: 'direct.transaction',
53814     alternateClassName: 'Ext.Direct.Transaction',
53815    
53816     statics: {
53817         TRANSACTION_ID: 0
53818     },
53819    
53820     
53821    
53822     constructor: function(config){
53823         var me = this;
53824         
53825         Ext.apply(me, config);
53826         me.id = ++me.self.TRANSACTION_ID;
53827         me.retryCount = 0;
53828     },
53829    
53830     send: function(){
53831          this.provider.queueTransaction(this);
53832     },
53833
53834     retry: function(){
53835         this.retryCount++;
53836         this.send();
53837     },
53838
53839     getProvider: function(){
53840         return this.provider;
53841     }
53842 });
53843
53844
53845 Ext.define('Ext.direct.RemotingProvider', {
53846     
53847     
53848    
53849     alias: 'direct.remotingprovider',
53850     
53851     extend: 'Ext.direct.JsonProvider', 
53852     
53853     requires: [
53854         'Ext.util.MixedCollection', 
53855         'Ext.util.DelayedTask', 
53856         'Ext.direct.Transaction',
53857         'Ext.direct.RemotingMethod'
53858     ],
53859    
53860     
53861    
53862    
53863     
53864     
53865     
53866     
53867     
53868     
53869     
53870     
53871     enableBuffer: 10,
53872     
53873     
53874     maxRetries: 1,
53875     
53876     
53877     timeout: undefined,
53878     
53879     constructor : function(config){
53880         var me = this;
53881         me.callParent(arguments);
53882         me.addEvents(
53883                         
53884             'beforecall',            
53885                         
53886             'call'
53887         );
53888         me.namespace = (Ext.isString(me.namespace)) ? Ext.ns(me.namespace) : me.namespace || window;
53889         me.transactions = Ext.create('Ext.util.MixedCollection');
53890         me.callBuffer = [];
53891     },
53892     
53893     
53894     initAPI : function(){
53895         var actions = this.actions,
53896             namespace = this.namespace,
53897             action,
53898             cls,
53899             methods,
53900             i,
53901             len,
53902             method;
53903             
53904         for (action in actions) {
53905             cls = namespace[action];
53906             if (!cls) {
53907                 cls = namespace[action] = {};
53908             }
53909             methods = actions[action];
53910             
53911             for (i = 0, len = methods.length; i < len; ++i) {
53912                 method = Ext.create('Ext.direct.RemotingMethod', methods[i]);
53913                 cls[method.name] = this.createHandler(action, method);
53914             }
53915         }
53916     },
53917     
53918     
53919     createHandler : function(action, method){
53920         var me = this,
53921             handler;
53922         
53923         if (!method.formHandler) {
53924             handler = function(){
53925                 me.configureRequest(action, method, Array.prototype.slice.call(arguments, 0));
53926             };
53927         } else {
53928             handler = function(form, callback, scope){
53929                 me.configureFormRequest(action, method, form, callback, scope);
53930             };
53931         }
53932         handler.directCfg = {
53933             action: action,
53934             method: method
53935         };
53936         return handler;
53937     },
53938     
53939     
53940     isConnected: function(){
53941         return !!this.connected;
53942     },
53943
53944     
53945     connect: function(){
53946         var me = this;
53947         
53948         if (me.url) {
53949             me.initAPI();
53950             me.connected = true;
53951             me.fireEvent('connect', me);
53952         } else if(!me.url) {
53953             Ext.Error.raise('Error initializing RemotingProvider, no url configured.');
53954         }
53955     },
53956
53957     
53958     disconnect: function(){
53959         var me = this;
53960         
53961         if (me.connected) {
53962             me.connected = false;
53963             me.fireEvent('disconnect', me);
53964         }
53965     },
53966     
53967     
53968     runCallback: function(transaction, event){
53969         var funcName = event.status ? 'success' : 'failure',
53970             callback,
53971             result;
53972         
53973         if (transaction && transaction.callback) {
53974             callback = transaction.callback;
53975             result = Ext.isDefined(event.result) ? event.result : event.data;
53976         
53977             if (Ext.isFunction(callback)) {
53978                 callback(result, event);
53979             } else {
53980                 Ext.callback(callback[funcName], callback.scope, [result, event]);
53981                 Ext.callback(callback.callback, callback.scope, [result, event]);
53982             }
53983         }
53984     },
53985     
53986     
53987     onData: function(options, success, response){
53988         var me = this,
53989             i = 0,
53990             len,
53991             events,
53992             event,
53993             transaction,
53994             transactions;
53995             
53996         if (success) {
53997             events = me.createEvents(response);
53998             for (len = events.length; i < len; ++i) {
53999                 event = events[i];
54000                 transaction = me.getTransaction(event);
54001                 me.fireEvent('data', me, event);
54002                 if (transaction) {
54003                     me.runCallback(transaction, event, true);
54004                     Ext.direct.Manager.removeTransaction(transaction);
54005                 }
54006             }
54007         } else {
54008             transactions = [].concat(options.transaction);
54009             for (len = transactions.length; i < len; ++i) {
54010                 transaction = me.getTransaction(transactions[i]);
54011                 if (transaction && transaction.retryCount < me.maxRetries) {
54012                     transaction.retry();
54013                 } else {
54014                     event = Ext.create('Ext.direct.ExceptionEvent', {
54015                         data: null,
54016                         transaction: transaction,
54017                         code: Ext.direct.Manager.self.exceptions.TRANSPORT,
54018                         message: 'Unable to connect to the server.',
54019                         xhr: response
54020                     });
54021                     me.fireEvent('data', me, event);
54022                     if (transaction) {
54023                         me.runCallback(transaction, event, false);
54024                         Ext.direct.Manager.removeTransaction(transaction);
54025                     }
54026                 }
54027             }
54028         }
54029     },
54030     
54031     
54032     getTransaction: function(options){
54033         return options && options.tid ? Ext.direct.Manager.getTransaction(options.tid) : null;
54034     },
54035     
54036     
54037     configureRequest: function(action, method, args){
54038         var me = this,
54039             callData = method.getCallData(args),
54040             data = callData.data, 
54041             callback = callData.callback, 
54042             scope = callData.scope,
54043             transaction;
54044
54045         transaction = Ext.create('Ext.direct.Transaction', {
54046             provider: me,
54047             args: args,
54048             action: action,
54049             method: method.name,
54050             data: data,
54051             callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback
54052         });
54053
54054         if (me.fireEvent('beforecall', me, transaction, method) !== false) {
54055             Ext.direct.Manager.addTransaction(transaction);
54056             me.queueTransaction(transaction);
54057             me.fireEvent('call', me, transaction, method);
54058         }
54059     },
54060     
54061     
54062     getCallData: function(transaction){
54063         return {
54064             action: transaction.action,
54065             method: transaction.method,
54066             data: transaction.data,
54067             type: 'rpc',
54068             tid: transaction.id
54069         };
54070     },
54071     
54072     
54073     sendRequest : function(data){
54074         var me = this,
54075             request = {
54076                 url: me.url,
54077                 callback: me.onData,
54078                 scope: me,
54079                 transaction: data,
54080                 timeout: me.timeout
54081             }, callData,
54082             enableUrlEncode = me.enableUrlEncode,
54083             i = 0,
54084             len,
54085             params;
54086             
54087
54088         if (Ext.isArray(data)) {
54089             callData = [];
54090             for (len = data.length; i < len; ++i) {
54091                 callData.push(me.getCallData(data[i]));
54092             }
54093         } else {
54094             callData = me.getCallData(data);
54095         }
54096
54097         if (enableUrlEncode) {
54098             params = {};
54099             params[Ext.isString(enableUrlEncode) ? enableUrlEncode : 'data'] = Ext.encode(callData);
54100             request.params = params;
54101         } else {
54102             request.jsonData = callData;
54103         }
54104         Ext.Ajax.request(request);
54105     },
54106     
54107     
54108     queueTransaction: function(transaction){
54109         var me = this,
54110             enableBuffer = me.enableBuffer;
54111         
54112         if (transaction.form) {
54113             me.sendFormRequest(transaction);
54114             return;
54115         }
54116         
54117         me.callBuffer.push(transaction);
54118         if (enableBuffer) {
54119             if (!me.callTask) {
54120                 me.callTask = Ext.create('Ext.util.DelayedTask', me.combineAndSend, me);
54121             }
54122             me.callTask.delay(Ext.isNumber(enableBuffer) ? enableBuffer : 10);
54123         } else {
54124             me.combineAndSend();
54125         }
54126     },
54127     
54128     
54129     combineAndSend : function(){
54130         var buffer = this.callBuffer,
54131             len = buffer.length;
54132             
54133         if (len > 0) {
54134             this.sendRequest(len == 1 ? buffer[0] : buffer);
54135             this.callBuffer = [];
54136         }
54137     },
54138     
54139     
54140     configureFormRequest : function(action, method, form, callback, scope){
54141         var me = this,
54142             transaction = Ext.create('Ext.direct.Transaction', {
54143                 provider: me,
54144                 action: action,
54145                 method: method.name,
54146                 args: [form, callback, scope],
54147                 callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback,
54148                 isForm: true
54149             }),
54150             isUpload,
54151             params;
54152
54153         if (me.fireEvent('beforecall', me, transaction, method) !== false) {
54154             Ext.direct.Manager.addTransaction(transaction);
54155             isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data';
54156             
54157             params = {
54158                 extTID: transaction.id,
54159                 extAction: action,
54160                 extMethod: method.name,
54161                 extType: 'rpc',
54162                 extUpload: String(isUpload)
54163             };
54164             
54165             
54166             
54167             Ext.apply(transaction, {
54168                 form: Ext.getDom(form),
54169                 isUpload: isUpload,
54170                 params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
54171             });
54172             me.fireEvent('call', me, transaction, method);
54173             me.sendFormRequest(transaction);
54174         }
54175     },
54176     
54177     
54178     sendFormRequest: function(transaction){
54179         Ext.Ajax.request({
54180             url: this.url,
54181             params: transaction.params,
54182             callback: this.onData,
54183             scope: this,
54184             form: transaction.form,
54185             isUpload: transaction.isUpload,
54186             transaction: transaction
54187         });
54188     }
54189     
54190 });
54191
54192
54193 Ext.define('Ext.draw.Matrix', {
54194
54195     
54196
54197     requires: ['Ext.draw.Draw'],
54198
54199     
54200
54201     constructor: function(a, b, c, d, e, f) {
54202         if (a != null) {
54203             this.matrix = [[a, c, e], [b, d, f], [0, 0, 1]];
54204         }
54205         else {
54206             this.matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
54207         }
54208     },
54209
54210     add: function(a, b, c, d, e, f) {
54211         var me = this,
54212             out = [[], [], []],
54213             matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
54214             x,
54215             y,
54216             z,
54217             res;
54218
54219         for (x = 0; x < 3; x++) {
54220             for (y = 0; y < 3; y++) {
54221                 res = 0;
54222                 for (z = 0; z < 3; z++) {
54223                     res += me.matrix[x][z] * matrix[z][y];
54224                 }
54225                 out[x][y] = res;
54226             }
54227         }
54228         me.matrix = out;
54229     },
54230
54231     prepend: function(a, b, c, d, e, f) {
54232         var me = this,
54233             out = [[], [], []],
54234             matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
54235             x,
54236             y,
54237             z,
54238             res;
54239
54240         for (x = 0; x < 3; x++) {
54241             for (y = 0; y < 3; y++) {
54242                 res = 0;
54243                 for (z = 0; z < 3; z++) {
54244                     res += matrix[x][z] * me.matrix[z][y];
54245                 }
54246                 out[x][y] = res;
54247             }
54248         }
54249         me.matrix = out;
54250     },
54251
54252     invert: function() {
54253         var matrix = this.matrix,
54254             a = matrix[0][0],
54255             b = matrix[1][0],
54256             c = matrix[0][1],
54257             d = matrix[1][1],
54258             e = matrix[0][2],
54259             f = matrix[1][2],
54260             x = a * d - b * c;
54261         return new Ext.draw.Matrix(d / x, -b / x, -c / x, a / x, (c * f - d * e) / x, (b * e - a * f) / x);
54262     },
54263
54264     clone: function() {
54265         var matrix = this.matrix,
54266             a = matrix[0][0],
54267             b = matrix[1][0],
54268             c = matrix[0][1],
54269             d = matrix[1][1],
54270             e = matrix[0][2],
54271             f = matrix[1][2];
54272         return new Ext.draw.Matrix(a, b, c, d, e, f);
54273     },
54274
54275     translate: function(x, y) {
54276         this.prepend(1, 0, 0, 1, x, y);
54277     },
54278
54279     scale: function(x, y, cx, cy) {
54280         var me = this;
54281         if (y == null) {
54282             y = x;
54283         }
54284         me.add(1, 0, 0, 1, cx, cy);
54285         me.add(x, 0, 0, y, 0, 0);
54286         me.add(1, 0, 0, 1, -cx, -cy);
54287     },
54288
54289     rotate: function(a, x, y) {
54290         a = Ext.draw.Draw.rad(a);
54291         var me = this,
54292             cos = +Math.cos(a).toFixed(9),
54293             sin = +Math.sin(a).toFixed(9);
54294         me.add(cos, sin, -sin, cos, x, y);
54295         me.add(1, 0, 0, 1, -x, -y);
54296     },
54297
54298     x: function(x, y) {
54299         var matrix = this.matrix;
54300         return x * matrix[0][0] + y * matrix[0][1] + matrix[0][2];
54301     },
54302
54303     y: function(x, y) {
54304         var matrix = this.matrix;
54305         return x * matrix[1][0] + y * matrix[1][1] + matrix[1][2];
54306     },
54307
54308     get: function(i, j) {
54309         return + this.matrix[i][j].toFixed(4);
54310     },
54311
54312     toString: function() {
54313         var me = this;
54314         return [me.get(0, 0), me.get(0, 1), me.get(1, 0), me.get(1, 1), 0, 0].join();
54315     },
54316
54317     toSvg: function() {
54318         var me = this;
54319         return "matrix(" + [me.get(0, 0), me.get(1, 0), me.get(0, 1), me.get(1, 1), me.get(0, 2), me.get(1, 2)].join() + ")";
54320     },
54321
54322     toFilter: function() {
54323         var me = this;
54324         return "progid:DXImageTransform.Microsoft.Matrix(M11=" + me.get(0, 0) +
54325             ", M12=" + me.get(0, 1) + ", M21=" + me.get(1, 0) + ", M22=" + me.get(1, 1) +
54326             ", Dx=" + me.get(0, 2) + ", Dy=" + me.get(1, 2) + ")";
54327     },
54328
54329     offset: function() {
54330         var matrix = this.matrix;
54331         return [matrix[0][2].toFixed(4), matrix[1][2].toFixed(4)];
54332     },
54333
54334     
54335     split: function () {
54336         function norm(a) {
54337             return a[0] * a[0] + a[1] * a[1];
54338         }
54339         function normalize(a) {
54340             var mag = Math.sqrt(norm(a));
54341             a[0] /= mag;
54342             a[1] /= mag;
54343         }
54344         var matrix = this.matrix,
54345             out = {
54346                 translateX: matrix[0][2],
54347                 translateY: matrix[1][2]
54348             },
54349             row;
54350
54351         
54352         row = [[matrix[0][0], matrix[0][1]], [matrix[1][1], matrix[1][1]]];
54353         out.scaleX = Math.sqrt(norm(row[0]));
54354         normalize(row[0]);
54355
54356         out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
54357         row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
54358
54359         out.scaleY = Math.sqrt(norm(row[1]));
54360         normalize(row[1]);
54361         out.shear /= out.scaleY;
54362
54363         
54364         out.rotate = Math.asin(-row[0][1]);
54365
54366         out.isSimple = !+out.shear.toFixed(9) && (out.scaleX.toFixed(9) == out.scaleY.toFixed(9) || !out.rotate);
54367
54368         return out;
54369     }
54370 });
54371
54372 Ext.define('Ext.draw.SpriteDD', {
54373     extend: 'Ext.dd.DragSource',
54374
54375     constructor : function(sprite, cfg){
54376         var me = this,
54377             el = sprite.el;
54378         me.sprite = sprite;
54379         me.el = el;
54380         me.dragData = {el: el, sprite: sprite};
54381         me.callParent([el, cfg]);
54382         me.sprite.setStyle('cursor', 'move');
54383     },
54384
54385     showFrame: Ext.emptyFn,
54386     createFrame : Ext.emptyFn,
54387
54388     getDragEl : function(e){
54389         return this.el;
54390     },
54391     
54392     getRegion: function() {
54393         var me = this,
54394             el = me.el,
54395             pos, x1, x2, y1, y2, t, r, b, l, bbox, sprite;
54396         
54397         sprite = me.sprite;
54398         bbox = sprite.getBBox();
54399         
54400         try {
54401             pos = Ext.core.Element.getXY(el);
54402         } catch (e) { }
54403
54404         if (!pos) {
54405             return null;
54406         }
54407
54408         x1 = pos[0];
54409         x2 = x1 + bbox.width;
54410         y1 = pos[1];
54411         y2 = y1 + bbox.height;
54412         
54413         return Ext.create('Ext.util.Region', y1, x2, y2, x1);
54414     },
54415
54416     
54417      
54418     startDrag: function(x, y) {
54419         var me = this,
54420             attr = me.sprite.attr,
54421             trans = attr.translation;
54422         if (me.sprite.vml) {
54423             me.prevX = x + attr.x;
54424             me.prevY = y + attr.y;
54425         } else {
54426             me.prevX = x - trans.x;
54427             me.prevY = y - trans.y;
54428         }
54429     },
54430
54431     onDrag: function(e) {
54432         var xy = e.getXY(),
54433             me = this,
54434             sprite = me.sprite,
54435             attr = sprite.attr;
54436         me.translateX = xy[0] - me.prevX;
54437         me.translateY = xy[1] - me.prevY;
54438         sprite.setAttributes({
54439             translate: {
54440                 x: me.translateX,
54441                 y: me.translateY
54442             }
54443         }, true);
54444         if (sprite.vml) {
54445             me.prevX = xy[0] + attr.x || 0;
54446             me.prevY = xy[1] + attr.y || 0;
54447         }
54448     }
54449 });
54450
54451 Ext.define('Ext.draw.Sprite', {
54452     
54453
54454     mixins: {
54455         observable: 'Ext.util.Observable',
54456         animate: 'Ext.util.Animate'
54457     },
54458
54459     requires: ['Ext.draw.SpriteDD'],
54460
54461     
54462
54463     dirty: false,
54464     dirtyHidden: false,
54465     dirtyTransform: false,
54466     dirtyPath: true,
54467     dirtyFont: true,
54468     zIndexDirty: true,
54469     isSprite: true,
54470     zIndex: 0,
54471     fontProperties: [
54472         'font',
54473         'font-size',
54474         'font-weight',
54475         'font-style',
54476         'font-family',
54477         'text-anchor',
54478         'text'
54479     ],
54480     pathProperties: [
54481         'x',
54482         'y',
54483         'd',
54484         'path',
54485         'height',
54486         'width',
54487         'radius',
54488         'r',
54489         'rx',
54490         'ry',
54491         'cx',
54492         'cy'
54493     ],
54494     constructor: function(config) {
54495         var me = this;
54496         config = config || {};
54497         me.id = Ext.id(null, 'ext-sprite-');
54498         me.transformations = [];
54499         Ext.copyTo(this, config, 'surface,group,type,draggable');
54500         
54501         me.bbox = {};
54502         me.attr = {
54503             zIndex: 0,
54504             translation: {
54505                 x: null,
54506                 y: null
54507             },
54508             rotation: {
54509                 degrees: null,
54510                 x: null,
54511                 y: null
54512             },
54513             scaling: {
54514                 x: null,
54515                 y: null,
54516                 cx: null,
54517                 cy: null
54518             }
54519         };
54520         
54521         delete config.surface;
54522         delete config.group;
54523         delete config.type;
54524         delete config.draggable;
54525         me.setAttributes(config);
54526         me.addEvents(
54527             'beforedestroy',
54528             'destroy',
54529             'render',
54530             'mousedown',
54531             'mouseup',
54532             'mouseover',
54533             'mouseout',
54534             'mousemove',
54535             'click'
54536         );
54537         me.mixins.observable.constructor.apply(this, arguments);
54538     },
54539
54540     
54541     initDraggable: function() {
54542         var me = this;
54543         me.draggable = true;
54544         
54545         if (!me.el) {
54546             me.surface.createSprite(me);
54547         }
54548         me.dd = Ext.create('Ext.draw.SpriteDD', me, Ext.isBoolean(me.draggable) ? null : me.draggable);
54549         me.on('beforedestroy', me.dd.destroy, me.dd);
54550     },
54551
54552     
54553     setAttributes: function(attrs, redraw) {
54554         var me = this,
54555             fontProps = me.fontProperties,
54556             fontPropsLength = fontProps.length,
54557             pathProps = me.pathProperties,
54558             pathPropsLength = pathProps.length,
54559             hasSurface = !!me.surface,
54560             custom = hasSurface && me.surface.customAttributes || {},
54561             spriteAttrs = me.attr,
54562             attr, i, translate, translation, rotate, rotation, scale, scaling;
54563
54564         for (attr in custom) {
54565             if (attrs.hasOwnProperty(attr) && typeof custom[attr] == "function") {
54566                 Ext.apply(attrs, custom[attr].apply(me, [].concat(attrs[attr])));
54567             }
54568         }
54569
54570         
54571         if (!!attrs.hidden !== !!spriteAttrs.hidden) {
54572             me.dirtyHidden = true;
54573         }
54574
54575         
54576         for (i = 0; i < pathPropsLength; i++) {
54577             attr = pathProps[i];
54578             if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
54579                 me.dirtyPath = true;
54580                 break;
54581             }
54582         }
54583
54584         
54585         if ('zIndex' in attrs) {
54586             me.zIndexDirty = true;
54587         }
54588
54589         
54590         for (i = 0; i < fontPropsLength; i++) {
54591             attr = fontProps[i];
54592             if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
54593                 me.dirtyFont = true;
54594                 break;
54595             }
54596         }
54597
54598         translate = attrs.translate;
54599         translation = spriteAttrs.translation;
54600         if (translate) {
54601             if ((translate.x && translate.x !== translation.x) ||
54602                 (translate.y && translate.y !== translation.y)) {
54603                 Ext.apply(translation, translate);
54604                 me.dirtyTransform = true;
54605             }
54606             delete attrs.translate;
54607         }
54608
54609         rotate = attrs.rotate;
54610         rotation = spriteAttrs.rotation;
54611         if (rotate) {
54612             if ((rotate.x && rotate.x !== rotation.x) || 
54613                 (rotate.y && rotate.y !== rotation.y) ||
54614                 (rotate.degrees && rotate.degrees !== rotation.degrees)) {
54615                 Ext.apply(rotation, rotate);
54616                 me.dirtyTransform = true;
54617             }
54618             delete attrs.rotate;
54619         }
54620
54621         scale = attrs.scale;
54622         scaling = spriteAttrs.scaling;
54623         if (scale) {
54624             if ((scale.x && scale.x !== scaling.x) || 
54625                 (scale.y && scale.y !== scaling.y) ||
54626                 (scale.cx && scale.cx !== scaling.cx) ||
54627                 (scale.cy && scale.cy !== scaling.cy)) {
54628                 Ext.apply(scaling, scale);
54629                 me.dirtyTransform = true;
54630             }
54631             delete attrs.scale;
54632         }
54633
54634         Ext.apply(spriteAttrs, attrs);
54635         me.dirty = true;
54636
54637         if (redraw === true && hasSurface) {
54638             me.redraw();
54639         }
54640         return this;
54641     },
54642
54643     
54644     getBBox: function() {
54645         return this.surface.getBBox(this);
54646     },
54647     
54648     setText: function(text) {
54649         return this.surface.setText(this, text);
54650     },
54651
54652     
54653     hide: function(redraw) {
54654         this.setAttributes({
54655             hidden: true
54656         }, redraw);
54657         return this;
54658     },
54659
54660     
54661     show: function(redraw) {
54662         this.setAttributes({
54663             hidden: false
54664         }, redraw);
54665         return this;
54666     },
54667
54668     
54669     remove: function() {
54670         if (this.surface) {
54671             this.surface.remove(this);
54672             return true;
54673         }
54674         return false;
54675     },
54676
54677     onRemove: function() {
54678         this.surface.onRemove(this);
54679     },
54680
54681     
54682     destroy: function() {
54683         var me = this;
54684         if (me.fireEvent('beforedestroy', me) !== false) {
54685             me.remove();
54686             me.surface.onDestroy(me);
54687             me.clearListeners();
54688             me.fireEvent('destroy');
54689         }
54690     },
54691
54692     
54693     redraw: function() {
54694         this.surface.renderItem(this);
54695         return this;
54696     },
54697
54698     
54699     setStyle: function() {
54700         this.el.setStyle.apply(this.el, arguments);
54701         return this;
54702     },
54703
54704     
54705     addCls: function(obj) {
54706         this.surface.addCls(this, obj);
54707         return this;
54708     },
54709
54710     
54711     removeCls: function(obj) {
54712         this.surface.removeCls(this, obj);
54713         return this;
54714     }
54715 });
54716
54717
54718 Ext.define('Ext.draw.engine.Svg', {
54719
54720     
54721
54722     extend: 'Ext.draw.Surface',
54723
54724     requires: ['Ext.draw.Draw', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.core.Element'],
54725
54726     
54727
54728     engine: 'Svg',
54729
54730     trimRe: /^\s+|\s+$/g,
54731     spacesRe: /\s+/,
54732     xlink: "http:/" + "/www.w3.org/1999/xlink",
54733
54734     translateAttrs: {
54735         radius: "r",
54736         radiusX: "rx",
54737         radiusY: "ry",
54738         path: "d",
54739         lineWidth: "stroke-width",
54740         fillOpacity: "fill-opacity",
54741         strokeOpacity: "stroke-opacity",
54742         strokeLinejoin: "stroke-linejoin"
54743     },
54744
54745     minDefaults: {
54746         circle: {
54747             cx: 0,
54748             cy: 0,
54749             r: 0,
54750             fill: "none",
54751             stroke: null,
54752             "stroke-width": null,
54753             opacity: null,
54754             "fill-opacity": null,
54755             "stroke-opacity": null
54756         },
54757         ellipse: {
54758             cx: 0,
54759             cy: 0,
54760             rx: 0,
54761             ry: 0,
54762             fill: "none",
54763             stroke: null,
54764             "stroke-width": null,
54765             opacity: null,
54766             "fill-opacity": null,
54767             "stroke-opacity": null
54768         },
54769         rect: {
54770             x: 0,
54771             y: 0,
54772             width: 0,
54773             height: 0,
54774             rx: 0,
54775             ry: 0,
54776             fill: "none",
54777             stroke: null,
54778             "stroke-width": null,
54779             opacity: null,
54780             "fill-opacity": null,
54781             "stroke-opacity": null
54782         },
54783         text: {
54784             x: 0,
54785             y: 0,
54786             "text-anchor": "start",
54787             "font-family": null,
54788             "font-size": null,
54789             "font-weight": null,
54790             "font-style": null,
54791             fill: "#000",
54792             stroke: null,
54793             "stroke-width": null,
54794             opacity: null,
54795             "fill-opacity": null,
54796             "stroke-opacity": null
54797         },
54798         path: {
54799             d: "M0,0",
54800             fill: "none",
54801             stroke: null,
54802             "stroke-width": null,
54803             opacity: null,
54804             "fill-opacity": null,
54805             "stroke-opacity": null
54806         },
54807         image: {
54808             x: 0,
54809             y: 0,
54810             width: 0,
54811             height: 0,
54812             preserveAspectRatio: "none",
54813             opacity: null
54814         }
54815     },
54816
54817     createSvgElement: function(type, attrs) {
54818         var el = this.domRef.createElementNS("http:/" + "/www.w3.org/2000/svg", type),
54819             key;
54820         if (attrs) {
54821             for (key in attrs) {
54822                 el.setAttribute(key, String(attrs[key]));
54823             }
54824         }
54825         return el;
54826     },
54827
54828     createSpriteElement: function(sprite) {
54829         
54830         var el = this.createSvgElement(sprite.type);
54831         el.id = sprite.id;
54832         if (el.style) {
54833             el.style.webkitTapHighlightColor = "rgba(0,0,0,0)";
54834         }
54835         sprite.el = Ext.get(el);
54836         this.applyZIndex(sprite); 
54837         sprite.matrix = Ext.create('Ext.draw.Matrix');
54838         sprite.bbox = {
54839             plain: 0,
54840             transform: 0
54841         };
54842         sprite.fireEvent("render", sprite);
54843         return el;
54844     },
54845
54846     getBBox: function (sprite, isWithoutTransform) {
54847         var realPath = this["getPath" + sprite.type](sprite);
54848         if (isWithoutTransform) {
54849             sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath);
54850             return sprite.bbox.plain;
54851         }
54852         sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
54853         return sprite.bbox.transform;
54854     },
54855     
54856     getBBoxText: function (sprite) {
54857         var bbox = {},
54858             bb, height, width, i, ln, el;
54859
54860         if (sprite && sprite.el) {
54861             el = sprite.el.dom;
54862             try {
54863                 bbox = el.getBBox();
54864                 return bbox;
54865             } catch(e) {
54866                 
54867             }
54868             bbox = {x: bbox.x, y: Infinity, width: 0, height: 0};
54869             ln = el.getNumberOfChars();
54870             for (i = 0; i < ln; i++) {
54871                 bb = el.getExtentOfChar(i);
54872                 bbox.y = Math.min(bb.y, bbox.y);
54873                 height = bb.y + bb.height - bbox.y;
54874                 bbox.height = Math.max(bbox.height, height);
54875                 width = bb.x + bb.width - bbox.x;
54876                 bbox.width = Math.max(bbox.width, width);
54877             }
54878             return bbox;
54879         }
54880     },
54881
54882     hide: function() {
54883         Ext.get(this.el).hide();
54884     },
54885
54886     show: function() {
54887         Ext.get(this.el).show();
54888     },
54889
54890     hidePrim: function(sprite) {
54891         this.addCls(sprite, Ext.baseCSSPrefix + 'hide-visibility');
54892     },
54893
54894     showPrim: function(sprite) {
54895         this.removeCls(sprite, Ext.baseCSSPrefix + 'hide-visibility');
54896     },
54897
54898     getDefs: function() {
54899         return this._defs || (this._defs = this.createSvgElement("defs"));
54900     },
54901
54902     transform: function(sprite) {
54903         var me = this,
54904             matrix = Ext.create('Ext.draw.Matrix'),
54905             transforms = sprite.transformations,
54906             transformsLength = transforms.length,
54907             i = 0,
54908             transform, type;
54909             
54910         for (; i < transformsLength; i++) {
54911             transform = transforms[i];
54912             type = transform.type;
54913             if (type == "translate") {
54914                 matrix.translate(transform.x, transform.y);
54915             }
54916             else if (type == "rotate") {
54917                 matrix.rotate(transform.degrees, transform.x, transform.y);
54918             }
54919             else if (type == "scale") {
54920                 matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY);
54921             }
54922         }
54923         sprite.matrix = matrix;
54924         sprite.el.set({transform: matrix.toSvg()});
54925     },
54926
54927     setSize: function(w, h) {
54928         var me = this,
54929             el = me.el;
54930         
54931         w = +w || me.width;
54932         h = +h || me.height;
54933         me.width = w;
54934         me.height = h;
54935
54936         el.setSize(w, h);
54937         el.set({
54938             width: w,
54939             height: h
54940         });
54941         me.callParent([w, h]);
54942     },
54943
54944     
54945     getRegion: function() {
54946         
54947         
54948         var svgXY = this.el.getXY(),
54949             rectXY = this.bgRect.getXY(),
54950             max = Math.max,
54951             x = max(svgXY[0], rectXY[0]),
54952             y = max(svgXY[1], rectXY[1]);
54953         return {
54954             left: x,
54955             top: y,
54956             right: x + this.width,
54957             bottom: y + this.height
54958         };
54959     },
54960
54961     onRemove: function(sprite) {
54962         if (sprite.el) {
54963             sprite.el.remove();
54964             delete sprite.el;
54965         }
54966         this.callParent(arguments);
54967     },
54968     
54969     setViewBox: function(x, y, width, height) {
54970         if (isFinite(x) && isFinite(y) && isFinite(width) && isFinite(height)) {
54971             this.callParent(arguments);
54972             this.el.dom.setAttribute("viewBox", [x, y, width, height].join(" "));
54973         }
54974     },
54975
54976     render: function (container) {
54977         var me = this;
54978         if (!me.el) {
54979             var width = me.width || 10,
54980                 height = me.height || 10,
54981                 el = me.createSvgElement('svg', {
54982                     xmlns: "http:/" + "/www.w3.org/2000/svg",
54983                     version: 1.1,
54984                     width: width,
54985                     height: height
54986                 }),
54987                 defs = me.getDefs(),
54988
54989                 
54990                 
54991                 
54992                 
54993                 bgRect = me.createSvgElement("rect", {
54994                     width: "100%",
54995                     height: "100%",
54996                     fill: "#000",
54997                     stroke: "none",
54998                     opacity: 0
54999                 }),
55000                 webkitRect;
55001             
55002                 if (Ext.isSafari3) {
55003                     
55004                     webkitRect = me.createSvgElement("rect", {
55005                         x: -10,
55006                         y: -10,
55007                         width: "110%",
55008                         height: "110%",
55009                         fill: "none",
55010                         stroke: "#000"
55011                     });
55012                 }
55013             el.appendChild(defs);
55014             if (Ext.isSafari3) {
55015                 el.appendChild(webkitRect);
55016             }
55017             el.appendChild(bgRect);
55018             container.appendChild(el);
55019             me.el = Ext.get(el);
55020             me.bgRect = Ext.get(bgRect);
55021             if (Ext.isSafari3) {
55022                 me.webkitRect = Ext.get(webkitRect);
55023                 me.webkitRect.hide();
55024             }
55025             me.el.on({
55026                 scope: me,
55027                 mouseup: me.onMouseUp,
55028                 mousedown: me.onMouseDown,
55029                 mouseover: me.onMouseOver,
55030                 mouseout: me.onMouseOut,
55031                 mousemove: me.onMouseMove,
55032                 mouseenter: me.onMouseEnter,
55033                 mouseleave: me.onMouseLeave,
55034                 click: me.onClick
55035             });
55036         }
55037         me.renderAll();
55038     },
55039
55040     
55041     onMouseEnter: function(e) {
55042         if (this.el.parent().getRegion().contains(e.getPoint())) {
55043             this.fireEvent('mouseenter', e);
55044         }
55045     },
55046
55047     
55048     onMouseLeave: function(e) {
55049         if (!this.el.parent().getRegion().contains(e.getPoint())) {
55050             this.fireEvent('mouseleave', e);
55051         }
55052     },
55053     
55054     processEvent: function(name, e) {
55055         var target = e.getTarget(),
55056             surface = this.surface,
55057             sprite;
55058
55059         this.fireEvent(name, e);
55060         
55061         if (target.nodeName == "tspan" && target.parentNode) {
55062             target = target.parentNode;
55063         }
55064         sprite = this.items.get(target.id);
55065         if (sprite) {
55066             sprite.fireEvent(name, sprite, e);
55067         }
55068     },
55069
55070     
55071     tuneText: function (sprite, attrs) {
55072         var el = sprite.el.dom,
55073             tspans = [],
55074             height, tspan, text, i, ln, texts, factor;
55075
55076         if (attrs.hasOwnProperty("text")) {
55077            tspans = this.setText(sprite, attrs.text);
55078         }
55079         
55080         if (tspans.length) {
55081             height = this.getBBoxText(sprite).height;
55082             for (i = 0, ln = tspans.length; i < ln; i++) {
55083                 
55084                 
55085                 factor = (Ext.isFF3_0 || Ext.isFF3_5) ? 2 : 4;
55086                 tspans[i].setAttribute("dy", i ? height * 1.2 : height / factor);
55087             }
55088             sprite.dirty = true;
55089         }
55090     },
55091
55092     setText: function(sprite, textString) {
55093          var me = this,
55094              el = sprite.el.dom,
55095              x = el.getAttribute("x"),
55096              tspans = [],
55097              height, tspan, text, i, ln, texts;
55098         
55099         while (el.firstChild) {
55100             el.removeChild(el.firstChild);
55101         }
55102         
55103         texts = String(textString).split("\n");
55104         for (i = 0, ln = texts.length; i < ln; i++) {
55105             text = texts[i];
55106             if (text) {
55107                 tspan = me.createSvgElement("tspan");
55108                 tspan.appendChild(document.createTextNode(Ext.htmlDecode(text)));
55109                 tspan.setAttribute("x", x);
55110                 el.appendChild(tspan);
55111                 tspans[i] = tspan;
55112             }
55113         }
55114         return tspans;
55115     },
55116
55117     renderAll: function() {
55118         this.items.each(this.renderItem, this);
55119     },
55120
55121     renderItem: function (sprite) {
55122         if (!this.el) {
55123             return;
55124         }
55125         if (!sprite.el) {
55126             this.createSpriteElement(sprite);
55127         }
55128         if (sprite.zIndexDirty) {
55129             this.applyZIndex(sprite);
55130         }
55131         if (sprite.dirty) {
55132             this.applyAttrs(sprite);
55133             this.applyTransformations(sprite);
55134         }
55135     },
55136
55137     redraw: function(sprite) {
55138         sprite.dirty = sprite.zIndexDirty = true;
55139         this.renderItem(sprite);
55140     },
55141
55142     applyAttrs: function (sprite) {
55143         var me = this,
55144             el = sprite.el,
55145             group = sprite.group,
55146             sattr = sprite.attr,
55147             groups, i, ln, attrs, font, key, style, name, rect;
55148
55149         if (group) {
55150             groups = [].concat(group);
55151             ln = groups.length;
55152             for (i = 0; i < ln; i++) {
55153                 group = groups[i];
55154                 me.getGroup(group).add(sprite);
55155             }
55156             delete sprite.group;
55157         }
55158         attrs = me.scrubAttrs(sprite) || {};
55159
55160         
55161         sprite.bbox.plain = 0;
55162         sprite.bbox.transform = 0;
55163             if (sprite.type == "circle" || sprite.type == "ellipse") {
55164                 attrs.cx = attrs.cx || attrs.x;
55165                 attrs.cy = attrs.cy || attrs.y;
55166             }
55167             else if (sprite.type == "rect") {
55168                 attrs.rx = attrs.ry = attrs.r;
55169             }
55170             else if (sprite.type == "path" && attrs.d) {
55171                 attrs.d = Ext.draw.Draw.pathToAbsolute(attrs.d);
55172             }
55173             sprite.dirtyPath = false;
55174         
55175
55176         if (attrs['clip-rect']) {
55177             me.setClip(sprite, attrs);
55178             delete attrs['clip-rect'];
55179         }
55180         if (sprite.type == 'text' && attrs.font && sprite.dirtyFont) {
55181             el.set({ style: "font: " + attrs.font});
55182             sprite.dirtyFont = false;
55183         }
55184         if (sprite.type == "image") {
55185             el.dom.setAttributeNS(me.xlink, "href", attrs.src);
55186         }
55187         Ext.applyIf(attrs, me.minDefaults[sprite.type]);
55188
55189         if (sprite.dirtyHidden) {
55190             (sattr.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
55191             sprite.dirtyHidden = false;
55192         }
55193         for (key in attrs) {
55194             if (attrs.hasOwnProperty(key) && attrs[key] != null) {
55195                 el.dom.setAttribute(key, String(attrs[key]));
55196             }
55197         }
55198         if (sprite.type == 'text') {
55199             me.tuneText(sprite, attrs);
55200         }
55201
55202         
55203         style = sattr.style;
55204         if (style) {
55205             el.setStyle(style);
55206         }
55207
55208         sprite.dirty = false;
55209
55210         if (Ext.isSafari3) {
55211             
55212             me.webkitRect.show();
55213             setTimeout(function () {
55214                 me.webkitRect.hide();
55215             });
55216         }
55217     },
55218
55219     setClip: function(sprite, params) {
55220         var me = this,
55221             rect = params["clip-rect"],
55222             clipEl, clipPath;
55223         if (rect) {
55224             if (sprite.clip) {
55225                 sprite.clip.parentNode.parentNode.removeChild(sprite.clip.parentNode);
55226             }
55227             clipEl = me.createSvgElement('clipPath');
55228             clipPath = me.createSvgElement('rect');
55229             clipEl.id = Ext.id(null, 'ext-clip-');
55230             clipPath.setAttribute("x", rect.x);
55231             clipPath.setAttribute("y", rect.y);
55232             clipPath.setAttribute("width", rect.width);
55233             clipPath.setAttribute("height", rect.height);
55234             clipEl.appendChild(clipPath);
55235             me.getDefs().appendChild(clipEl);
55236             sprite.el.dom.setAttribute("clip-path", "url(#" + clipEl.id + ")");
55237             sprite.clip = clipPath;
55238         }
55239         
55240         
55241         
55242         
55243         
55244         
55245     },
55246
55247     
55248     applyZIndex: function(sprite) {
55249         var idx = this.normalizeSpriteCollection(sprite),
55250             el = sprite.el,
55251             prevEl;
55252         if (this.el.dom.childNodes[idx + 2] !== el.dom) { 
55253             if (idx > 0) {
55254                 
55255                 do {
55256                     prevEl = this.items.getAt(--idx).el;
55257                 } while (!prevEl && idx > 0);
55258             }
55259             el.insertAfter(prevEl || this.bgRect);
55260         }
55261         sprite.zIndexDirty = false;
55262     },
55263
55264     createItem: function (config) {
55265         var sprite = Ext.create('Ext.draw.Sprite', config);
55266         sprite.surface = this;
55267         return sprite;
55268     },
55269
55270     addGradient: function(gradient) {
55271         gradient = Ext.draw.Draw.parseGradient(gradient);
55272         var ln = gradient.stops.length,
55273             vector = gradient.vector,
55274             gradientEl,
55275             stop,
55276             stopEl,
55277             i;
55278         if (gradient.type == "linear") {
55279             gradientEl = this.createSvgElement("linearGradient");
55280             gradientEl.setAttribute("x1", vector[0]);
55281             gradientEl.setAttribute("y1", vector[1]);
55282             gradientEl.setAttribute("x2", vector[2]);
55283             gradientEl.setAttribute("y2", vector[3]);
55284         }
55285         else {
55286             gradientEl = this.createSvgElement("radialGradient");
55287             gradientEl.setAttribute("cx", gradient.centerX);
55288             gradientEl.setAttribute("cy", gradient.centerY);
55289             gradientEl.setAttribute("r", gradient.radius);
55290             if (Ext.isNumber(gradient.focalX) && Ext.isNumber(gradient.focalY)) {
55291                 gradientEl.setAttribute("fx", gradient.focalX);
55292                 gradientEl.setAttribute("fy", gradient.focalY);
55293             }
55294         }    
55295         gradientEl.id = gradient.id;
55296         this.getDefs().appendChild(gradientEl);
55297
55298         for (i = 0; i < ln; i++) {
55299             stop = gradient.stops[i];
55300             stopEl = this.createSvgElement("stop");
55301             stopEl.setAttribute("offset", stop.offset + "%");
55302             stopEl.setAttribute("stop-color", stop.color);
55303             stopEl.setAttribute("stop-opacity",stop.opacity);
55304             gradientEl.appendChild(stopEl);
55305         }
55306     },
55307
55308     
55309     hasCls: function(sprite, className) {
55310         return className && (' ' + (sprite.el.dom.getAttribute('class') || '') + ' ').indexOf(' ' + className + ' ') != -1;
55311     },
55312
55313     addCls: function(sprite, className) {
55314         var el = sprite.el,
55315             i,
55316             len,
55317             v,
55318             cls = [],
55319             curCls =  el.getAttribute('class') || '';
55320         
55321         if (!Ext.isArray(className)) {
55322             if (typeof className == 'string' && !this.hasCls(sprite, className)) {
55323                 el.set({ 'class': curCls + ' ' + className });
55324             }
55325         }
55326         else {
55327             for (i = 0, len = className.length; i < len; i++) {
55328                 v = className[i];
55329                 if (typeof v == 'string' && (' ' + curCls + ' ').indexOf(' ' + v + ' ') == -1) {
55330                     cls.push(v);
55331                 }
55332             }
55333             if (cls.length) {
55334                 el.set({ 'class': ' ' + cls.join(' ') });
55335             }
55336         }
55337     },
55338
55339     removeCls: function(sprite, className) {
55340         var me = this,
55341             el = sprite.el,
55342             curCls =  el.getAttribute('class') || '',
55343             i, idx, len, cls, elClasses;
55344         if (!Ext.isArray(className)){
55345             className = [className];
55346         }
55347         if (curCls) {
55348             elClasses = curCls.replace(me.trimRe, ' ').split(me.spacesRe);
55349             for (i = 0, len = className.length; i < len; i++) {
55350                 cls = className[i];
55351                 if (typeof cls == 'string') {
55352                     cls = cls.replace(me.trimRe, '');
55353                     idx = Ext.Array.indexOf(elClasses, cls);
55354                     if (idx != -1) {
55355                         elClasses.splice(idx, 1);
55356                     }
55357                 }
55358             }
55359             el.set({ 'class': elClasses.join(' ') });
55360         }
55361     },
55362
55363     destroy: function() {
55364         var me = this;
55365         
55366         me.callParent();
55367         if (me.el) {
55368             me.el.remove();
55369         }
55370         delete me.el;
55371     }
55372 });
55373
55374
55375 Ext.define('Ext.draw.engine.Vml', {
55376
55377     
55378
55379     extend: 'Ext.draw.Surface',
55380
55381     requires: ['Ext.draw.Draw', 'Ext.draw.Color', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.core.Element'],
55382
55383     
55384
55385     engine: 'Vml',
55386
55387     map: {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
55388     bitesRe: /([clmz]),?([^clmz]*)/gi,
55389     valRe: /-?[^,\s-]+/g,
55390     fillUrlRe: /^url\(\s*['"]?([^\)]+?)['"]?\s*\)$/i,
55391     pathlike: /^(path|rect)$/,
55392     NonVmlPathRe: /[ahqstv]/ig, // Non-VML Pathing ops
55393     partialPathRe: /[clmz]/g,
55394     fontFamilyRe: /^['"]+|['"]+$/g,
55395     baseVmlCls: Ext.baseCSSPrefix + 'vml-base',
55396     vmlGroupCls: Ext.baseCSSPrefix + 'vml-group',
55397     spriteCls: Ext.baseCSSPrefix + 'vml-sprite',
55398     measureSpanCls: Ext.baseCSSPrefix + 'vml-measure-span',
55399     zoom: 21600,
55400     coordsize: 1000,
55401     coordorigin: '0 0',
55402
55403     // @private
55404     // Convert an SVG standard path into a VML path
55405     path2vml: function (path) {
55406         var me = this,
55407             nonVML =  me.NonVmlPathRe,
55408             map = me.map,
55409             val = me.valRe,
55410             zoom = me.zoom,
55411             bites = me.bitesRe,
55412             command = Ext.Function.bind(Ext.draw.Draw.pathToAbsolute, Ext.draw.Draw),
55413             res, pa, p, r, i, ii, j, jj;
55414         if (String(path).match(nonVML)) {
55415             command = Ext.Function.bind(Ext.draw.Draw.path2curve, Ext.draw.Draw);
55416         } else if (!String(path).match(me.partialPathRe)) {
55417             res = String(path).replace(bites, function (all, command, args) {
55418                 var vals = [],
55419                     isMove = command.toLowerCase() == "m",
55420                     res = map[command];
55421                 args.replace(val, function (value) {
55422                     if (isMove && vals[length] == 2) {
55423                         res += vals + map[command == "m" ? "l" : "L"];
55424                         vals = [];
55425                     }
55426                     vals.push(Math.round(value * zoom));
55427                 });
55428                 return res + vals;
55429             });
55430             return res;
55431         }
55432         pa = command(path);
55433         res = [];
55434         for (i = 0, ii = pa.length; i < ii; i++) {
55435             p = pa[i];
55436             r = pa[i][0].toLowerCase();
55437             if (r == "z") {
55438                 r = "x";
55439             }
55440             for (j = 1, jj = p.length; j < jj; j++) {
55441                 r += Math.round(p[j] * me.zoom) + (j != jj - 1 ? "," : "");
55442             }
55443             res.push(r);
55444         }
55445         return res.join(" ");
55446     },
55447
55448     // @private - set of attributes which need to be translated from the sprite API to the native browser API
55449     translateAttrs: {
55450         radius: "r",
55451         radiusX: "rx",
55452         radiusY: "ry",
55453         lineWidth: "stroke-width",
55454         fillOpacity: "fill-opacity",
55455         strokeOpacity: "stroke-opacity",
55456         strokeLinejoin: "stroke-linejoin"
55457     },
55458
55459     // @private - Minimun set of defaults for different types of sprites.
55460     minDefaults: {
55461         circle: {
55462             fill: "none",
55463             stroke: null,
55464             "stroke-width": null,
55465             opacity: null,
55466             "fill-opacity": null,
55467             "stroke-opacity": null
55468         },
55469         ellipse: {
55470             cx: 0,
55471             cy: 0,
55472             rx: 0,
55473             ry: 0,
55474             fill: "none",
55475             stroke: null,
55476             "stroke-width": null,
55477             opacity: null,
55478             "fill-opacity": null,
55479             "stroke-opacity": null
55480         },
55481         rect: {
55482             x: 0,
55483             y: 0,
55484             width: 0,
55485             height: 0,
55486             rx: 0,
55487             ry: 0,
55488             fill: "none",
55489             stroke: null,
55490             "stroke-width": null,
55491             opacity: null,
55492             "fill-opacity": null,
55493             "stroke-opacity": null
55494         },
55495         text: {
55496             x: 0,
55497             y: 0,
55498             "text-anchor": "start",
55499             font: '10px "Arial"',
55500             fill: "#000",
55501             stroke: null,
55502             "stroke-width": null,
55503             opacity: null,
55504             "fill-opacity": null,
55505             "stroke-opacity": null
55506         },
55507         path: {
55508             d: "M0,0",
55509             fill: "none",
55510             stroke: null,
55511             "stroke-width": null,
55512             opacity: null,
55513             "fill-opacity": null,
55514             "stroke-opacity": null
55515         },
55516         image: {
55517             x: 0,
55518             y: 0,
55519             width: 0,
55520             height: 0,
55521             preserveAspectRatio: "none",
55522             opacity: null
55523         }
55524     },
55525
55526     // private
55527     onMouseEnter: function(e) {
55528         this.fireEvent("mouseenter", e);
55529     },
55530
55531     // private
55532     onMouseLeave: function(e) {
55533         this.fireEvent("mouseleave", e);
55534     },
55535
55536     // @private - Normalize a delegated single event from the main container to each sprite and sprite group
55537     processEvent: function(name, e) {
55538         var target = e.getTarget(),
55539             surface = this.surface,
55540             sprite;
55541         this.fireEvent(name, e);
55542         sprite = this.items.get(target.id);
55543         if (sprite) {
55544             sprite.fireEvent(name, sprite, e);
55545         }
55546     },
55547
55548     // Create the VML element/elements and append them to the DOM
55549     createSpriteElement: function(sprite) {
55550         var me = this,
55551             attr = sprite.attr,
55552             type = sprite.type,
55553             zoom = me.zoom,
55554             vml = sprite.vml || (sprite.vml = {}),
55555             round = Math.round,
55556             el = (type === 'image') ? me.createNode('image') : me.createNode('shape'),
55557             path, skew, textPath;
55558
55559         el.coordsize = zoom + ' ' + zoom;
55560         el.coordorigin = attr.coordorigin || "0 0";
55561         Ext.get(el).addCls(me.spriteCls);
55562         if (type == "text") {
55563             vml.path = path = me.createNode("path");
55564             path.textpathok = true;
55565             vml.textpath = textPath = me.createNode("textpath");
55566             textPath.on = true;
55567             el.appendChild(textPath);
55568             el.appendChild(path);
55569         }
55570         el.id = sprite.id;
55571         sprite.el = Ext.get(el);
55572         me.el.appendChild(el);
55573         if (type !== 'image') {
55574             skew = me.createNode("skew");
55575             skew.on = true;
55576             el.appendChild(skew);
55577             sprite.skew = skew;
55578         }
55579         sprite.matrix = Ext.create('Ext.draw.Matrix');
55580         sprite.bbox = {
55581             plain: null,
55582             transform: null
55583         };
55584         sprite.fireEvent("render", sprite);
55585         return sprite.el;
55586     },
55587
55588     // @private - Get bounding box for the sprite.  The Sprite itself has the public method.
55589     getBBox: function (sprite, isWithoutTransform) {
55590         var realPath = this["getPath" + sprite.type](sprite);
55591         if (isWithoutTransform) {
55592             sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath);
55593             return sprite.bbox.plain;
55594         }
55595         sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
55596         return sprite.bbox.transform;
55597     },
55598
55599     getBBoxText: function (sprite) {
55600         var vml = sprite.vml;
55601         return {
55602             x: vml.X + (vml.bbx || 0) - vml.W / 2,
55603             y: vml.Y - vml.H / 2,
55604             width: vml.W,
55605             height: vml.H
55606         };
55607     },
55608
55609     applyAttrs: function (sprite) {
55610         var me = this,
55611             vml = sprite.vml,
55612             group = sprite.group,
55613             spriteAttr = sprite.attr,
55614             el = sprite.el,
55615             dom = el.dom,
55616             style, name, groups, i, ln, scrubbedAttrs, font, key, bbox;
55617
55618         if (group) {
55619             groups = [].concat(group);
55620             ln = groups.length;
55621             for (i = 0; i < ln; i++) {
55622                 group = groups[i];
55623                 me.getGroup(group).add(sprite);
55624             }
55625             delete sprite.group;
55626         }
55627         scrubbedAttrs = me.scrubAttrs(sprite) || {};
55628
55629         if (sprite.zIndexDirty) {
55630             me.setZIndex(sprite);
55631         }
55632
55633         // Apply minimum default attributes
55634         Ext.applyIf(scrubbedAttrs, me.minDefaults[sprite.type]);
55635
55636         if (sprite.type == 'image') {
55637             Ext.apply(sprite.attr, {
55638                 x: scrubbedAttrs.x,
55639                 y: scrubbedAttrs.y,
55640                 width: scrubbedAttrs.width,
55641                 height: scrubbedAttrs.height
55642             });
55643             bbox = sprite.getBBox();
55644             el.setStyle({
55645                 width: bbox.width + 'px',
55646                 height: bbox.height + 'px'
55647             });
55648             dom.src = scrubbedAttrs.src;
55649         }
55650
55651         if (dom.href) {
55652             dom.href = scrubbedAttrs.href;
55653         }
55654         if (dom.title) {
55655             dom.title = scrubbedAttrs.title;
55656         }
55657         if (dom.target) {
55658             dom.target = scrubbedAttrs.target;
55659         }
55660         if (dom.cursor) {
55661             dom.cursor = scrubbedAttrs.cursor;
55662         }
55663
55664         // Change visibility
55665         if (sprite.dirtyHidden) {
55666             (scrubbedAttrs.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
55667             sprite.dirtyHidden = false;
55668         }
55669
55670         // Update path
55671         if (sprite.dirtyPath) {
55672             if (sprite.type == "circle" || sprite.type == "ellipse") {
55673                 var cx = scrubbedAttrs.x,
55674                     cy = scrubbedAttrs.y,
55675                     rx = scrubbedAttrs.rx || scrubbedAttrs.r || 0,
55676                     ry = scrubbedAttrs.ry || scrubbedAttrs.r || 0;
55677                 dom.path = Ext.String.format("ar{0},{1},{2},{3},{4},{1},{4},{1}",
55678                             Math.round((cx - rx) * me.zoom),
55679                             Math.round((cy - ry) * me.zoom),
55680                             Math.round((cx + rx) * me.zoom),
55681                             Math.round((cy + ry) * me.zoom),
55682                             Math.round(cx * me.zoom));
55683                 sprite.dirtyPath = false;
55684             }
55685             else if (sprite.type !== "text" && sprite.type !== 'image') {
55686                 sprite.attr.path = scrubbedAttrs.path = me.setPaths(sprite, scrubbedAttrs) || scrubbedAttrs.path;
55687                 dom.path = me.path2vml(scrubbedAttrs.path);
55688                 sprite.dirtyPath = false;
55689             }
55690         }
55691
55692         // Apply clipping
55693         if ("clip-rect" in scrubbedAttrs) {
55694             me.setClip(sprite, scrubbedAttrs);
55695         }
55696
55697         // Handle text (special handling required)
55698         if (sprite.type == "text") {
55699             me.setTextAttributes(sprite, scrubbedAttrs);
55700         }
55701
55702         // Handle fill and opacity
55703         if (scrubbedAttrs.opacity  || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) {
55704             me.setFill(sprite, scrubbedAttrs);
55705         }
55706
55707         // Handle stroke (all fills require a stroke element)
55708         if (scrubbedAttrs.stroke || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) {
55709             me.setStroke(sprite, scrubbedAttrs);
55710         }
55711         
55712         //set styles
55713         style = spriteAttr.style;
55714         if (style) {
55715             el.setStyle(style);
55716         }
55717
55718         sprite.dirty = false;
55719     },
55720
55721     setZIndex: function(sprite) {
55722         if (sprite.el) {
55723             if (sprite.attr.zIndex != undefined) {
55724                 sprite.el.setStyle('zIndex', sprite.attr.zIndex);
55725             }
55726             sprite.zIndexDirty = false;
55727         }
55728     },
55729
55730     // Normalize all virtualized types into paths.
55731     setPaths: function(sprite, params) {
55732         var spriteAttr = sprite.attr;
55733         // Clear bbox cache
55734         sprite.bbox.plain = null;
55735         sprite.bbox.transform = null;
55736         if (sprite.type == 'circle') {
55737             spriteAttr.rx = spriteAttr.ry = params.r;
55738             return Ext.draw.Draw.ellipsePath(sprite);
55739         }
55740         else if (sprite.type == 'ellipse') {
55741             spriteAttr.rx = params.rx;
55742             spriteAttr.ry = params.ry;
55743             return Ext.draw.Draw.ellipsePath(sprite);
55744         }
55745         else if (sprite.type == 'rect') {
55746             spriteAttr.rx = spriteAttr.ry = params.r;
55747             return Ext.draw.Draw.rectPath(sprite);
55748         }
55749         else if (sprite.type == 'path' && spriteAttr.path) {
55750             return Ext.draw.Draw.pathToAbsolute(spriteAttr.path);
55751         }
55752         return false;
55753     },
55754
55755     setFill: function(sprite, params) {
55756         var me = this,
55757             el = sprite.el.dom,
55758             fillEl = el.fill,
55759             newfill = false,
55760             opacity, gradient, fillUrl, rotation, angle;
55761
55762         if (!fillEl) {
55763             // NOT an expando (but it sure looks like one)...
55764             fillEl = el.fill = me.createNode("fill");
55765             newfill = true;
55766         }
55767         if (Ext.isArray(params.fill)) {
55768             params.fill = params.fill[0];
55769         }
55770         if (params.fill == "none") {
55771             fillEl.on = false;
55772         }
55773         else {
55774             if (typeof params.opacity == "number") {
55775                 fillEl.opacity = params.opacity;
55776             }
55777             if (typeof params["fill-opacity"] == "number") {
55778                 fillEl.opacity = params["fill-opacity"];
55779             }
55780             fillEl.on = true;
55781             if (typeof params.fill == "string") {
55782                 fillUrl = params.fill.match(me.fillUrlRe);
55783                 if (fillUrl) {
55784                     fillUrl = fillUrl[1];
55785                     // If the URL matches one of the registered gradients, render that gradient
55786                     if (fillUrl.charAt(0) == "#") {
55787                         gradient = me.gradientsColl.getByKey(fillUrl.substring(1));
55788                     }
55789                     if (gradient) {
55790                         // VML angle is offset and inverted from standard, and must be adjusted to match rotation transform
55791                         rotation = params.rotation;
55792                         angle = -(gradient.angle + 270 + (rotation ? rotation.degrees : 0)) % 360;
55793                         // IE will flip the angle at 0 degrees...
55794                         if (angle === 0) {
55795                             angle = 180;
55796                         }
55797                         fillEl.angle = angle;
55798                         fillEl.type = "gradient";
55799                         fillEl.method = "sigma";
55800                         fillEl.colors.value = gradient.colors;
55801                     }
55802                     // Otherwise treat it as an image
55803                     else {
55804                         fillEl.src = fillUrl;
55805                         fillEl.type = "tile";
55806                     }
55807                 }
55808                 else {
55809                     fillEl.color = Ext.draw.Color.toHex(params.fill);
55810                     fillEl.src = "";
55811                     fillEl.type = "solid";
55812                 }
55813             }
55814         }
55815         if (newfill) {
55816             el.appendChild(fillEl);
55817         }
55818     },
55819
55820     setStroke: function(sprite, params) {
55821         var me = this,
55822             el = sprite.el.dom,
55823             strokeEl = sprite.strokeEl,
55824             newStroke = false,
55825             width, opacity;
55826
55827         if (!strokeEl) {
55828             strokeEl = sprite.strokeEl = me.createNode("stroke");
55829             newStroke = true;
55830         }
55831         if (Ext.isArray(params.stroke)) {
55832             params.stroke = params.stroke[0];
55833         }
55834         if (!params.stroke || params.stroke == "none" || params.stroke == 0 || params["stroke-width"] == 0) {
55835             strokeEl.on = false;
55836         }
55837         else {
55838             strokeEl.on = true;
55839             if (params.stroke && !params.stroke.match(me.fillUrlRe)) {
55840                 // VML does NOT support a gradient stroke :(
55841                 strokeEl.color = Ext.draw.Color.toHex(params.stroke);
55842             }
55843             strokeEl.joinstyle = params["stroke-linejoin"];
55844             strokeEl.endcap = params["stroke-linecap"] || "round";
55845             strokeEl.miterlimit = params["stroke-miterlimit"] || 8;
55846             width = parseFloat(params["stroke-width"] || 1) * 0.75;
55847             opacity = params["stroke-opacity"] || 1;
55848             // VML Does not support stroke widths under 1, so we're going to fiddle with stroke-opacity instead.
55849             if (Ext.isNumber(width) && width < 1) {
55850                 strokeEl.weight = 1;
55851                 strokeEl.opacity = opacity * width;
55852             }
55853             else {
55854                 strokeEl.weight = width;
55855                 strokeEl.opacity = opacity;
55856             }
55857         }
55858         if (newStroke) {
55859             el.appendChild(strokeEl);
55860         }
55861     },
55862
55863     setClip: function(sprite, params) {
55864         var me = this,
55865             el = sprite.el,
55866             clipEl = sprite.clipEl,
55867             rect = String(params["clip-rect"]).split(me.separatorRe);
55868         if (!clipEl) {
55869             clipEl = sprite.clipEl = me.el.insertFirst(Ext.getDoc().dom.createElement("div"));
55870             clipEl.addCls(Ext.baseCSSPrefix + 'vml-sprite');
55871         }
55872         if (rect.length == 4) {
55873             rect[2] = +rect[2] + (+rect[0]);
55874             rect[3] = +rect[3] + (+rect[1]);
55875             clipEl.setStyle("clip", Ext.String.format("rect({1}px {2}px {3}px {0}px)", rect[0], rect[1], rect[2], rect[3]));
55876             clipEl.setSize(me.el.width, me.el.height);
55877         }
55878         else {
55879             clipEl.setStyle("clip", "");
55880         }
55881     },
55882
55883     setTextAttributes: function(sprite, params) {
55884         var me = this,
55885             vml = sprite.vml,
55886             textStyle = vml.textpath.style,
55887             spanCacheStyle = me.span.style,
55888             zoom = me.zoom,
55889             round = Math.round,
55890             fontObj = {
55891                 fontSize: "font-size",
55892                 fontWeight: "font-weight",
55893                 fontStyle: "font-style"
55894             },
55895             fontProp,
55896             paramProp;
55897         if (sprite.dirtyFont) {
55898             if (params.font) {
55899                 textStyle.font = spanCacheStyle.font = params.font;
55900             }
55901             if (params["font-family"]) {
55902                 textStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(me.fontFamilyRe, "") + '"';
55903                 spanCacheStyle.fontFamily = params["font-family"];
55904             }
55905
55906             for (fontProp in fontObj) {
55907                 paramProp = params[fontObj[fontProp]];
55908                 if (paramProp) {
55909                     textStyle[fontProp] = spanCacheStyle[fontProp] = paramProp;
55910                 }
55911             }
55912
55913             me.setText(sprite, params.text);
55914             
55915             if (vml.textpath.string) {
55916                 me.span.innerHTML = String(vml.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>");
55917             }
55918             vml.W = me.span.offsetWidth;
55919             vml.H = me.span.offsetHeight + 2; 
55920
55921             
55922             if (params["text-anchor"] == "middle") {
55923                 textStyle["v-text-align"] = "center";
55924             }
55925             else if (params["text-anchor"] == "end") {
55926                 textStyle["v-text-align"] = "right";
55927                 vml.bbx = -Math.round(vml.W / 2);
55928             }
55929             else {
55930                 textStyle["v-text-align"] = "left";
55931                 vml.bbx = Math.round(vml.W / 2);
55932             }
55933         }
55934         vml.X = params.x;
55935         vml.Y = params.y;
55936         vml.path.v = Ext.String.format("m{0},{1}l{2},{1}", Math.round(vml.X * zoom), Math.round(vml.Y * zoom), Math.round(vml.X * zoom) + 1);
55937         
55938         sprite.bbox.plain = null;
55939         sprite.bbox.transform = null;
55940         sprite.dirtyFont = false;
55941     },
55942     
55943     setText: function(sprite, text) {
55944         sprite.vml.textpath.string = Ext.htmlDecode(text);
55945     },
55946
55947     hide: function() {
55948         this.el.hide();
55949     },
55950
55951     show: function() {
55952         this.el.show();
55953     },
55954
55955     hidePrim: function(sprite) {
55956         sprite.el.addCls(Ext.baseCSSPrefix + 'hide-visibility');
55957     },
55958
55959     showPrim: function(sprite) {
55960         sprite.el.removeCls(Ext.baseCSSPrefix + 'hide-visibility');
55961     },
55962
55963     setSize: function(width, height) {
55964         var me = this,
55965             viewBox = me.viewBox,
55966             scaleX, scaleY, items, i, len;
55967         width = width || me.width;
55968         height = height || me.height;
55969         me.width = width;
55970         me.height = height;
55971
55972         if (!me.el) {
55973             return;
55974         }
55975
55976         
55977         if (width != undefined) {
55978             me.el.setWidth(width);
55979         }
55980         if (height != undefined) {
55981             me.el.setHeight(height);
55982         }
55983
55984         
55985         if (viewBox && (width || height)) {
55986             var viewBoxX = viewBox.x,
55987                 viewBoxY = viewBox.y,
55988                 viewBoxWidth = viewBox.width,
55989                 viewBoxHeight = viewBox.height,
55990                 relativeHeight = height / viewBoxHeight,
55991                 relativeWidth = width / viewBoxWidth,
55992                 size;
55993             if (viewBoxWidth * relativeHeight < width) {
55994                 viewBoxX -= (width - viewBoxWidth * relativeHeight) / 2 / relativeHeight;
55995             }
55996             if (viewBoxHeight * relativeWidth < height) {
55997                 viewBoxY -= (height - viewBoxHeight * relativeWidth) / 2 / relativeWidth;
55998             }
55999             size = 1 / Math.max(viewBoxWidth / width, viewBoxHeight / height);
56000             
56001             me.viewBoxShift = {
56002                 dx: -viewBoxX,
56003                 dy: -viewBoxY,
56004                 scale: size
56005             };
56006             items = me.items.items;
56007             for (i = 0, len = items.length; i < len; i++) {
56008                 me.transform(items[i]);
56009             }
56010         }
56011         this.callParent(arguments);
56012     },
56013
56014     setViewBox: function(x, y, width, height) {
56015         this.callParent(arguments);
56016         this.viewBox = {
56017             x: x,
56018             y: y,
56019             width: width,
56020             height: height
56021         };
56022     },
56023
56024     onAdd: function(item) {
56025         this.callParent(arguments);
56026         if (this.el) {
56027             this.renderItem(item);
56028         }
56029     },
56030
56031     onRemove: function(sprite) {
56032         if (sprite.el) {
56033             sprite.el.remove();
56034             delete sprite.el;
56035         }
56036         this.callParent(arguments);
56037     },
56038
56039     render: function (container) {
56040         var me = this,
56041             doc = Ext.getDoc().dom;
56042         
56043         if (!me.createNode) {
56044             try {
56045                 if (!doc.namespaces.rvml) {
56046                     doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
56047                 }
56048                 me.createNode = function (tagName) {
56049                     return doc.createElement("<rvml:" + tagName + ' class="rvml">');
56050                 };
56051             } catch (e) {
56052                 me.createNode = function (tagName) {
56053                     return doc.createElement("<" + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
56054                 };
56055             }
56056         }
56057
56058         if (!me.el) {
56059             var el = doc.createElement("div");
56060             me.el = Ext.get(el);
56061             me.el.addCls(me.baseVmlCls);
56062
56063             
56064             me.span = doc.createElement("span");
56065             Ext.get(me.span).addCls(me.measureSpanCls);
56066             el.appendChild(me.span);
56067             me.el.setSize(me.width || 10, me.height || 10);
56068             container.appendChild(el);
56069             me.el.on({
56070                 scope: me,
56071                 mouseup: me.onMouseUp,
56072                 mousedown: me.onMouseDown,
56073                 mouseover: me.onMouseOver,
56074                 mouseout: me.onMouseOut,
56075                 mousemove: me.onMouseMove,
56076                 mouseenter: me.onMouseEnter,
56077                 mouseleave: me.onMouseLeave,
56078                 click: me.onClick
56079             });
56080         }
56081         me.renderAll();
56082     },
56083
56084     renderAll: function() {
56085         this.items.each(this.renderItem, this);
56086     },
56087
56088     redraw: function(sprite) {
56089         sprite.dirty = true;
56090         this.renderItem(sprite);
56091     },
56092
56093     renderItem: function (sprite) {
56094         
56095         if (!this.el) {
56096             return;
56097         }
56098
56099         
56100         if (!sprite.el) {
56101             this.createSpriteElement(sprite);
56102         }
56103
56104         if (sprite.dirty) {
56105             this.applyAttrs(sprite);
56106             if (sprite.dirtyTransform) {
56107                 this.applyTransformations(sprite);
56108             }
56109         }
56110     },
56111
56112     rotationCompensation: function (deg, dx, dy) {
56113         var matrix = Ext.create('Ext.draw.Matrix');
56114         matrix.rotate(-deg, 0.5, 0.5);
56115         return {
56116             x: matrix.x(dx, dy),
56117             y: matrix.y(dx, dy)
56118         };
56119     },
56120
56121     transform: function(sprite) {
56122         var me = this,
56123             matrix = Ext.create('Ext.draw.Matrix'),
56124             transforms = sprite.transformations,
56125             transformsLength = transforms.length,
56126             i = 0,
56127             deltaDegrees = 0,
56128             deltaScaleX = 1,
56129             deltaScaleY = 1,
56130             flip = "",
56131             el = sprite.el,
56132             dom = el.dom,
56133             domStyle = dom.style,
56134             zoom = me.zoom,
56135             skew = sprite.skew,
56136             deltaX, deltaY, transform, type, compensate, y, fill, newAngle,zoomScaleX, zoomScaleY, newOrigin;
56137
56138         for (; i < transformsLength; i++) {
56139             transform = transforms[i];
56140             type = transform.type;
56141             if (type == "translate") {
56142                 matrix.translate(transform.x, transform.y);
56143             }
56144             else if (type == "rotate") {
56145                 matrix.rotate(transform.degrees, transform.x, transform.y);
56146                 deltaDegrees += transform.degrees;
56147             }
56148             else if (type == "scale") {
56149                 matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY);
56150                 deltaScaleX *= transform.x;
56151                 deltaScaleY *= transform.y;
56152             }
56153         }
56154
56155         if (me.viewBoxShift) {
56156             matrix.scale(me.viewBoxShift.scale, me.viewBoxShift.scale, -1, -1);
56157             matrix.add(1, 0, 0, 1, me.viewBoxShift.dx, me.viewBoxShift.dy);
56158         }
56159
56160         sprite.matrix = matrix;
56161
56162
56163         
56164
56165         if (sprite.type != "image" && skew) {
56166             
56167             skew.matrix = matrix.toString();
56168             skew.offset = matrix.offset();
56169         }
56170         else {
56171             deltaX = matrix.matrix[0][2];
56172             deltaY = matrix.matrix[1][2];
56173             
56174             zoomScaleX = zoom / deltaScaleX;
56175             zoomScaleY = zoom / deltaScaleY;
56176
56177             dom.coordsize = Math.abs(zoomScaleX) + " " + Math.abs(zoomScaleY);
56178
56179             
56180             newAngle = deltaDegrees * (deltaScaleX * ((deltaScaleY < 0) ? -1 : 1));
56181             if (newAngle != domStyle.rotation && !(newAngle === 0 && !domStyle.rotation)) {
56182                 domStyle.rotation = newAngle;
56183             }
56184             if (deltaDegrees) {
56185                 
56186                 compensate = me.rotationCompensation(deltaDegrees, deltaX, deltaY);
56187                 deltaX = compensate.x;
56188                 deltaY = compensate.y;
56189             }
56190
56191             
56192             if (deltaScaleX < 0) {
56193                 flip += "x";
56194             }
56195             if (deltaScaleY < 0) {
56196                 flip += " y";
56197                 y = -1;
56198             }
56199             if (flip != "" && !dom.style.flip) {
56200                 domStyle.flip = flip;
56201             }
56202
56203             
56204             newOrigin = (deltaX * -zoomScaleX) + " " + (deltaY * -zoomScaleY);
56205             if (newOrigin != dom.coordorigin) {
56206                 dom.coordorigin = (deltaX * -zoomScaleX) + " " + (deltaY * -zoomScaleY);
56207             }
56208         }
56209     },
56210
56211     createItem: function (config) {
56212         return Ext.create('Ext.draw.Sprite', config);
56213     },
56214
56215     getRegion: function() {
56216         return this.el.getRegion();
56217     },
56218
56219     addCls: function(sprite, className) {
56220         if (sprite && sprite.el) {
56221             sprite.el.addCls(className);
56222         }
56223     },
56224
56225     removeCls: function(sprite, className) {
56226         if (sprite && sprite.el) {
56227             sprite.el.removeCls(className);
56228         }
56229     },
56230
56231     
56232     addGradient: function(gradient) {
56233         var gradients = this.gradientsColl || (this.gradientsColl = Ext.create('Ext.util.MixedCollection')),
56234             colors = [],
56235             stops = Ext.create('Ext.util.MixedCollection');
56236
56237         
56238         stops.addAll(gradient.stops);
56239         stops.sortByKey("ASC", function(a, b) {
56240             a = parseInt(a, 10);
56241             b = parseInt(b, 10);
56242             return a > b ? 1 : (a < b ? -1 : 0);
56243         });
56244         stops.eachKey(function(k, v) {
56245             colors.push(k + "% " + v.color);
56246         });
56247
56248         gradients.add(gradient.id, {
56249             colors: colors.join(","),
56250             angle: gradient.angle
56251         });
56252     },
56253
56254     destroy: function() {
56255         var me = this;
56256         
56257         me.callParent(arguments);
56258         if (me.el) {
56259             me.el.remove();
56260         }
56261         delete me.el;
56262     }
56263 });
56264
56265
56266 Ext.define('Ext.fx.target.ElementCSS', {
56267
56268     
56269
56270     extend: 'Ext.fx.target.Element',
56271
56272     
56273
56274     setAttr: function(targetData, isFirstFrame) {
56275         var cssArr = {
56276                 attrs: [],
56277                 duration: [],
56278                 easing: []
56279             },
56280             ln = targetData.length,
56281             attributes,
56282             attrs,
56283             attr,
56284             easing,
56285             duration,
56286             o,
56287             i,
56288             j,
56289             ln2;
56290         for (i = 0; i < ln; i++) {
56291             attrs = targetData[i];
56292             duration = attrs.duration;
56293             easing = attrs.easing;
56294             attrs = attrs.attrs;
56295             for (attr in attrs) {
56296                 if (Ext.Array.indexOf(cssArr.attrs, attr) == -1) {
56297                     cssArr.attrs.push(attr.replace(/[A-Z]/g, function(v) {
56298                         return '-' + v.toLowerCase();
56299                     }));
56300                     cssArr.duration.push(duration + 'ms');
56301                     cssArr.easing.push(easing);
56302                 }
56303             }
56304         }
56305         attributes = cssArr.attrs.join(',');
56306         duration = cssArr.duration.join(',');
56307         easing = cssArr.easing.join(', ');
56308         for (i = 0; i < ln; i++) {
56309             attrs = targetData[i].attrs;
56310             for (attr in attrs) {
56311                 ln2 = attrs[attr].length;
56312                 for (j = 0; j < ln2; j++) {
56313                     o = attrs[attr][j];
56314                     o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', isFirstFrame ? '' : attributes);
56315                     o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', isFirstFrame ? '' : duration);
56316                     o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', isFirstFrame ? '' : easing);
56317                     o[0].setStyle(attr, o[1]);
56318
56319                     
56320                     if (isFirstFrame) {
56321                         o = o[0].dom.offsetWidth;
56322                     }
56323                     else {
56324                         
56325                         o[0].on(Ext.supports.CSS3TransitionEnd, function() {
56326                             this.setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', null);
56327                             this.setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', null);
56328                             this.setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', null);
56329                         }, o[0], { single: true });
56330                     }
56331                 }
56332             }
56333         }
56334     }
56335 });
56336
56337 Ext.define('Ext.fx.target.CompositeElementCSS', {
56338
56339     
56340
56341     extend: 'Ext.fx.target.CompositeElement',
56342
56343     requires: ['Ext.fx.target.ElementCSS'],
56344
56345     
56346     setAttr: function() {
56347         return Ext.fx.target.ElementCSS.prototype.setAttr.apply(this, arguments);
56348     }
56349 });
56350
56351 Ext.define('Ext.layout.container.AbstractFit', {
56352
56353     
56354
56355     extend: 'Ext.layout.container.Container',
56356
56357     
56358
56359     itemCls: Ext.baseCSSPrefix + 'fit-item',
56360     targetCls: Ext.baseCSSPrefix + 'layout-fit',
56361     type: 'fit'
56362 });
56363
56364 Ext.define('Ext.layout.container.Fit', {
56365
56366     
56367
56368     extend: 'Ext.layout.container.AbstractFit',
56369     alias: 'layout.fit',
56370     alternateClassName: 'Ext.layout.FitLayout',
56371
56372     
56373    
56374     
56375     onLayout : function() {
56376         var me = this;
56377         me.callParent();
56378
56379         if (me.owner.items.length) {
56380             me.setItemBox(me.owner.items.get(0), me.getLayoutTargetSize());
56381         }
56382     },
56383
56384     getTargetBox : function() {
56385         return this.getLayoutTargetSize();
56386     },
56387
56388     setItemBox : function(item, box) {
56389         var me = this;
56390         if (item && box.height > 0) {
56391             if (me.isManaged('width') === true) {
56392                box.width = undefined;
56393             }
56394             if (me.isManaged('height') === true) {
56395                box.height = undefined;
56396             }
56397             me.setItemSize(item, box.width, box.height);
56398         }
56399     }
56400 });
56401
56402
56403 Ext.define('Ext.layout.container.AbstractCard', {
56404
56405     
56406
56407     extend: 'Ext.layout.container.Fit',
56408
56409     
56410
56411     type: 'card',
56412
56413     sizeAllCards: false,
56414
56415     hideInactive: true,
56416
56417     
56418     deferredRender : false,
56419
56420     beforeLayout: function() {
56421         var me = this;
56422         me.activeItem = me.getActiveItem();
56423         if (me.activeItem && me.deferredRender) {
56424             me.renderItems([me.activeItem], me.getRenderTarget());
56425             return true;
56426         }
56427         else {
56428             return this.callParent(arguments);
56429         }
56430     },
56431
56432     onLayout: function() {
56433         var me = this,
56434             activeItem = me.activeItem,
56435             items = me.getVisibleItems(),
56436             ln = items.length,
56437             targetBox = me.getTargetBox(),
56438             i, item;
56439
56440         for (i = 0; i < ln; i++) {
56441             item = items[i];
56442             me.setItemBox(item, targetBox);
56443         }
56444
56445         if (!me.firstActivated && activeItem) {
56446             if (activeItem.fireEvent('beforeactivate', activeItem) !== false) {
56447                 activeItem.fireEvent('activate', activeItem);
56448             }
56449             me.firstActivated = true;
56450         }
56451     },
56452
56453     isValidParent : function(item, target, position) {
56454         
56455         
56456         var itemEl = item.el ? item.el.dom : Ext.getDom(item);
56457         return (itemEl && itemEl.parentNode === (target.dom || target)) || false;
56458     },
56459
56460     
56461     getActiveItem: function() {
56462         var me = this;
56463         if (!me.activeItem && me.owner) {
56464             me.activeItem = me.parseActiveItem(me.owner.activeItem);
56465         }
56466
56467         if (me.activeItem && me.owner.items.indexOf(me.activeItem) != -1) {
56468             return me.activeItem;
56469         }
56470
56471         return null;
56472     },
56473
56474     
56475     parseActiveItem: function(item) {
56476         if (item && item.isComponent) {
56477             return item;
56478         }
56479         else if (typeof item == 'number' || item === undefined) {
56480             return this.getLayoutItems()[item || 0];
56481         }
56482         else {
56483             return this.owner.getComponent(item);
56484         }
56485     },
56486
56487     
56488     configureItem: function(item, position) {
56489         this.callParent([item, position]);
56490         if (this.hideInactive && this.activeItem !== item) {
56491             item.hide();
56492         }
56493         else {
56494             item.show();
56495         }
56496     },
56497
56498     onRemove: function(component) {
56499         if (component === this.activeItem) {
56500             this.activeItem = null;
56501             if (this.owner.items.getCount() === 0) {
56502                 this.firstActivated = false;
56503             }
56504         }
56505     },
56506
56507     
56508     getAnimation: function(newCard, owner) {
56509         var newAnim = (newCard || {}).cardSwitchAnimation;
56510         if (newAnim === false) {
56511             return false;
56512         }
56513         return newAnim || owner.cardSwitchAnimation;
56514     },
56515
56516     
56517     getNext: function(wrap) {
56518         
56519         
56520         
56521         var items = this.getLayoutItems(),
56522             index = Ext.Array.indexOf(items, this.activeItem);
56523         return items[index + 1] || (wrap ? items[0] : false);
56524     },
56525
56526     
56527     next: function(anim, wrap) {
56528         
56529         
56530         
56531         return this.setActiveItem(this.getNext(wrap), anim);
56532     },
56533
56534     
56535     getPrev: function(wrap) {
56536         
56537         
56538         
56539         var items = this.getLayoutItems(),
56540             index = Ext.Array.indexOf(items, this.activeItem);
56541         return items[index - 1] || (wrap ? items[items.length - 1] : false);
56542     },
56543
56544     
56545     prev: function(anim, wrap) {
56546         
56547         
56548         
56549         return this.setActiveItem(this.getPrev(wrap), anim);
56550     }
56551 });
56552
56553
56554 Ext.define('Ext.selection.Model', {
56555     extend: 'Ext.util.Observable',
56556     alternateClassName: 'Ext.AbstractStoreSelectionModel',
56557     requires: ['Ext.data.StoreManager'],
56558     
56559
56560     
56561     
56562     
56563     allowDeselect: false,
56564
56565     
56566     selected: null,
56567     
56568     
56569     
56570     pruneRemoved: true,
56571
56572     constructor: function(cfg) {
56573         var me = this;
56574         
56575         cfg = cfg || {};
56576         Ext.apply(me, cfg);
56577         
56578         me.addEvents(
56579             
56580              'selectionchange'
56581         );
56582
56583         me.modes = {
56584             SINGLE: true,
56585             SIMPLE: true,
56586             MULTI: true
56587         };
56588
56589         
56590         me.setSelectionMode(cfg.mode || me.mode);
56591
56592         
56593         me.selected = Ext.create('Ext.util.MixedCollection');
56594         
56595         me.callParent(arguments);
56596     },
56597
56598     
56599     bind : function(store, initial){
56600         var me = this;
56601         
56602         if(!initial && me.store){
56603             if(store !== me.store && me.store.autoDestroy){
56604                 me.store.destroy();
56605             }else{
56606                 me.store.un("add", me.onStoreAdd, me);
56607                 me.store.un("clear", me.onStoreClear, me);
56608                 me.store.un("remove", me.onStoreRemove, me);
56609                 me.store.un("update", me.onStoreUpdate, me);
56610             }
56611         }
56612         if(store){
56613             store = Ext.data.StoreManager.lookup(store);
56614             store.on({
56615                 add: me.onStoreAdd,
56616                 clear: me.onStoreClear,
56617                 remove: me.onStoreRemove,
56618                 update: me.onStoreUpdate,
56619                 scope: me
56620             });
56621         }
56622         me.store = store;
56623         if(store && !initial) {
56624             me.refresh();
56625         }
56626     },
56627
56628     selectAll: function(silent) {
56629         var selections = this.store.getRange(),
56630             i = 0,
56631             len = selections.length;
56632             
56633         for (; i < len; i++) {
56634             this.doSelect(selections[i], true, silent);
56635         }
56636     },
56637
56638     deselectAll: function() {
56639         var selections = this.getSelection(),
56640             i = 0,
56641             len = selections.length;
56642             
56643         for (; i < len; i++) {
56644             this.doDeselect(selections[i]);
56645         }
56646     },
56647
56648     
56649     
56650     
56651     selectWithEvent: function(record, e) {
56652         var me = this;
56653         
56654         switch (me.selectionMode) {
56655             case 'MULTI':
56656                 if (e.ctrlKey && me.isSelected(record)) {
56657                     me.doDeselect(record, false);
56658                 } else if (e.shiftKey && me.lastFocused) {
56659                     me.selectRange(me.lastFocused, record, e.ctrlKey);
56660                 } else if (e.ctrlKey) {
56661                     me.doSelect(record, true, false);
56662                 } else if (me.isSelected(record) && !e.shiftKey && !e.ctrlKey && me.selected.getCount() > 1) {
56663                     me.doSelect(record, false, false);
56664                 } else {
56665                     me.doSelect(record, false);
56666                 }
56667                 break;
56668             case 'SIMPLE':
56669                 if (me.isSelected(record)) {
56670                     me.doDeselect(record);
56671                 } else {
56672                     me.doSelect(record, true);
56673                 }
56674                 break;
56675             case 'SINGLE':
56676                 
56677                 if (me.allowDeselect && me.isSelected(record)) {
56678                     me.doDeselect(record);
56679                 
56680                 } else {
56681                     me.doSelect(record, false);
56682                 }
56683                 break;
56684         }
56685     },
56686
56687     
56688     selectRange : function(startRow, endRow, keepExisting, dir){
56689         var me = this,
56690             store = me.store,
56691             selectedCount = 0,
56692             i,
56693             tmp,
56694             dontDeselect,
56695             records = [];
56696         
56697         if (me.isLocked()){
56698             return;
56699         }
56700         
56701         if (!keepExisting) {
56702             me.clearSelections();
56703         }
56704         
56705         if (!Ext.isNumber(startRow)) {
56706             startRow = store.indexOf(startRow);
56707         } 
56708         if (!Ext.isNumber(endRow)) {
56709             endRow = store.indexOf(endRow);
56710         }
56711         
56712         
56713         if (startRow > endRow){
56714             tmp = endRow;
56715             endRow = startRow;
56716             startRow = tmp;
56717         }
56718
56719         for (i = startRow; i <= endRow; i++) {
56720             if (me.isSelected(store.getAt(i))) {
56721                 selectedCount++;
56722             }
56723         }
56724
56725         if (!dir) {
56726             dontDeselect = -1;
56727         } else {
56728             dontDeselect = (dir == 'up') ? startRow : endRow;
56729         }
56730         
56731         for (i = startRow; i <= endRow; i++){
56732             if (selectedCount == (endRow - startRow + 1)) {
56733                 if (i != dontDeselect) {
56734                     me.doDeselect(i, true);
56735                 }
56736             } else {
56737                 records.push(store.getAt(i));
56738             }
56739         }
56740         me.doMultiSelect(records, true);
56741     },
56742     
56743     
56744     select: function(records, keepExisting, suppressEvent) {
56745         this.doSelect(records, keepExisting, suppressEvent);
56746     },
56747
56748     
56749     deselect: function(records, suppressEvent) {
56750         this.doDeselect(records, suppressEvent);
56751     },
56752     
56753     doSelect: function(records, keepExisting, suppressEvent) {
56754         var me = this,
56755             record;
56756             
56757         if (me.locked) {
56758             return;
56759         }
56760         if (typeof records === "number") {
56761             records = [me.store.getAt(records)];
56762         }
56763         if (me.selectionMode == "SINGLE" && records) {
56764             record = records.length ? records[0] : records;
56765             me.doSingleSelect(record, suppressEvent);
56766         } else {
56767             me.doMultiSelect(records, keepExisting, suppressEvent);
56768         }
56769     },
56770
56771     doMultiSelect: function(records, keepExisting, suppressEvent) {
56772         var me = this,
56773             selected = me.selected,
56774             change = false,
56775             i = 0,
56776             len, record;
56777             
56778         if (me.locked) {
56779             return;
56780         }
56781         
56782
56783         records = !Ext.isArray(records) ? [records] : records;
56784         len = records.length;
56785         if (!keepExisting && selected.getCount() > 0) {
56786             change = true;
56787             me.doDeselect(me.getSelection(), true);
56788         }
56789
56790         for (; i < len; i++) {
56791             record = records[i];
56792             if (keepExisting && me.isSelected(record)) {
56793                 continue;
56794             }
56795             change = true;
56796             me.lastSelected = record;
56797             selected.add(record);
56798
56799             me.onSelectChange(record, true, suppressEvent);
56800         }
56801         me.setLastFocused(record, suppressEvent);
56802         
56803         me.maybeFireSelectionChange(change && !suppressEvent);
56804     },
56805
56806     
56807     doDeselect: function(records, suppressEvent) {
56808         var me = this,
56809             selected = me.selected,
56810             change = false,
56811             i = 0,
56812             len, record;
56813             
56814         if (me.locked) {
56815             return;
56816         }
56817
56818         if (typeof records === "number") {
56819             records = [me.store.getAt(records)];
56820         }
56821
56822         records = !Ext.isArray(records) ? [records] : records;
56823         len = records.length;
56824         for (; i < len; i++) {
56825             record = records[i];
56826             if (selected.remove(record)) {
56827                 if (me.lastSelected == record) {
56828                     me.lastSelected = selected.last();
56829                 }
56830                 me.onSelectChange(record, false, suppressEvent);
56831                 change = true;
56832             }
56833         }
56834         
56835         me.maybeFireSelectionChange(change && !suppressEvent);
56836     },
56837
56838     doSingleSelect: function(record, suppressEvent) {
56839         var me = this,
56840             selected = me.selected;
56841             
56842         if (me.locked) {
56843             return;
56844         }
56845         
56846         
56847         if (me.isSelected(record)) {
56848             return;
56849         }
56850         if (selected.getCount() > 0) {
56851             me.doDeselect(me.lastSelected, suppressEvent);
56852         }
56853         selected.add(record);
56854         me.lastSelected = record;
56855         me.onSelectChange(record, true, suppressEvent);
56856         if (!suppressEvent) {
56857             me.setLastFocused(record);
56858         }
56859         me.maybeFireSelectionChange(!suppressEvent);
56860     },
56861
56862     
56863     setLastFocused: function(record, supressFocus) {
56864         var me = this,
56865             recordBeforeLast = me.lastFocused;
56866         me.lastFocused = record;
56867         me.onLastFocusChanged(recordBeforeLast, record, supressFocus);
56868     },
56869     
56870     
56871     isFocused: function(record) {
56872         return record === this.getLastFocused();
56873     },
56874
56875
56876     
56877     
56878     maybeFireSelectionChange: function(fireEvent) {
56879         if (fireEvent) {
56880             var me = this;
56881             me.fireEvent('selectionchange', me, me.getSelection());
56882         }
56883     },
56884
56885     
56886     getLastSelected: function() {
56887         return this.lastSelected;
56888     },
56889     
56890     getLastFocused: function() {
56891         return this.lastFocused;
56892     },
56893
56894     
56895     getSelection: function() {
56896         return this.selected.getRange();
56897     },
56898
56899     
56900     getSelectionMode: function() {
56901         return this.selectionMode;
56902     },
56903
56904     
56905     setSelectionMode: function(selMode) {
56906         selMode = selMode ? selMode.toUpperCase() : 'SINGLE';
56907         
56908         
56909         this.selectionMode = this.modes[selMode] ? selMode : 'SINGLE';
56910     },
56911
56912     
56913     isLocked: function() {
56914         return this.locked;
56915     },
56916
56917     
56918     setLocked: function(locked) {
56919         this.locked = !!locked;
56920     },
56921
56922     
56923     isSelected: function(record) {
56924         record = Ext.isNumber(record) ? this.store.getAt(record) : record;
56925         return this.selected.indexOf(record) !== -1;
56926     },
56927     
56928     
56929     hasSelection: function() {
56930         return this.selected.getCount() > 0;
56931     },
56932
56933     refresh: function() {
56934         var me = this,
56935             toBeSelected = [],
56936             oldSelections = me.getSelection(),
56937             len = oldSelections.length,
56938             selection,
56939             change,
56940             i = 0,
56941             lastFocused = this.getLastFocused();
56942
56943         
56944         
56945         
56946         for (; i < len; i++) {
56947             selection = oldSelections[i];
56948             if (!this.pruneRemoved || me.store.indexOf(selection) !== -1) {
56949                 toBeSelected.push(selection);
56950             }
56951         }
56952
56953         
56954         
56955         if (me.selected.getCount() != toBeSelected.length) {
56956             change = true;
56957         }
56958
56959         me.clearSelections();
56960         
56961         if (me.store.indexOf(lastFocused) !== -1) {
56962             
56963             this.setLastFocused(lastFocused, true);
56964         }
56965
56966         if (toBeSelected.length) {
56967             
56968             me.doSelect(toBeSelected, false, true);
56969         }
56970         
56971         me.maybeFireSelectionChange(change);
56972     },
56973
56974     clearSelections: function() {
56975         
56976         var me = this;
56977         me.selected.clear();
56978         me.lastSelected = null;
56979         me.setLastFocused(null);
56980     },
56981
56982     
56983     onStoreAdd: function() {
56984
56985     },
56986
56987     
56988     
56989     onStoreClear: function() {
56990         var me = this,
56991             selected = this.selected;
56992             
56993         if (selected.getCount > 0) {
56994             selected.clear();
56995             me.lastSelected = null;
56996             me.setLastFocused(null);
56997             me.maybeFireSelectionChange(true);
56998         }
56999     },
57000
57001     
57002     
57003     
57004     onStoreRemove: function(store, record) {
57005         var me = this,
57006             selected = me.selected;
57007             
57008         if (me.locked || !me.pruneRemoved) {
57009             return;
57010         }
57011
57012         if (selected.remove(record)) {
57013             if (me.lastSelected == record) {
57014                 me.lastSelected = null;
57015             }
57016             if (me.getLastFocused() == record) {
57017                 me.setLastFocused(null);
57018             }
57019             me.maybeFireSelectionChange(true);
57020         }
57021     },
57022
57023     getCount: function() {
57024         return this.selected.getCount();
57025     },
57026
57027     
57028     destroy: function() {
57029
57030     },
57031
57032     
57033     onStoreUpdate: function() {
57034
57035     },
57036
57037     
57038     onSelectChange: function(record, isSelected, suppressEvent) {
57039
57040     },
57041
57042     
57043     onLastFocusChanged: function(oldFocused, newFocused) {
57044
57045     },
57046
57047     
57048     onEditorKey: function(field, e) {
57049
57050     },
57051
57052     
57053     bindComponent: function(cmp) {
57054
57055     }
57056 });
57057
57058 Ext.define('Ext.selection.DataViewModel', {
57059     extend: 'Ext.selection.Model',
57060     
57061     requires: ['Ext.util.KeyNav'],
57062
57063     deselectOnContainerClick: true,
57064     
57065     
57066     enableKeyNav: true,
57067     
57068     constructor: function(cfg){
57069         this.addEvents(
57070             
57071             'deselect',
57072             
57073             
57074             'select'
57075         );
57076         this.callParent(arguments);
57077     },
57078     
57079     bindComponent: function(view) {
57080         var me = this,
57081             eventListeners = {
57082                 refresh: me.refresh,
57083                 scope: me
57084             };
57085
57086         me.view = view;
57087         me.bind(view.getStore());
57088
57089         view.on(view.triggerEvent, me.onItemClick, me);
57090         view.on(view.triggerCtEvent, me.onContainerClick, me);
57091
57092         view.on(eventListeners);
57093
57094         if (me.enableKeyNav) {
57095             me.initKeyNav(view);
57096         }
57097     },
57098
57099     onItemClick: function(view, record, item, index, e) {
57100         this.selectWithEvent(record, e);
57101     },
57102
57103     onContainerClick: function() {
57104         if (this.deselectOnContainerClick) {
57105             this.deselectAll();
57106         }
57107     },
57108     
57109     initKeyNav: function(view) {
57110         var me = this;
57111         
57112         if (!view.rendered) {
57113             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
57114             return;
57115         }
57116         
57117         view.el.set({
57118             tabIndex: -1
57119         });
57120         me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
57121             down: Ext.pass(me.onNavKey, [1], me),
57122             right: Ext.pass(me.onNavKey, [1], me),
57123             left: Ext.pass(me.onNavKey, [-1], me),
57124             up: Ext.pass(me.onNavKey, [-1], me),
57125             scope: me
57126         });
57127     },
57128     
57129     onNavKey: function(step) {
57130         step = step || 1;
57131         var me = this,
57132             view = me.view,
57133             selected = me.getSelection()[0],
57134             numRecords = me.view.store.getCount(),
57135             idx;
57136                 
57137         if (selected) {
57138             idx = view.indexOf(view.getNode(selected)) + step;
57139         } else {
57140             idx = 0;
57141         }
57142         
57143         if (idx < 0) {
57144             idx = numRecords - 1;
57145         } else if (idx >= numRecords) {
57146             idx = 0;
57147         }
57148         
57149         me.select(idx);
57150     },
57151
57152     
57153     onSelectChange: function(record, isSelected, suppressEvent) {
57154         var me = this,
57155             view = me.view,
57156             allowSelect = true;
57157         
57158         if (isSelected) {
57159             if (!suppressEvent) {
57160                 allowSelect = me.fireEvent('beforeselect', me, record) !== false;
57161             }
57162             if (allowSelect) {
57163                 view.onItemSelect(record);
57164                 if (!suppressEvent) {
57165                     me.fireEvent('select', me, record);
57166                 }
57167             }
57168         } else {
57169             view.onItemDeselect(record);
57170             if (!suppressEvent) {
57171                 me.fireEvent('deselect', me, record);
57172             }
57173         }
57174     }
57175 });
57176
57177
57178 Ext.define('Ext.state.CookieProvider', {
57179     extend: 'Ext.state.Provider',
57180
57181     constructor : function(config){
57182         var me = this;
57183         me.path = "/";
57184         me.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
57185         me.domain = null;
57186         me.secure = false;
57187         me.callParent(arguments);
57188         me.state = me.readCookies();
57189     },
57190     
57191     
57192     set : function(name, value){
57193         var me = this;
57194         
57195         if(typeof value == "undefined" || value === null){
57196             me.clear(name);
57197             return;
57198         }
57199         me.setCookie(name, value);
57200         me.callParent(arguments);
57201     },
57202
57203     
57204     clear : function(name){
57205         this.clearCookie(name);
57206         this.callParent(arguments);
57207     },
57208
57209     
57210     readCookies : function(){
57211         var cookies = {},
57212             c = document.cookie + ";",
57213             re = /\s?(.*?)=(.*?);/g,
57214             prefix = this.prefix,
57215             len = prefix.length,
57216             matches,
57217             name,
57218             value;
57219             
57220         while((matches = re.exec(c)) != null){
57221             name = matches[1];
57222             value = matches[2];
57223             if (name && name.substring(0, len) == prefix){
57224                 cookies[name.substr(len)] = this.decodeValue(value);
57225             }
57226         }
57227         return cookies;
57228     },
57229
57230     
57231     setCookie : function(name, value){
57232         var me = this;
57233         
57234         document.cookie = me.prefix + name + "=" + me.encodeValue(value) +
57235            ((me.expires == null) ? "" : ("; expires=" + me.expires.toGMTString())) +
57236            ((me.path == null) ? "" : ("; path=" + me.path)) +
57237            ((me.domain == null) ? "" : ("; domain=" + me.domain)) +
57238            ((me.secure == true) ? "; secure" : "");
57239     },
57240
57241     
57242     clearCookie : function(name){
57243         var me = this;
57244         
57245         document.cookie = me.prefix + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
57246            ((me.path == null) ? "" : ("; path=" + me.path)) +
57247            ((me.domain == null) ? "" : ("; domain=" + me.domain)) +
57248            ((me.secure == true) ? "; secure" : "");
57249     }
57250 });
57251
57252 Ext.define('Ext.state.LocalStorageProvider', {
57253     
57254     
57255     extend: 'Ext.state.Provider',
57256     
57257     alias: 'state.localstorage',
57258     
57259     
57260    
57261     constructor: function(){
57262         var me = this;
57263         me.callParent(arguments);
57264         me.store = me.getStorageObject();
57265         me.state = me.readLocalStorage();
57266     },
57267     
57268     readLocalStorage: function(){
57269         var store = this.store,
57270             i = 0,
57271             len = store.length,
57272             prefix = this.prefix,
57273             prefixLen = prefix.length,
57274             data = {},
57275             key;
57276             
57277         for (; i < len; ++i) {
57278             key = store.key(i);
57279             if (key.substring(0, prefixLen) == prefix) {
57280                 data[key.substr(prefixLen)] = this.decodeValue(store.getItem(key));
57281             }            
57282         }
57283         return data;
57284     },
57285     
57286     set : function(name, value){
57287         var me = this;
57288         
57289         me.clear(name);
57290         if (typeof value == "undefined" || value === null) {
57291             return;
57292         }
57293         me.store.setItem(me.prefix + name, me.encodeValue(value));
57294         me.callParent(arguments);
57295     },
57296
57297     
57298     clear : function(name){
57299         this.store.removeItem(this.prefix + name);
57300         this.callParent(arguments);
57301     },
57302     
57303     getStorageObject: function(){
57304         try {
57305             var supports = 'localStorage' in window && window['localStorage'] !== null;
57306             if (supports) {
57307                 return window.localStorage;
57308             }
57309         } catch (e) {
57310             return false;
57311         }
57312         Ext.Error.raise('LocalStorage is not supported by the current browser');
57313     }    
57314 });
57315
57316
57317
57318 Ext.define('Ext.util.Point', {
57319
57320     
57321     extend: 'Ext.util.Region',
57322
57323     statics: {
57324
57325         
57326         fromEvent: function(e) {
57327             e = (e.changedTouches && e.changedTouches.length > 0) ? e.changedTouches[0] : e;
57328             return new this(e.pageX, e.pageY);
57329         }
57330     },
57331
57332     
57333
57334     constructor: function(x, y) {
57335         this.callParent([y, x, y, x]);
57336     },
57337
57338     
57339     toString: function() {
57340         return "Point[" + this.x + "," + this.y + "]";
57341     },
57342
57343     
57344     equals: function(p) {
57345         return (this.x == p.x && this.y == p.y);
57346     },
57347
57348     
57349     isWithin: function(p, threshold) {
57350         if (!Ext.isObject(threshold)) {
57351             threshold = {
57352                 x: threshold,
57353                 y: threshold
57354             };
57355         }
57356
57357         return (this.x <= p.x + threshold.x && this.x >= p.x - threshold.x &&
57358                 this.y <= p.y + threshold.y && this.y >= p.y - threshold.y);
57359     },
57360
57361     
57362     roundedEquals: function(p) {
57363         return (Math.round(this.x) == Math.round(p.x) && Math.round(this.y) == Math.round(p.y));
57364     }
57365 }, function() {
57366     
57367     this.prototype.translate = Ext.util.Region.prototype.translateBy;
57368 });
57369
57370
57371 Ext.define('Ext.view.AbstractView', {
57372     extend: 'Ext.Component',
57373     alternateClassName: 'Ext.view.AbstractView',
57374     requires: [
57375         'Ext.LoadMask',
57376         'Ext.data.StoreManager',
57377         'Ext.CompositeElementLite',
57378         'Ext.DomQuery',
57379         'Ext.selection.DataViewModel'
57380     ],
57381     
57382     inheritableStatics: {
57383         getRecord: function(node) {
57384             return this.getBoundView(node).getRecord(node);
57385         },
57386         
57387         getBoundView: function(node) {
57388             return Ext.getCmp(node.boundView);
57389         }
57390     },
57391     
57392     
57393     
57394
57395     
57396     
57397     
57398     itemCls: Ext.baseCSSPrefix + 'dataview-item',
57399     
57400     
57401
57402     
57403
57404     
57405     loadingText: 'Loading...',
57406     
57407     
57408     
57409     
57410     loadingUseMsg: true,
57411     
57412
57413     
57414
57415     
57416     selectedItemCls: Ext.baseCSSPrefix + 'item-selected',
57417
57418     
57419     emptyText: "",
57420
57421     
57422     deferEmptyText: true,
57423
57424     
57425     trackOver: false,
57426
57427     
57428     blockRefresh: false,
57429
57430     
57431
57432
57433     
57434     last: false,
57435     
57436     triggerEvent: 'itemclick',
57437     triggerCtEvent: 'containerclick',
57438     
57439     addCmpEvents: function() {
57440         
57441     },
57442
57443     
57444     initComponent : function(){
57445         var me = this,
57446             isDef = Ext.isDefined,
57447             itemTpl = me.itemTpl,
57448             memberFn = {};
57449             
57450         if (itemTpl) {
57451             if (Ext.isArray(itemTpl)) {
57452                 
57453                 itemTpl = itemTpl.join('');
57454             } else if (Ext.isObject(itemTpl)) {
57455                 
57456                 memberFn = Ext.apply(memberFn, itemTpl.initialConfig);
57457                 itemTpl = itemTpl.html;
57458             }
57459             
57460             if (!me.itemSelector) {
57461                 me.itemSelector = '.' + me.itemCls;
57462             }
57463             
57464             itemTpl = Ext.String.format('<tpl for="."><div class="{0}">{1}</div></tpl>', me.itemCls, itemTpl);
57465             me.tpl = Ext.create('Ext.XTemplate', itemTpl, memberFn);
57466         }
57467
57468         if (!isDef(me.tpl) || !isDef(me.itemSelector)) {
57469             Ext.Error.raise({
57470                 sourceClass: 'Ext.view.View',
57471                 tpl: me.tpl,
57472                 itemSelector: me.itemSelector,
57473                 msg: "DataView requires both tpl and itemSelector configurations to be defined."
57474             });
57475         }
57476
57477         me.callParent();
57478         if(Ext.isString(me.tpl) || Ext.isArray(me.tpl)){
57479             me.tpl = Ext.create('Ext.XTemplate', me.tpl);
57480         }
57481
57482         
57483         
57484         if (isDef(me.overCls) || isDef(me.overClass)) {
57485             if (Ext.isDefined(Ext.global.console)) {
57486                 Ext.global.console.warn('Ext.view.View: Using the deprecated overCls or overClass configuration. Use overItemCls instead.');
57487             }
57488             me.overItemCls = me.overCls || me.overClass;
57489             delete me.overCls;
57490             delete me.overClass;
57491         }
57492
57493         if (me.overItemCls) {
57494             me.trackOver = true;
57495         }
57496         
57497         if (isDef(me.selectedCls) || isDef(me.selectedClass)) {
57498             if (Ext.isDefined(Ext.global.console)) {
57499                 Ext.global.console.warn('Ext.view.View: Using the deprecated selectedCls or selectedClass configuration. Use selectedItemCls instead.');
57500             }
57501             me.selectedItemCls = me.selectedCls || me.selectedClass;
57502             delete me.selectedCls;
57503             delete me.selectedClass;
57504         }
57505         
57506         me.addEvents(
57507             
57508             'beforerefresh',
57509             
57510             'refresh',
57511             
57512             'itemupdate',
57513             
57514             'itemadd',
57515             
57516             'itemremove'
57517         );
57518
57519         me.addCmpEvents();
57520
57521         if (me.store) {
57522             me.store = Ext.data.StoreManager.lookup(me.store);
57523         }
57524         me.all = new Ext.CompositeElementLite();
57525         me.getSelectionModel().bindComponent(me);
57526     },
57527
57528     onRender: function() {
57529         var me = this,
57530             loadingText = me.loadingText,
57531             loadingHeight = me.loadingHeight,
57532             undef;
57533
57534         me.callParent(arguments);
57535         if (loadingText) {
57536             
57537             
57538             
57539             
57540             
57541             me.loadMask = Ext.create('Ext.LoadMask', me.floating ? me : me.ownerCt || me, {
57542                 msg: loadingText,
57543                 msgCls: me.loadingCls,
57544                 useMsg: me.loadingUseMsg,
57545                 listeners: {
57546                     beforeshow: function() {
57547                         me.getTargetEl().update('');
57548                         me.getSelectionModel().deselectAll();
57549                         me.all.clear();
57550                         if (loadingHeight) {
57551                             me.setCalculatedSize(undef, loadingHeight);
57552                         }
57553                     },
57554                     hide: function() {
57555                         if (loadingHeight) {
57556                             me.setHeight(me.height);
57557                         }
57558                     }
57559                 }
57560             });
57561         }
57562     },
57563
57564     getSelectionModel: function(){
57565         var me = this,
57566             mode = 'SINGLE';
57567
57568         if (!me.selModel) {
57569             me.selModel = {};
57570         }
57571
57572         if (me.simpleSelect) {
57573             mode = 'SIMPLE';
57574         } else if (me.multiSelect) {
57575             mode = 'MULTI';
57576         }
57577
57578         Ext.applyIf(me.selModel, {
57579             allowDeselect: me.allowDeselect,
57580             mode: mode
57581         });
57582
57583         if (!me.selModel.events) {
57584             me.selModel = Ext.create('Ext.selection.DataViewModel', me.selModel);
57585         }
57586
57587         if (!me.selModel.hasRelaySetup) {
57588             me.relayEvents(me.selModel, ['selectionchange', 'beforeselect', 'select', 'deselect']);
57589             me.selModel.hasRelaySetup = true;
57590         }
57591
57592         
57593         
57594         if (me.disableSelection) {
57595             me.selModel.locked = true;
57596         }
57597
57598         return me.selModel;
57599     },
57600
57601     
57602     refresh: function() {
57603         var me = this,
57604             el,
57605             records;
57606             
57607         if (!me.rendered) {
57608             return;
57609         }
57610         
57611         me.fireEvent('beforerefresh', me);
57612         el = me.getTargetEl();
57613         records = me.store.getRange();
57614
57615         el.update('');
57616         if (records.length < 1) {
57617             if (!me.deferEmptyText || me.hasSkippedEmptyText) {
57618                 el.update(me.emptyText);
57619             }
57620             me.all.clear();
57621         } else {
57622             me.tpl.overwrite(el, me.collectData(records, 0));
57623             me.all.fill(Ext.query(me.getItemSelector(), el.dom));
57624             me.updateIndexes(0);
57625         }
57626         
57627         me.selModel.refresh();
57628         me.hasSkippedEmptyText = true;
57629         me.fireEvent('refresh', me);
57630     },
57631
57632     
57633     prepareData: function(data, index, record) {
57634         if (record) {    
57635             Ext.apply(data, record.getAssociatedData());            
57636         }
57637         return data;
57638     },
57639     
57640     
57641     collectData : function(records, startIndex){
57642         var r = [],
57643             i = 0,
57644             len = records.length;
57645
57646         for(; i < len; i++){
57647             r[r.length] = this.prepareData(records[i].data, startIndex + i, records[i]);
57648         }
57649
57650         return r;
57651     },
57652
57653     
57654     bufferRender : function(records, index){
57655         var div = document.createElement('div');
57656         this.tpl.overwrite(div, this.collectData(records, index));
57657         return Ext.query(this.getItemSelector(), div);
57658     },
57659
57660     
57661     onUpdate : function(ds, record){
57662         var me = this,
57663             index = me.store.indexOf(record),
57664             original,
57665             node;
57666
57667         if (index > -1){
57668             original = me.all.elements[index];
57669             node = me.bufferRender([record], index)[0];
57670
57671             me.all.replaceElement(index, node, true);
57672             me.updateIndexes(index, index);
57673
57674             
57675             
57676             me.selModel.refresh();
57677             me.fireEvent('itemupdate', record, index, node);
57678         }
57679
57680     },
57681
57682     
57683     onAdd : function(ds, records, index) {
57684         var me = this,
57685             nodes;
57686             
57687         if (me.all.getCount() === 0) {
57688             me.refresh();
57689             return;
57690         }
57691         
57692         nodes = me.bufferRender(records, index);
57693         me.doAdd(nodes, records, index);
57694
57695         me.selModel.refresh();
57696         me.updateIndexes(index);
57697         me.fireEvent('itemadd', records, index, nodes);
57698     },
57699
57700     doAdd: function(nodes, records, index) {
57701         var n, a = this.all.elements;
57702         if (index < this.all.getCount()) {
57703             n = this.all.item(index).insertSibling(nodes, 'before', true);
57704             a.splice.apply(a, [index, 0].concat(nodes));
57705         } 
57706         else {
57707             n = this.all.last().insertSibling(nodes, 'after', true);
57708             a.push.apply(a, nodes);
57709         }    
57710     },
57711     
57712     
57713     onRemove : function(ds, record, index) {
57714         var me = this;
57715         
57716         me.doRemove(record, index);
57717         me.updateIndexes(index);
57718         if (me.store.getCount() === 0){
57719             me.refresh();
57720         }
57721         me.fireEvent('itemremove', record, index);
57722     },
57723     
57724     doRemove: function(record, index) {
57725         this.all.removeElement(index, true);
57726     },
57727
57728     
57729     refreshNode : function(index){
57730         this.onUpdate(this.store, this.store.getAt(index));
57731     },
57732
57733     
57734     updateIndexes : function(startIndex, endIndex) {
57735         var ns = this.all.elements,
57736             records = this.store.getRange();
57737         startIndex = startIndex || 0;
57738         endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
57739         for(var i = startIndex; i <= endIndex; i++){
57740             ns[i].viewIndex = i;
57741             ns[i].viewRecordId = records[i].internalId;
57742             if (!ns[i].boundView) {
57743                 ns[i].boundView = this.id;
57744             }
57745         }
57746     },
57747
57748     
57749     getStore : function(){
57750         return this.store;
57751     },
57752
57753     
57754     bindStore : function(store, initial) {
57755         var me = this;
57756         
57757         if (!initial && me.store) {
57758             if (store !== me.store && me.store.autoDestroy) {
57759                 me.store.destroy();
57760             } 
57761             else {
57762                 me.mun(me.store, {
57763                     scope: me,
57764                     datachanged: me.onDataChanged,
57765                     add: me.onAdd,
57766                     remove: me.onRemove,
57767                     update: me.onUpdate,
57768                     clear: me.refresh
57769                 });
57770             }
57771             if (!store) {
57772                 if (me.loadMask) {
57773                     me.loadMask.bindStore(null);
57774                 }
57775                 me.store = null;
57776             }
57777         }
57778         if (store) {
57779             store = Ext.data.StoreManager.lookup(store);
57780             me.mon(store, {
57781                 scope: me,
57782                 datachanged: me.onDataChanged,
57783                 add: me.onAdd,
57784                 remove: me.onRemove,
57785                 update: me.onUpdate,
57786                 clear: me.refresh
57787             });
57788             if (me.loadMask) {
57789                 me.loadMask.bindStore(store);
57790             }
57791         }
57792         
57793         me.store = store;
57794         
57795         me.getSelectionModel().bind(store);
57796         
57797         if (store) {
57798             me.refresh(true);
57799         }
57800     },
57801
57802     
57803     onDataChanged: function() {
57804         if (this.blockRefresh !== true) {
57805             this.refresh.apply(this, arguments);
57806         }
57807     },
57808
57809     
57810     findItemByChild: function(node){
57811         return Ext.fly(node).findParent(this.getItemSelector(), this.getTargetEl());
57812     },
57813     
57814     
57815     findTargetByEvent: function(e) {
57816         return e.getTarget(this.getItemSelector(), this.getTargetEl());
57817     },
57818
57819
57820     
57821     getSelectedNodes: function(){
57822         var nodes   = [],
57823             records = this.selModel.getSelection(),
57824             ln = records.length,
57825             i  = 0;
57826
57827         for (; i < ln; i++) {
57828             nodes.push(this.getNode(records[i]));
57829         }
57830
57831         return nodes;
57832     },
57833
57834     
57835     getRecords: function(nodes) {
57836         var records = [],
57837             i = 0,
57838             len = nodes.length,
57839             data = this.store.data;
57840
57841         for (; i < len; i++) {
57842             records[records.length] = data.getByKey(nodes[i].viewRecordId);
57843         }
57844
57845         return records;
57846     },
57847
57848     
57849     getRecord: function(node){
57850         return this.store.data.getByKey(Ext.getDom(node).viewRecordId);
57851     },
57852     
57853
57854     
57855     isSelected : function(node) {
57856         
57857         var r = this.getRecord(node);
57858         return this.selModel.isSelected(r);
57859     },
57860     
57861     
57862     select: function(records, keepExisting, suppressEvent) {
57863         this.selModel.select(records, keepExisting, suppressEvent);
57864     },
57865
57866     
57867     deselect: function(records, suppressEvent) {
57868         this.selModel.deselect(records, suppressEvent);
57869     },
57870
57871     
57872     getNode : function(nodeInfo) {
57873         if (Ext.isString(nodeInfo)) {
57874             return document.getElementById(nodeInfo);
57875         } else if (Ext.isNumber(nodeInfo)) {
57876             return this.all.elements[nodeInfo];
57877         } else if (nodeInfo instanceof Ext.data.Model) {
57878             return this.getNodeByRecord(nodeInfo);
57879         }
57880         return nodeInfo;
57881     },
57882     
57883     
57884     getNodeByRecord: function(record) {
57885         var ns = this.all.elements,
57886             ln = ns.length,
57887             i = 0;
57888         
57889         for (; i < ln; i++) {
57890             if (ns[i].viewRecordId === record.internalId) {
57891                 return ns[i];
57892             }
57893         }
57894         
57895         return null;
57896     },
57897     
57898     
57899     getNodes: function(start, end) {
57900         var ns = this.all.elements,
57901             nodes = [],
57902             i;
57903
57904         start = start || 0;
57905         end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
57906         if (start <= end) {
57907             for (i = start; i <= end && ns[i]; i++) {
57908                 nodes.push(ns[i]);
57909             }
57910         } else {
57911             for (i = start; i >= end && ns[i]; i--) {
57912                 nodes.push(ns[i]);
57913             }
57914         }
57915         return nodes;
57916     },
57917
57918     
57919     indexOf: function(node) {
57920         node = this.getNode(node);
57921         if (Ext.isNumber(node.viewIndex)) {
57922             return node.viewIndex;
57923         }
57924         return this.all.indexOf(node);
57925     },
57926
57927     onDestroy : function() {
57928         var me = this;
57929         
57930         me.all.clear();
57931         me.callParent();
57932         me.bindStore(null);
57933         me.selModel.destroy();
57934     },
57935
57936     
57937     onItemSelect: function(record) {
57938         var node = this.getNode(record);
57939         Ext.fly(node).addCls(this.selectedItemCls);
57940     },
57941
57942     
57943     onItemDeselect: function(record) {
57944         var node = this.getNode(record);
57945         Ext.fly(node).removeCls(this.selectedItemCls);
57946     },
57947     
57948     getItemSelector: function() {
57949         return this.itemSelector;
57950     }
57951 }, function() {
57952     
57953     
57954     
57955     
57956     Ext.deprecate('extjs', '4.0', function() {
57957         Ext.view.AbstractView.override({
57958             
57959             
57960             
57961             
57962             
57963             getSelectionCount : function(){
57964                 console.warn("DataView: getSelectionCount will be removed, please interact with the Ext.selection.DataViewModel");
57965                 return this.selModel.getSelection().length;
57966             },
57967         
57968             
57969             getSelectedRecords : function(){
57970                 console.warn("DataView: getSelectedRecords will be removed, please interact with the Ext.selection.DataViewModel");
57971                 return this.selModel.getSelection();
57972             },
57973     
57974             select: function(records, keepExisting, supressEvents) {
57975                 console.warn("DataView: select will be removed, please access select through a DataView's SelectionModel, ie: view.getSelectionModel().select()");
57976                 var sm = this.getSelectionModel();
57977                 return sm.select.apply(sm, arguments);
57978             },
57979             
57980             clearSelections: function() {
57981                 console.warn("DataView: clearSelections will be removed, please access deselectAll through DataView's SelectionModel, ie: view.getSelectionModel().deselectAll()");
57982                 var sm = this.getSelectionModel();
57983                 return sm.deselectAll();
57984             }
57985         });    
57986     });
57987 });
57988
57989
57990 Ext.define('Ext.Action', {
57991
57992     
57993
57994     
57995
57996     
57997     
57998     
57999     
58000     
58001     
58002     
58003
58004     constructor : function(config){
58005         this.initialConfig = config;
58006         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
58007         this.items = [];
58008     },
58009
58010     
58011     isAction : true,
58012
58013     
58014     setText : function(text){
58015         this.initialConfig.text = text;
58016         this.callEach('setText', [text]);
58017     },
58018
58019     
58020     getText : function(){
58021         return this.initialConfig.text;
58022     },
58023
58024     
58025     setIconCls : function(cls){
58026         this.initialConfig.iconCls = cls;
58027         this.callEach('setIconCls', [cls]);
58028     },
58029
58030     
58031     getIconCls : function(){
58032         return this.initialConfig.iconCls;
58033     },
58034
58035     
58036     setDisabled : function(v){
58037         this.initialConfig.disabled = v;
58038         this.callEach('setDisabled', [v]);
58039     },
58040
58041     
58042     enable : function(){
58043         this.setDisabled(false);
58044     },
58045
58046     
58047     disable : function(){
58048         this.setDisabled(true);
58049     },
58050
58051     
58052     isDisabled : function(){
58053         return this.initialConfig.disabled;
58054     },
58055
58056     
58057     setHidden : function(v){
58058         this.initialConfig.hidden = v;
58059         this.callEach('setVisible', [!v]);
58060     },
58061
58062     
58063     show : function(){
58064         this.setHidden(false);
58065     },
58066
58067     
58068     hide : function(){
58069         this.setHidden(true);
58070     },
58071
58072     
58073     isHidden : function(){
58074         return this.initialConfig.hidden;
58075     },
58076
58077     
58078     setHandler : function(fn, scope){
58079         this.initialConfig.handler = fn;
58080         this.initialConfig.scope = scope;
58081         this.callEach('setHandler', [fn, scope]);
58082     },
58083
58084     
58085     each : function(fn, scope){
58086         Ext.each(this.items, fn, scope);
58087     },
58088
58089     
58090     callEach : function(fnName, args){
58091         var cs = this.items;
58092         for(var i = 0, len = cs.length; i < len; i++){
58093             cs[i][fnName].apply(cs[i], args);
58094         }
58095     },
58096
58097     
58098     addComponent : function(comp){
58099         this.items.push(comp);
58100         comp.on('destroy', this.removeComponent, this);
58101     },
58102
58103     
58104     removeComponent : function(comp){
58105         this.items.remove(comp);
58106     },
58107
58108     
58109     execute : function(){
58110         this.initialConfig.handler.apply(this.initialConfig.scope || Ext.global, arguments);
58111     }
58112 });
58113
58114
58115 Ext.define('Ext.layout.component.Editor', {
58116
58117     
58118
58119     alias: ['layout.editor'],
58120
58121     extend: 'Ext.layout.component.Component',
58122
58123     
58124
58125     onLayout: function(width, height) {
58126         var me = this,
58127             owner = me.owner,
58128             autoSize = owner.autoSize;
58129             
58130         if (autoSize === true) {
58131             autoSize = {
58132                 width: 'field',
58133                 height: 'field'    
58134             };
58135         }
58136         
58137         if (autoSize) {
58138             width = me.getDimension(owner, autoSize.width, 'Width', width);
58139             height = me.getDimension(owner, autoSize.height, 'Height', height);
58140         }
58141         me.setTargetSize(width, height);
58142         owner.field.setSize(width, height);
58143     },
58144     
58145     getDimension: function(owner, type, dimension, actual){
58146         var method = 'get' + dimension;
58147         switch (type) {
58148             case 'boundEl':
58149                 return owner.boundEl[method]();
58150             case 'field':
58151                 return owner.field[method]();
58152             default:
58153                 return actual;
58154         }
58155     }
58156 });
58157
58158 Ext.define('Ext.Editor', {
58159
58160     
58161
58162     extend: 'Ext.Component',
58163
58164     alias: 'widget.editor',
58165
58166     requires: ['Ext.layout.component.Editor'],
58167
58168     
58169
58170    componentLayout: 'editor',
58171
58172     
58173
58174     
58175     allowBlur: true,
58176
58177     
58178
58179     
58180     revertInvalid: true,
58181
58182     
58183
58184     
58185
58186     
58187     value : '',
58188
58189     
58190     alignment: 'c-c?',
58191
58192     
58193     offsets: [0, 0],
58194
58195     
58196     shadow : 'frame',
58197
58198     
58199     constrain : false,
58200
58201     
58202     swallowKeys : true,
58203
58204     
58205     completeOnEnter : true,
58206
58207     
58208     cancelOnEsc : true,
58209
58210     
58211     updateEl : false,
58212
58213     
58214
58215     
58216     hidden: true,
58217     baseCls: Ext.baseCSSPrefix + 'editor',
58218
58219     initComponent : function() {
58220         var me = this,
58221             field = me.field = Ext.ComponentManager.create(me.field, 'textfield');
58222
58223         Ext.apply(field, {
58224             inEditor: true,
58225             msgTarget: field.msgTarget == 'title' ? 'title' :  'qtip'
58226         });
58227         me.mon(field, {
58228             scope: me,
58229             blur: {
58230                 fn: me.onBlur,
58231                 
58232                 delay: 1
58233             },
58234             specialkey: me.onSpecialKey
58235         });
58236
58237         if (field.grow) {
58238             me.mon(field, 'autosize', me.onAutoSize,  me, {delay: 1});
58239         }
58240         me.floating = {
58241             constrain: me.constrain
58242         };
58243
58244         me.callParent(arguments);
58245
58246         me.addEvents(
58247             
58248             'beforestartedit',
58249             
58250             'startedit',
58251             
58252             'beforecomplete',
58253             
58254             'complete',
58255             
58256             'canceledit',
58257             
58258             'specialkey'
58259         );
58260     },
58261
58262     
58263     onAutoSize: function(){
58264         this.doComponentLayout();
58265     },
58266
58267     
58268     onRender : function(ct, position) {
58269         var me = this,
58270             field = me.field;
58271
58272         me.callParent(arguments);
58273
58274         field.render(me.el);
58275         
58276         
58277         field.inputEl.dom.name = '';
58278         if (me.swallowKeys) {
58279             field.inputEl.swallowEvent([
58280                 'keypress', 
58281                 'keydown'   
58282             ]);
58283         }
58284     },
58285
58286     
58287     onSpecialKey : function(field, event) {
58288         var me = this,
58289             key = event.getKey(),
58290             complete = me.completeOnEnter && key == event.ENTER,
58291             cancel = me.cancelOnEsc && key == event.ESC;
58292
58293         if (complete || cancel) {
58294             event.stopEvent();
58295             
58296             
58297             Ext.defer(function() {
58298                 if (complete) {
58299                     me.completeEdit();
58300                 } else {
58301                     me.cancelEdit();
58302                 }
58303                 if (field.triggerBlur) {
58304                     field.triggerBlur();
58305                 }
58306             }, 10);
58307         }
58308
58309         this.fireEvent('specialkey', this, field, event);
58310     },
58311
58312     
58313     startEdit : function(el, value) {
58314         var me = this,
58315             field = me.field;
58316
58317         me.completeEdit();
58318         me.boundEl = Ext.get(el);
58319         value = Ext.isDefined(value) ? value : me.boundEl.dom.innerHTML;
58320
58321         if (!me.rendered) {
58322             me.render(me.parentEl || document.body);
58323         }
58324
58325         if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) {
58326             me.startValue = value;
58327             me.show();
58328             field.reset();
58329             field.setValue(value);
58330             me.realign(true);
58331             field.focus(false, 10);
58332             if (field.autoSize) {
58333                 field.autoSize();
58334             }
58335             me.editing = true;
58336         }
58337     },
58338
58339     
58340     realign : function(autoSize) {
58341         var me = this;
58342         if (autoSize === true) {
58343             me.doComponentLayout();
58344         }
58345         me.alignTo(me.boundEl, me.alignment, me.offsets);
58346     },
58347
58348     
58349     completeEdit : function(remainVisible) {
58350         var me = this,
58351             field = me.field,
58352             value;
58353
58354         if (!me.editing) {
58355             return;
58356         }
58357
58358         
58359         if (field.assertValue) {
58360             field.assertValue();
58361         }
58362
58363         value = me.getValue();
58364         if (!field.isValid()) {
58365             if (me.revertInvalid !== false) {
58366                 me.cancelEdit(remainVisible);
58367             }
58368             return;
58369         }
58370
58371         if (String(value) === String(me.startValue) && me.ignoreNoChange) {
58372             me.hideEdit(remainVisible);
58373             return;
58374         }
58375
58376         if (me.fireEvent('beforecomplete', me, value, me.startValue) !== false) {
58377             
58378             value = me.getValue();
58379             if (me.updateEl && me.boundEl) {
58380                 me.boundEl.update(value);
58381             }
58382             me.hideEdit(remainVisible);
58383             me.fireEvent('complete', me, value, me.startValue);
58384         }
58385     },
58386
58387     
58388     onShow : function() {
58389         var me = this;
58390
58391         me.callParent(arguments);
58392         if (me.hideEl !== false) {
58393             me.boundEl.hide();
58394         }
58395         me.fireEvent("startedit", me.boundEl, me.startValue);
58396     },
58397
58398     
58399     cancelEdit : function(remainVisible) {
58400         var me = this,
58401             startValue = me.startValue,
58402             value;
58403
58404         if (me.editing) {
58405             value = me.getValue();
58406             me.setValue(startValue);
58407             me.hideEdit(remainVisible);
58408             me.fireEvent('canceledit', me, value, startValue);
58409         }
58410     },
58411
58412     
58413     hideEdit: function(remainVisible) {
58414         if (remainVisible !== true) {
58415             this.editing = false;
58416             this.hide();
58417         }
58418     },
58419
58420     
58421     onBlur : function() {
58422         var me = this;
58423
58424         
58425         if(me.allowBlur === true && me.editing && me.selectSameEditor !== true) {
58426             me.completeEdit();
58427         }
58428     },
58429
58430     
58431     onHide : function() {
58432         var me = this,
58433             field = me.field;
58434
58435         if (me.editing) {
58436             me.completeEdit();
58437             return;
58438         }
58439         field.blur();
58440         if (field.collapse) {
58441             field.collapse();
58442         }
58443
58444         
58445         if (me.hideEl !== false) {
58446             me.boundEl.show();
58447         }
58448         me.callParent(arguments);
58449     },
58450
58451     
58452     setValue : function(value) {
58453         this.field.setValue(value);
58454     },
58455
58456     
58457     getValue : function() {
58458         return this.field.getValue();
58459     },
58460
58461     beforeDestroy : function() {
58462         var me = this;
58463
58464         Ext.destroy(me.field);
58465         delete me.field;
58466         delete me.parentEl;
58467         delete me.boundEl;
58468
58469         me.callParent(arguments);
58470     }
58471 });
58472
58473 Ext.define('Ext.Img', {
58474     extend: 'Ext.Component',
58475     alias: ['widget.image', 'widget.imagecomponent'],
58476     
58477     src: '',
58478
58479     getElConfig: function() {
58480         return {
58481             tag: 'img',
58482             src: this.src
58483         };
58484     },
58485     
58486     
58487     setSrc: function(src) {
58488         var me = this,
58489             img = me.el;
58490         me.src = src;
58491         if (img) {
58492             img.dom.src = src;
58493         }
58494     }
58495 });
58496
58497
58498 Ext.define('Ext.Layer', {
58499     uses: ['Ext.Shadow'],
58500
58501     
58502     statics: {
58503         shims: []
58504     },
58505
58506     extend: 'Ext.core.Element',
58507
58508     constructor: function(config, existingEl) {
58509         config = config || {};
58510         var me = this,
58511             dh = Ext.core.DomHelper,
58512             cp = config.parentEl,
58513             pel = cp ? Ext.getDom(cp) : document.body,
58514         hm = config.hideMode;
58515
58516         if (existingEl) {
58517             me.dom = Ext.getDom(existingEl);
58518         }
58519         if (!me.dom) {
58520             me.dom = dh.append(pel, config.dh || {
58521                 tag: 'div',
58522                 cls: Ext.baseCSSPrefix + 'layer'
58523             });
58524         } else {
58525             me.addCls(Ext.baseCSSPrefix + 'layer');
58526             if (!me.dom.parentNode) {
58527                 pel.appendChild(me.dom);
58528             }
58529         }
58530
58531         if (config.cls) {
58532             me.addCls(config.cls);
58533         }
58534         me.constrain = config.constrain !== false;
58535
58536         
58537         
58538         
58539         if (hm) {
58540             me.setVisibilityMode(Ext.core.Element[hm.toUpperCase()]);
58541             if (me.visibilityMode == Ext.core.Element.ASCLASS) {
58542                 me.visibilityCls = config.visibilityCls;
58543             }
58544         } else if (config.useDisplay) {
58545             me.setVisibilityMode(Ext.core.Element.DISPLAY);
58546         } else {
58547             me.setVisibilityMode(Ext.core.Element.VISIBILITY);
58548         }
58549
58550         if (config.id) {
58551             me.id = me.dom.id = config.id;
58552         } else {
58553             me.id = Ext.id(me.dom);
58554         }
58555         me.position('absolute');
58556         if (config.shadow) {
58557             me.shadowOffset = config.shadowOffset || 4;
58558             me.shadow = Ext.create('Ext.Shadow', {
58559                 offset: me.shadowOffset,
58560                 mode: config.shadow
58561             });
58562             me.disableShadow();
58563         } else {
58564             me.shadowOffset = 0;
58565         }
58566         me.useShim = config.shim !== false && Ext.useShims;
58567         if (config.hidden === true) {
58568             me.hide();
58569         } else {
58570             this.show();
58571         }
58572     },
58573
58574     getZIndex: function() {
58575         return parseInt((this.getShim() || this).getStyle('z-index'), 10);
58576     },
58577
58578     getShim: function() {
58579         var me = this,
58580             shim, pn;
58581
58582         if (!me.useShim) {
58583             return null;
58584         }
58585         if (!me.shim) {
58586             shim = me.self.shims.shift();
58587             if (!shim) {
58588                 shim = me.createShim();
58589                 shim.enableDisplayMode('block');
58590                 shim.hide();
58591             }
58592             pn = me.dom.parentNode;
58593             if (shim.dom.parentNode != pn) {
58594                 pn.insertBefore(shim.dom, me.dom);
58595             }
58596             me.shim = shim;
58597         }
58598         return me.shim;
58599     },
58600
58601     hideShim: function() {
58602         if (this.shim) {
58603             this.shim.setDisplayed(false);
58604             this.self.shims.push(this.shim);
58605             delete this.shim;
58606         }
58607     },
58608
58609     disableShadow: function() {
58610         if (this.shadow) {
58611             this.shadowDisabled = true;
58612             this.shadow.hide();
58613             this.lastShadowOffset = this.shadowOffset;
58614             this.shadowOffset = 0;
58615         }
58616     },
58617
58618     enableShadow: function(show) {
58619         if (this.shadow) {
58620             this.shadowDisabled = false;
58621             this.shadowOffset = this.lastShadowOffset;
58622             delete this.lastShadowOffset;
58623             if (show) {
58624                 this.sync(true);
58625             }
58626         }
58627     },
58628
58629     
58630     sync: function(doShow) {
58631         var me = this,
58632             shadow = me.shadow,
58633             shadowPos, shimStyle, shadowSize;
58634
58635         if (!this.updating && this.isVisible() && (shadow || this.useShim)) {
58636             var shim = this.getShim(),
58637                 l = this.getLeft(true),
58638                 t = this.getTop(true),
58639                 w = this.getWidth(),
58640                 h = this.getHeight(),
58641                 shimIndex;
58642
58643             if (shadow && !this.shadowDisabled) {
58644                 if (doShow && !shadow.isVisible()) {
58645                     shadow.show(this);
58646                 } else {
58647                     shadow.realign(l, t, w, h);
58648                 }
58649                 if (shim) {
58650                     
58651                     shimIndex = shim.getStyle('z-index');
58652                     if (shimIndex > me.zindex) {
58653                         me.shim.setStyle('z-index', me.zindex - 2);
58654                     }
58655                     shim.show();
58656                     
58657                     if (shadow.isVisible()) {
58658                         shadowPos = shadow.el.getXY();
58659                         shimStyle = shim.dom.style;
58660                         shadowSize = shadow.el.getSize();
58661                         shimStyle.left = (shadowPos[0]) + 'px';
58662                         shimStyle.top = (shadowPos[1]) + 'px';
58663                         shimStyle.width = (shadowSize.width) + 'px';
58664                         shimStyle.height = (shadowSize.height) + 'px';
58665                     } else {
58666                         shim.setSize(w, h);
58667                         shim.setLeftTop(l, t);
58668                     }
58669                 }
58670             } else if (shim) {
58671                 
58672                 shimIndex = shim.getStyle('z-index');
58673                 if (shimIndex > me.zindex) {
58674                     me.shim.setStyle('z-index', me.zindex - 2);
58675                 }
58676                 shim.show();
58677                 shim.setSize(w, h);
58678                 shim.setLeftTop(l, t);
58679             }
58680         }
58681         return this;
58682     },
58683
58684     remove: function() {
58685         this.hideUnders();
58686         this.callParent();
58687     },
58688
58689     
58690     beginUpdate: function() {
58691         this.updating = true;
58692     },
58693
58694     
58695     endUpdate: function() {
58696         this.updating = false;
58697         this.sync(true);
58698     },
58699
58700     
58701     hideUnders: function() {
58702         if (this.shadow) {
58703             this.shadow.hide();
58704         }
58705         this.hideShim();
58706     },
58707
58708     
58709     constrainXY: function() {
58710         if (this.constrain) {
58711             var vw = Ext.core.Element.getViewWidth(),
58712                 vh = Ext.core.Element.getViewHeight(),
58713                 s = Ext.getDoc().getScroll(),
58714                 xy = this.getXY(),
58715                 x = xy[0],
58716                 y = xy[1],
58717                 so = this.shadowOffset,
58718                 w = this.dom.offsetWidth + so,
58719                 h = this.dom.offsetHeight + so,
58720                 moved = false; 
58721             
58722             if ((x + w) > vw + s.left) {
58723                 x = vw - w - so;
58724                 moved = true;
58725             }
58726             if ((y + h) > vh + s.top) {
58727                 y = vh - h - so;
58728                 moved = true;
58729             }
58730             
58731             if (x < s.left) {
58732                 x = s.left;
58733                 moved = true;
58734             }
58735             if (y < s.top) {
58736                 y = s.top;
58737                 moved = true;
58738             }
58739             if (moved) {
58740                 Ext.Layer.superclass.setXY.call(this, [x, y]);
58741                 this.sync();
58742             }
58743         }
58744         return this;
58745     },
58746
58747     getConstrainOffset: function() {
58748         return this.shadowOffset;
58749     },
58750
58751     
58752     setVisible: function(visible, animate, duration, callback, easing) {
58753         var me = this,
58754             cb;
58755
58756         
58757         cb = function() {
58758             if (visible) {
58759                 me.sync(true);
58760             }
58761             if (callback) {
58762                 callback();
58763             }
58764         };
58765
58766         
58767         if (!visible) {
58768             this.hideUnders(true);
58769         }
58770         this.callParent([visible, animate, duration, callback, easing]);
58771         if (!animate) {
58772             cb();
58773         }
58774         return this;
58775     },
58776
58777     
58778     beforeFx: function() {
58779         this.beforeAction();
58780         return this.callParent(arguments);
58781     },
58782
58783     
58784     afterFx: function() {
58785         this.callParent(arguments);
58786         this.sync(this.isVisible());
58787     },
58788
58789     
58790     beforeAction: function() {
58791         if (!this.updating && this.shadow) {
58792             this.shadow.hide();
58793         }
58794     },
58795
58796     
58797     setLeft: function(left) {
58798         this.callParent(arguments);
58799         return this.sync();
58800     },
58801
58802     setTop: function(top) {
58803         this.callParent(arguments);
58804         return this.sync();
58805     },
58806
58807     setLeftTop: function(left, top) {
58808         this.callParent(arguments);
58809         return this.sync();
58810     },
58811
58812     setXY: function(xy, animate, duration, callback, easing) {
58813
58814         
58815         callback = this.createCB(callback);
58816
58817         this.fixDisplay();
58818         this.beforeAction();
58819         this.callParent([xy, animate, duration, callback, easing]);
58820         if (!animate) {
58821             callback();
58822         }
58823         return this;
58824     },
58825
58826     
58827     createCB: function(callback) {
58828         var me = this,
58829             showShadow = me.shadow && me.shadow.isVisible();
58830
58831         return function() {
58832             me.constrainXY();
58833             me.sync(showShadow);
58834             if (callback) {
58835                 callback();
58836             }
58837         };
58838     },
58839
58840     
58841     setX: function(x, animate, duration, callback, easing) {
58842         this.setXY([x, this.getY()], animate, duration, callback, easing);
58843         return this;
58844     },
58845
58846     
58847     setY: function(y, animate, duration, callback, easing) {
58848         this.setXY([this.getX(), y], animate, duration, callback, easing);
58849         return this;
58850     },
58851
58852     
58853     setSize: function(w, h, animate, duration, callback, easing) {
58854         
58855         callback = this.createCB(callback);
58856
58857         this.beforeAction();
58858         this.callParent([w, h, animate, duration, callback, easing]);
58859         if (!animate) {
58860             callback();
58861         }
58862         return this;
58863     },
58864
58865     
58866     setWidth: function(w, animate, duration, callback, easing) {
58867         
58868         callback = this.createCB(callback);
58869
58870         this.beforeAction();
58871         this.callParent([w, animate, duration, callback, easing]);
58872         if (!animate) {
58873             callback();
58874         }
58875         return this;
58876     },
58877
58878     
58879     setHeight: function(h, animate, duration, callback, easing) {
58880         
58881         callback = this.createCB(callback);
58882
58883         this.beforeAction();
58884         this.callParent([h, animate, duration, callback, easing]);
58885         if (!animate) {
58886             callback();
58887         }
58888         return this;
58889     },
58890
58891     
58892     setBounds: function(x, y, width, height, animate, duration, callback, easing) {
58893         
58894         callback = this.createCB(callback);
58895
58896         this.beforeAction();
58897         if (!animate) {
58898             Ext.Layer.superclass.setXY.call(this, [x, y]);
58899             Ext.Layer.superclass.setSize.call(this, width, height);
58900             callback();
58901         } else {
58902             this.callParent([x, y, width, height, animate, duration, callback, easing]);
58903         }
58904         return this;
58905     },
58906
58907     
58908     setZIndex: function(zindex) {
58909         this.zindex = zindex;
58910         if (this.getShim()) {
58911             this.shim.setStyle('z-index', zindex++);
58912         }
58913         if (this.shadow) {
58914             this.shadow.setZIndex(zindex++);
58915         }
58916         this.setStyle('z-index', zindex);
58917         return this;
58918     }
58919 });
58920
58921
58922
58923 Ext.define('Ext.layout.component.ProgressBar', {
58924
58925     
58926
58927     alias: ['layout.progressbar'],
58928
58929     extend: 'Ext.layout.component.Component',
58930
58931     
58932
58933     type: 'progressbar',
58934
58935     onLayout: function(width, height) {
58936         var me = this,
58937             owner = me.owner,
58938             textEl = owner.textEl;
58939         
58940         me.setElementSize(owner.el, width, height);
58941         textEl.setWidth(owner.el.getWidth(true));
58942         
58943         me.callParent([width, height]);
58944         
58945         owner.updateProgress(owner.value);
58946     }
58947 });
58948
58949 Ext.define('Ext.ProgressBar', {
58950     extend: 'Ext.Component',
58951     alias: 'widget.progressbar',
58952
58953     requires: [
58954         'Ext.Template',
58955         'Ext.CompositeElement',
58956         'Ext.TaskManager',
58957         'Ext.layout.component.ProgressBar'
58958     ],
58959
58960     uses: ['Ext.fx.Anim'],
58961    
58962     baseCls: Ext.baseCSSPrefix + 'progress',
58963
58964     config: {
58965         
58966         animate: false,
58967
58968         
58969         text: ''
58970     },
58971
58972     
58973     waitTimer: null,
58974
58975     renderTpl: [
58976         '<div class="{baseCls}-text {baseCls}-text-back">',
58977             '<div>&#160;</div>',
58978         '</div>',
58979         '<div class="{baseCls}-bar">',
58980             '<div class="{baseCls}-text">',
58981                 '<div>&#160;</div>',
58982             '</div>',
58983         '</div>'
58984     ],
58985
58986     componentLayout: 'progressbar',
58987
58988     
58989     initComponent: function() {
58990         this.callParent();
58991
58992         this.renderSelectors = Ext.apply(this.renderSelectors || {}, {
58993             textTopEl: '.' + this.baseCls + '-text',
58994             textBackEl: '.' + this.baseCls + '-text-back',
58995             bar: '.' + this.baseCls + '-bar'
58996         });
58997
58998         this.addEvents(
58999             
59000             "update"
59001         );
59002     },
59003
59004     afterRender : function() {
59005         var me = this;
59006
59007         me.textEl = me.textEl ? Ext.get(me.textEl) : me.el.select('.' + me.baseCls + '-text');
59008
59009         this.callParent(arguments);
59010
59011         if (me.value) {
59012             me.updateProgress(me.value, me.text);
59013         }
59014         else {
59015             me.updateText(me.text);
59016         }
59017     },
59018
59019     
59020     updateProgress: function(value, text, animate) {
59021         var newWidth;
59022         this.value = value || 0;
59023         if (text) {
59024             this.updateText(text);
59025         }
59026         if (this.rendered && !this.isDestroyed) {
59027             newWidth = Math.floor(this.value * this.el.getWidth(true));
59028             if (Ext.isForcedBorderBox) {
59029                 newWidth += this.bar.getBorderWidth("lr");
59030             }
59031             if (animate === true || (animate !== false && this.animate)) {
59032                 this.bar.stopAnimation();
59033                 this.bar.animate(Ext.apply({
59034                     to: {
59035                         width: newWidth + 'px'
59036                     }
59037                 }, this.animate));
59038             } else {
59039                 this.bar.setWidth(newWidth);
59040             }
59041         }
59042         this.fireEvent('update', this, this.value, text);
59043         return this;
59044     },
59045
59046     
59047     updateText: function(text) {
59048         this.text = text;
59049         if (this.rendered) {
59050             this.textEl.update(this.text);
59051         }
59052         return this;
59053     },
59054
59055     applyText : function(text) {
59056         this.updateText(text);
59057     },
59058
59059     
59060     wait: function(o) {
59061         if (!this.waitTimer) {
59062             var scope = this;
59063             o = o || {};
59064             this.updateText(o.text);
59065             this.waitTimer = Ext.TaskManager.start({
59066                 run: function(i){
59067                     var inc = o.increment || 10;
59068                     i -= 1;
59069                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
59070                 },
59071                 interval: o.interval || 1000,
59072                 duration: o.duration,
59073                 onStop: function(){
59074                     if (o.fn) {
59075                         o.fn.apply(o.scope || this);
59076                     }
59077                     this.reset();
59078                 },
59079                 scope: scope
59080             });
59081         }
59082         return this;
59083     },
59084
59085     
59086     isWaiting: function(){
59087         return this.waitTimer !== null;
59088     },
59089
59090     
59091     reset: function(hide){
59092         this.updateProgress(0);
59093         this.clearTimer();
59094         if (hide === true) {
59095             this.hide();
59096         }
59097         return this;
59098     },
59099
59100     
59101     clearTimer: function(){
59102         if (this.waitTimer) {
59103             this.waitTimer.onStop = null; 
59104             Ext.TaskManager.stop(this.waitTimer);
59105             this.waitTimer = null;
59106         }
59107     },
59108
59109     onDestroy: function(){
59110         this.clearTimer();
59111         if (this.rendered) {
59112             if (this.textEl.isComposite) {
59113                 this.textEl.clear();
59114             }
59115             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
59116         }
59117         this.callParent();
59118     }
59119 });
59120
59121
59122 Ext.define('Ext.ShadowPool', {
59123     singleton: true,
59124     requires: ['Ext.core.DomHelper'],
59125
59126     markup: function() {
59127         if (Ext.supports.CSS3BoxShadow) {
59128             return '<div class="' + Ext.baseCSSPrefix + 'css-shadow" role="presentation"></div>';
59129         } else if (Ext.isIE) {
59130             return '<div class="' + Ext.baseCSSPrefix + 'ie-shadow" role="presentation"></div>';
59131         } else {
59132             return '<div class="' + Ext.baseCSSPrefix + 'frame-shadow" role="presentation">' +
59133                 '<div class="xst" role="presentation">' +
59134                     '<div class="xstl" role="presentation"></div>' +
59135                     '<div class="xstc" role="presentation"></div>' +
59136                     '<div class="xstr" role="presentation"></div>' +
59137                 '</div>' +
59138                 '<div class="xsc" role="presentation">' +
59139                     '<div class="xsml" role="presentation"></div>' +
59140                     '<div class="xsmc" role="presentation"></div>' +
59141                     '<div class="xsmr" role="presentation"></div>' +
59142                 '</div>' +
59143                 '<div class="xsb" role="presentation">' +
59144                     '<div class="xsbl" role="presentation"></div>' +
59145                     '<div class="xsbc" role="presentation"></div>' +
59146                     '<div class="xsbr" role="presentation"></div>' +
59147                 '</div>' +
59148             '</div>';
59149         }
59150     }(),
59151
59152     shadows: [],
59153
59154     pull: function() {
59155         var sh = this.shadows.shift();
59156         if (!sh) {
59157             sh = Ext.get(Ext.core.DomHelper.insertHtml("beforeBegin", document.body.firstChild, this.markup));
59158             sh.autoBoxAdjust = false;
59159         }
59160         return sh;
59161     },
59162
59163     push: function(sh) {
59164         this.shadows.push(sh);
59165     },
59166     
59167     reset: function() {
59168         Ext.Array.each(this.shadows, function(shadow) {
59169             shadow.remove();
59170         });
59171         this.shadows = [];
59172     }
59173 });
59174
59175 Ext.define('Ext.Shadow', {
59176     requires: ['Ext.ShadowPool'],
59177
59178     constructor: function(config) {
59179         Ext.apply(this, config);
59180         if (typeof this.mode != "string") {
59181             this.mode = this.defaultMode;
59182         }
59183         var offset = this.offset,
59184             adjusts = {
59185                 h: 0
59186             },
59187             rad = Math.floor(this.offset / 2);
59188
59189         switch (this.mode.toLowerCase()) {
59190             
59191             case "drop":
59192                 if (Ext.supports.CSS3BoxShadow) {
59193                     adjusts.w = adjusts.h = -offset;
59194                     adjusts.l = adjusts.t = offset;
59195                 } else {
59196                     adjusts.w = 0;
59197                     adjusts.l = adjusts.t = offset;
59198                     adjusts.t -= 1;
59199                     if (Ext.isIE) {
59200                         adjusts.l -= offset + rad;
59201                         adjusts.t -= offset + rad;
59202                         adjusts.w -= rad;
59203                         adjusts.h -= rad;
59204                         adjusts.t += 1;
59205                     }
59206                 }
59207                 break;
59208             case "sides":
59209                 if (Ext.supports.CSS3BoxShadow) {
59210                     adjusts.h -= offset;
59211                     adjusts.t = offset;
59212                     adjusts.l = adjusts.w = 0;
59213                 } else {
59214                     adjusts.w = (offset * 2);
59215                     adjusts.l = -offset;
59216                     adjusts.t = offset - 1;
59217                     if (Ext.isIE) {
59218                         adjusts.l -= (offset - rad);
59219                         adjusts.t -= offset + rad;
59220                         adjusts.l += 1;
59221                         adjusts.w -= (offset - rad) * 2;
59222                         adjusts.w -= rad + 1;
59223                         adjusts.h -= 1;
59224                     }
59225                 }
59226                 break;
59227             case "frame":
59228                 if (Ext.supports.CSS3BoxShadow) {
59229                     adjusts.l = adjusts.w = adjusts.t = 0;
59230                 } else {
59231                     adjusts.w = adjusts.h = (offset * 2);
59232                     adjusts.l = adjusts.t = -offset;
59233                     adjusts.t += 1;
59234                     adjusts.h -= 2;
59235                     if (Ext.isIE) {
59236                         adjusts.l -= (offset - rad);
59237                         adjusts.t -= (offset - rad);
59238                         adjusts.l += 1;
59239                         adjusts.w -= (offset + rad + 1);
59240                         adjusts.h -= (offset + rad);
59241                         adjusts.h += 1;
59242                     }
59243                     break;
59244                 }
59245         }
59246         this.adjusts = adjusts;
59247     },
59248
59249     
59250     
59251     offset: 4,
59252
59253     
59254     defaultMode: "drop",
59255
59256     
59257     show: function(target) {
59258         target = Ext.get(target);
59259         if (!this.el) {
59260             this.el = Ext.ShadowPool.pull();
59261             if (this.el.dom.nextSibling != target.dom) {
59262                 this.el.insertBefore(target);
59263             }
59264         }
59265         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10) - 1);
59266         if (Ext.isIE && !Ext.supports.CSS3BoxShadow) {
59267             this.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (this.offset) + ")";
59268         }
59269         this.realign(
59270             target.getLeft(true),
59271             target.getTop(true),
59272             target.getWidth(),
59273             target.getHeight()
59274         );
59275         this.el.dom.style.display = "block";
59276     },
59277
59278     
59279     isVisible: function() {
59280         return this.el ? true: false;
59281     },
59282
59283     
59284     realign: function(l, t, targetWidth, targetHeight) {
59285         if (!this.el) {
59286             return;
59287         }
59288         var adjusts = this.adjusts,
59289             d = this.el.dom,
59290             targetStyle = d.style,
59291             shadowWidth,
59292             shadowHeight,
59293             cn,
59294             sww, 
59295             sws, 
59296             shs;
59297
59298         targetStyle.left = (l + adjusts.l) + "px";
59299         targetStyle.top = (t + adjusts.t) + "px";
59300         shadowWidth = Math.max(targetWidth + adjusts.w, 0);
59301         shadowHeight = Math.max(targetHeight + adjusts.h, 0);
59302         sws = shadowWidth + "px";
59303         shs = shadowHeight + "px";
59304         if (targetStyle.width != sws || targetStyle.height != shs) {
59305             targetStyle.width = sws;
59306             targetStyle.height = shs;
59307             if (Ext.supports.CSS3BoxShadow) {
59308                 targetStyle.boxShadow = '0 0 ' + this.offset + 'px 0 #888';
59309             } else {
59310
59311                 
59312                 if (!Ext.isIE) {
59313                     cn = d.childNodes;
59314                     sww = Math.max(0, (shadowWidth - 12)) + "px";
59315                     cn[0].childNodes[1].style.width = sww;
59316                     cn[1].childNodes[1].style.width = sww;
59317                     cn[2].childNodes[1].style.width = sww;
59318                     cn[1].style.height = Math.max(0, (shadowHeight - 12)) + "px";
59319                 }
59320             }
59321         }
59322     },
59323
59324     
59325     hide: function() {
59326         if (this.el) {
59327             this.el.dom.style.display = "none";
59328             Ext.ShadowPool.push(this.el);
59329             delete this.el;
59330         }
59331     },
59332
59333     
59334     setZIndex: function(z) {
59335         this.zIndex = z;
59336         if (this.el) {
59337             this.el.setStyle("z-index", z);
59338         }
59339     }
59340 });
59341
59342
59343 Ext.define('Ext.button.Split', {
59344
59345     
59346
59347     alias: 'widget.splitbutton',
59348
59349     extend: 'Ext.button.Button',
59350     alternateClassName: 'Ext.SplitButton',
59351
59352     
59353     arrowCls      : 'split',
59354     split         : true,
59355
59356     
59357     initComponent : function(){
59358         this.callParent();
59359         
59360         this.addEvents("arrowclick");
59361     },
59362
59363      
59364     setArrowHandler : function(handler, scope){
59365         this.arrowHandler = handler;
59366         this.scope = scope;
59367     },
59368
59369     
59370     onClick : function(e, t) {
59371         var me = this;
59372         
59373         e.preventDefault();
59374         if (!me.disabled) {
59375             if (me.overMenuTrigger) {
59376                 if (me.menu && !me.menu.isVisible() && !me.ignoreNextClick) {
59377                     me.showMenu();
59378                 }
59379                 me.fireEvent("arrowclick", me, e);
59380                 if (me.arrowHandler) {
59381                     me.arrowHandler.call(me.scope || me, me, e);
59382                 }
59383             } else {
59384                 if (me.enableToggle) {
59385                     me.toggle();
59386                 }
59387                 me.fireEvent("click", me, e);
59388                 if (me.handler) {
59389                     me.handler.call(me.scope || me, me, e);
59390                 }
59391                 me.onBlur();
59392             }
59393         }
59394     }
59395 });
59396
59397
59398 Ext.define('Ext.button.Cycle', {
59399
59400     
59401
59402     alias: 'widget.cycle',
59403
59404     extend: 'Ext.button.Split',
59405     alternateClassName: 'Ext.CycleButton',
59406
59407     
59408
59409     
59410     
59411     
59412     
59413     
59414     
59415
59416     
59417     getButtonText: function(item) {
59418         var me = this,
59419             text = '';
59420
59421         if (item && me.showText === true) {
59422             if (me.prependText) {
59423                 text += me.prependText;
59424             }
59425             text += item.text;
59426             return text;
59427         }
59428         return me.text;
59429     },
59430
59431     
59432     setActiveItem: function(item, suppressEvent) {
59433         var me = this;
59434
59435         if (!Ext.isObject(item)) {
59436             item = me.menu.getComponent(item);
59437         }
59438         if (item) {
59439             if (!me.rendered) {
59440                 me.text = me.getButtonText(item);
59441                 me.iconCls = item.iconCls;
59442             } else {
59443                 me.setText(me.getButtonText(item));
59444                 me.setIconCls(item.iconCls);
59445             }
59446             me.activeItem = item;
59447             if (!item.checked) {
59448                 item.setChecked(true, false);
59449             }
59450             if (me.forceIcon) {
59451                 me.setIconCls(me.forceIcon);
59452             }
59453             if (!suppressEvent) {
59454                 me.fireEvent('change', me, item);
59455             }
59456         }
59457     },
59458
59459     
59460     getActiveItem: function() {
59461         return this.activeItem;
59462     },
59463
59464     
59465     initComponent: function() {
59466         var me = this,
59467             checked = 0,
59468             items;
59469
59470         me.addEvents(
59471             
59472             "change"
59473         );
59474
59475         if (me.changeHandler) {
59476             me.on('change', me.changeHandler, me.scope || me);
59477             delete me.changeHandler;
59478         }
59479
59480         
59481         
59482         items = (me.menu.items||[]).concat(me.items||[]);
59483         me.menu = Ext.applyIf({
59484             cls: Ext.baseCSSPrefix + 'cycle-menu',
59485             items: []
59486         }, me.menu);
59487
59488         
59489         Ext.each(items, function(item, i) {
59490             item = Ext.applyIf({
59491                 group: me.id,
59492                 itemIndex: i,
59493                 checkHandler: me.checkHandler,
59494                 scope: me,
59495                 checked: item.checked || false
59496             }, item);
59497             me.menu.items.push(item);
59498             if (item.checked) {
59499                 checked = i;
59500             }
59501         });
59502         me.itemCount = me.menu.items.length;
59503         me.callParent(arguments);
59504         me.on('click', me.toggleSelected, me);
59505         me.setActiveItem(checked, me);
59506
59507         
59508         if (me.width && me.showText) {
59509             me.addCls(Ext.baseCSSPrefix + 'cycle-fixed-width');
59510         }
59511     },
59512
59513     
59514     checkHandler: function(item, pressed) {
59515         if (pressed) {
59516             this.setActiveItem(item);
59517         }
59518     },
59519
59520     
59521     toggleSelected: function() {
59522         var me = this,
59523             m = me.menu,
59524             checkItem;
59525
59526         checkItem = me.activeItem.next(':not([disabled])') || m.items.getAt(0);
59527         checkItem.setChecked(true);
59528     }
59529 });
59530
59531 Ext.define('Ext.container.ButtonGroup', {
59532     extend: 'Ext.panel.Panel',
59533     alias: 'widget.buttongroup',
59534     alternateClassName: 'Ext.ButtonGroup',
59535
59536     
59537
59538     
59539     baseCls: Ext.baseCSSPrefix + 'btn-group',
59540
59541     
59542     layout: {
59543         type: 'table'
59544     },
59545
59546     defaultType: 'button',
59547
59548     
59549     frame: true,
59550     
59551     frameHeader: false,
59552     
59553     internalDefaults: {removeMode: 'container', hideParent: true},
59554
59555     initComponent : function(){
59556         
59557         var me = this,
59558             cols = me.columns;
59559
59560         me.noTitleCls = me.baseCls + '-notitle';
59561         if (cols) {
59562             me.layout = Ext.apply({}, {columns: cols}, me.layout);
59563         }
59564
59565         if (!me.title) {
59566             me.addCls(me.noTitleCls);
59567         }
59568         me.callParent(arguments);
59569     },
59570
59571     afterLayout: function() {
59572         var me = this;
59573         
59574         me.callParent(arguments);
59575
59576         
59577         
59578         if (me.layout.table && (Ext.isIEQuirks || Ext.isIE6) && !me.width) {
59579             var t = me.getTargetEl();
59580             t.setWidth(me.layout.table.offsetWidth + t.getPadding('lr'));
59581         }
59582     },
59583
59584     afterRender: function() {
59585         var me = this;
59586         
59587         
59588         if (me.header) {
59589             me.header.insert(0, {
59590                 xtype: 'component',
59591                 ui   : me.ui,
59592                 html : '&nbsp;',
59593                 flex : 1
59594             });
59595         }
59596         
59597         me.callParent(arguments);
59598     },
59599     
59600     
59601     onBeforeAdd: function(component) {
59602         if (component.is('button')) {
59603             component.ui = component.ui + '-toolbar';
59604         }
59605         this.callParent(arguments);
59606     },
59607
59608     
59609     applyDefaults: function(c) {
59610         if (!Ext.isString(c)) {
59611             c = this.callParent(arguments);
59612             var d = this.internalDefaults;
59613             if (c.events) {
59614                 Ext.applyIf(c.initialConfig, d);
59615                 Ext.apply(c, d);
59616             } else {
59617                 Ext.applyIf(c, d);
59618             }
59619         }
59620         return c;
59621     }
59622
59623     
59624     
59625     
59626     
59627     
59628 });
59629
59630
59631 Ext.define('Ext.container.Viewport', {
59632     extend: 'Ext.container.Container',
59633     alias: 'widget.viewport',
59634     requires: ['Ext.EventManager'],
59635     alternateClassName: 'Ext.Viewport',
59636
59637     
59638     
59639     
59640     
59641     
59642     
59643     
59644     
59645     
59646     
59647     
59648     
59649
59650     isViewport: true,
59651
59652     ariaRole: 'application',
59653     initComponent : function() {
59654         var me = this,
59655             html = Ext.fly(document.body.parentNode),
59656             el;
59657         me.callParent(arguments);
59658         html.addCls(Ext.baseCSSPrefix + 'viewport');
59659         if (me.autoScroll) {
59660             html.setStyle('overflow', 'auto');
59661         }
59662         me.el = el = Ext.getBody();
59663         el.setHeight = Ext.emptyFn;
59664         el.setWidth = Ext.emptyFn;
59665         el.setSize = Ext.emptyFn;
59666         el.dom.scroll = 'no';
59667         me.allowDomMove = false;
59668         
59669         
59670         Ext.EventManager.onWindowResize(me.fireResize, me);
59671         me.renderTo = me.el;
59672     },
59673
59674     fireResize : function(w, h){
59675         
59676         this.setSize(w, h);
59677         
59678     }
59679 });
59680
59681
59682
59683
59684
59685 Ext.define('Ext.dd.DDTarget', {
59686     extend: 'Ext.dd.DragDrop',
59687     constructor: function(id, sGroup, config) {
59688         if (id) {
59689             this.initTarget(id, sGroup, config);
59690         }
59691     },
59692
59693     
59694     getDragEl: Ext.emptyFn,
59695     
59696     isValidHandleChild: Ext.emptyFn,
59697     
59698     startDrag: Ext.emptyFn,
59699     
59700     endDrag: Ext.emptyFn,
59701     
59702     onDrag: Ext.emptyFn,
59703     
59704     onDragDrop: Ext.emptyFn,
59705     
59706     onDragEnter: Ext.emptyFn,
59707     
59708     onDragOut: Ext.emptyFn,
59709     
59710     onDragOver: Ext.emptyFn,
59711     
59712     onInvalidDrop: Ext.emptyFn,
59713     
59714     onMouseDown: Ext.emptyFn,
59715     
59716     onMouseUp: Ext.emptyFn,
59717     
59718     setXConstraint: Ext.emptyFn,
59719     
59720     setYConstraint: Ext.emptyFn,
59721     
59722     resetConstraints: Ext.emptyFn,
59723     
59724     clearConstraints: Ext.emptyFn,
59725     
59726     clearTicks: Ext.emptyFn,
59727     
59728     setInitPosition: Ext.emptyFn,
59729     
59730     setDragElId: Ext.emptyFn,
59731     
59732     setHandleElId: Ext.emptyFn,
59733     
59734     setOuterHandleElId: Ext.emptyFn,
59735     
59736     addInvalidHandleClass: Ext.emptyFn,
59737     
59738     addInvalidHandleId: Ext.emptyFn,
59739     
59740     addInvalidHandleType: Ext.emptyFn,
59741     
59742     removeInvalidHandleClass: Ext.emptyFn,
59743     
59744     removeInvalidHandleId: Ext.emptyFn,
59745     
59746     removeInvalidHandleType: Ext.emptyFn,
59747
59748     toString: function() {
59749         return ("DDTarget " + this.id);
59750     }
59751 });
59752
59753 Ext.define('Ext.dd.DragTracker', {
59754
59755     uses: ['Ext.util.Region'],
59756
59757     mixins: {
59758         observable: 'Ext.util.Observable'
59759     },
59760
59761     
59762     active: false,
59763
59764     
59765
59766     
59767     trackOver: false,
59768
59769     
59770
59771     
59772
59773     
59774     tolerance: 5,
59775
59776     
59777     autoStart: false,
59778
59779     
59780
59781     
59782
59783     
59784
59785     constructor : function(config){
59786         Ext.apply(this, config);
59787         this.addEvents(
59788             
59789             'mouseover',
59790
59791             
59792             'mouseout',
59793
59794             
59795             'mousedown',
59796
59797             
59798             'mouseup',
59799
59800             
59801             'mousemove',
59802
59803             
59804             'dragstart',
59805
59806             
59807             'dragend',
59808
59809             
59810             'drag'
59811         );
59812
59813         this.dragRegion = Ext.create('Ext.util.Region', 0,0,0,0);
59814
59815         if (this.el) {
59816             this.initEl(this.el);
59817         }
59818
59819         
59820         this.mixins.observable.constructor.call(this);
59821         if (this.disabled) {
59822             this.disable();
59823         }
59824
59825     },
59826
59827     
59828     initEl: function(el) {
59829         this.el = Ext.get(el);
59830
59831         
59832         this.handle = Ext.get(this.delegate);
59833
59834         
59835         this.delegate = this.handle ? undefined : this.delegate;
59836
59837         if (!this.handle) {
59838             this.handle = this.el;
59839         }
59840
59841         
59842         
59843         this.mon(this.handle, {
59844             mousedown: this.onMouseDown,
59845             delegate: this.delegate,
59846             scope: this
59847         });
59848
59849         
59850         
59851         
59852         if (this.trackOver || this.overCls) {
59853             this.mon(this.handle, {
59854                 mouseover: this.onMouseOver,
59855                 mouseout: this.onMouseOut,
59856                 delegate: this.delegate,
59857                 scope: this
59858             });
59859         }
59860     },
59861
59862     disable: function() {
59863         this.disabled = true;
59864     },
59865
59866     enable: function() {
59867         this.disabled = false;
59868     },
59869
59870     destroy : function() {
59871         this.clearListeners();
59872         delete this.el;
59873     },
59874
59875     
59876     
59877     onMouseOver: function(e, target) {
59878         var me = this;
59879         if (!me.disabled) {
59880             if (Ext.EventManager.contains(e) || me.delegate) {
59881                 me.mouseIsOut = false;
59882                 if (me.overCls) {
59883                     me.el.addCls(me.overCls);
59884                 }
59885                 me.fireEvent('mouseover', me, e, me.delegate ? e.getTarget(me.delegate, target) : me.handle);
59886             }
59887         }
59888     },
59889
59890     
59891     
59892     onMouseOut: function(e) {
59893         if (this.mouseIsDown) {
59894             this.mouseIsOut = true;
59895         } else {
59896             if (this.overCls) {
59897                 this.el.removeCls(this.overCls);
59898             }
59899             this.fireEvent('mouseout', this, e);
59900         }
59901     },
59902
59903     onMouseDown: function(e, target){
59904         
59905         if (this.disabled ||e.dragTracked) {
59906             return;
59907         }
59908
59909         
59910         this.dragTarget = this.delegate ? target : this.handle.dom;
59911         this.startXY = this.lastXY = e.getXY();
59912         this.startRegion = Ext.fly(this.dragTarget).getRegion();
59913
59914         if (this.fireEvent('mousedown', this, e) !== false && this.onBeforeStart(e) !== false) {
59915
59916             
59917             
59918             this.mouseIsDown = true;
59919
59920             
59921             e.dragTracked = true;
59922
59923             if (this.preventDefault !== false) {
59924                 e.preventDefault();
59925             }
59926             Ext.getDoc().on({
59927                 scope: this,
59928                 mouseup: this.onMouseUp,
59929                 mousemove: this.onMouseMove,
59930                 selectstart: this.stopSelect
59931             });
59932             if (this.autoStart) {
59933                 this.timer =  Ext.defer(this.triggerStart, this.autoStart === true ? 1000 : this.autoStart, this, [e]);
59934             }
59935         }
59936     },
59937
59938     onMouseMove: function(e, target){
59939         
59940         
59941         if (this.active && Ext.isIE && !e.browserEvent.button) {
59942             e.preventDefault();
59943             this.onMouseUp(e);
59944             return;
59945         }
59946
59947         e.preventDefault();
59948         var xy = e.getXY(),
59949             s = this.startXY;
59950
59951         this.lastXY = xy;
59952         if (!this.active) {
59953             if (Math.max(Math.abs(s[0]-xy[0]), Math.abs(s[1]-xy[1])) > this.tolerance) {
59954                 this.triggerStart(e);
59955             } else {
59956                 return;
59957             }
59958         }
59959
59960         
59961         if (this.fireEvent('mousemove', this, e) === false) {
59962             this.onMouseUp(e);
59963         } else {
59964             this.onDrag(e);
59965             this.fireEvent('drag', this, e);
59966         }
59967     },
59968
59969     onMouseUp: function(e) {
59970         
59971         
59972         this.mouseIsDown = false;
59973
59974         
59975         delete e.dragTracked;
59976
59977         
59978         if (this.mouseIsOut) {
59979             this.mouseIsOut = false;
59980             this.onMouseOut(e);
59981         }
59982         e.preventDefault();
59983         this.fireEvent('mouseup', this, e);
59984         this.endDrag(e);
59985     },
59986
59987     
59988     endDrag: function(e) {
59989         var doc = Ext.getDoc(),
59990         wasActive = this.active;
59991
59992         doc.un('mousemove', this.onMouseMove, this);
59993         doc.un('mouseup', this.onMouseUp, this);
59994         doc.un('selectstart', this.stopSelect, this);
59995         this.clearStart();
59996         this.active = false;
59997         if (wasActive) {
59998             this.onEnd(e);
59999             this.fireEvent('dragend', this, e);
60000         }
60001         
60002         delete this._constrainRegion;
60003     },
60004
60005     triggerStart: function(e) {
60006         this.clearStart();
60007         this.active = true;
60008         this.onStart(e);
60009         this.fireEvent('dragstart', this, e);
60010     },
60011
60012     clearStart : function() {
60013         if (this.timer) {
60014             clearTimeout(this.timer);
60015             delete this.timer;
60016         }
60017     },
60018
60019     stopSelect : function(e) {
60020         e.stopEvent();
60021         return false;
60022     },
60023
60024     
60025     onBeforeStart : function(e) {
60026
60027     },
60028
60029     
60030     onStart : function(xy) {
60031
60032     },
60033
60034     
60035     onDrag : function(e) {
60036
60037     },
60038
60039     
60040     onEnd : function(e) {
60041
60042     },
60043
60044     
60045     getDragTarget : function(){
60046         return this.dragTarget;
60047     },
60048
60049     
60050     getDragCt : function(){
60051         return this.el;
60052     },
60053
60054     
60055     getConstrainRegion: function() {
60056         if (this.constrainTo) {
60057             if (this.constrainTo instanceof Ext.util.Region) {
60058                 return this.constrainTo;
60059             }
60060             if (!this._constrainRegion) {
60061                 this._constrainRegion = Ext.fly(this.constrainTo).getViewRegion();
60062             }
60063         } else {
60064             if (!this._constrainRegion) {
60065                 this._constrainRegion = this.getDragCt().getViewRegion();
60066             }
60067         }
60068         return this._constrainRegion;
60069     },
60070
60071     getXY : function(constrain){
60072         return constrain ? this.constrainModes[constrain].call(this, this.lastXY) : this.lastXY;
60073     },
60074
60075     
60076     getOffset : function(constrain){
60077         var xy = this.getXY(constrain),
60078             s = this.startXY;
60079
60080         return [xy[0]-s[0], xy[1]-s[1]];
60081     },
60082
60083     constrainModes: {
60084         
60085         point: function(xy) {
60086             var dr = this.dragRegion,
60087                 constrainTo = this.getConstrainRegion();
60088
60089             
60090             if (!constrainTo) {
60091                 return xy;
60092             }
60093
60094             dr.x = dr.left = dr[0] = dr.right = xy[0];
60095             dr.y = dr.top = dr[1] = dr.bottom = xy[1];
60096             dr.constrainTo(constrainTo);
60097
60098             return [dr.left, dr.top];
60099         },
60100
60101         
60102         dragTarget: function(xy) {
60103             var s = this.startXY,
60104                 dr = this.startRegion.copy(),
60105                 constrainTo = this.getConstrainRegion(),
60106                 adjust;
60107
60108             
60109             if (!constrainTo) {
60110                 return xy;
60111             }
60112
60113             
60114             
60115             
60116             dr.translateBy.apply(dr, [xy[0]-s[0], xy[1]-s[1]]);
60117
60118             
60119             if (dr.right > constrainTo.right) {
60120                 xy[0] += adjust = (constrainTo.right - dr.right);    
60121                 dr.left += adjust;
60122             }
60123             if (dr.left < constrainTo.left) {
60124                 xy[0] += (constrainTo.left - dr.left);      
60125             }
60126
60127             
60128             if (dr.bottom > constrainTo.bottom) {
60129                 xy[1] += adjust = (constrainTo.bottom - dr.bottom);  
60130                 dr.top += adjust;
60131             }
60132             if (dr.top < constrainTo.top) {
60133                 xy[1] += (constrainTo.top - dr.top);        
60134             }
60135             return xy;
60136         }
60137     }
60138 });
60139
60140 Ext.define('Ext.dd.DragZone', {
60141
60142     extend: 'Ext.dd.DragSource',
60143
60144     constructor : function(el, config){
60145         this.callParent([el, config]);
60146         if (this.containerScroll) {
60147             Ext.dd.ScrollManager.register(this.el);
60148         }
60149     },
60150
60151     
60152
60153     
60154
60155     
60156     getDragData : function(e){
60157         return Ext.dd.Registry.getHandleFromEvent(e);
60158     },
60159
60160     
60161     onInitDrag : function(x, y){
60162         this.proxy.update(this.dragData.ddel.cloneNode(true));
60163         this.onStartDrag(x, y);
60164         return true;
60165     },
60166
60167     
60168     afterRepair : function(){
60169         var me = this;
60170         if (Ext.enableFx) {
60171             Ext.fly(me.dragData.ddel).highlight(me.repairHighlightColor);
60172         }
60173         me.dragging = false;
60174     },
60175
60176     
60177     getRepairXY : function(e){
60178         return Ext.core.Element.fly(this.dragData.ddel).getXY();
60179     },
60180
60181     destroy : function(){
60182         this.callParent();
60183         if (this.containerScroll) {
60184             Ext.dd.ScrollManager.unregister(this.el);
60185         }
60186     }
60187 });
60188
60189
60190 Ext.define('Ext.dd.ScrollManager', {
60191     singleton: true,
60192     requires: [
60193         'Ext.dd.DragDropManager'
60194     ],
60195
60196     constructor: function() {
60197         var ddm = Ext.dd.DragDropManager;
60198         ddm.fireEvents = Ext.Function.createSequence(ddm.fireEvents, this.onFire, this);
60199         ddm.stopDrag = Ext.Function.createSequence(ddm.stopDrag, this.onStop, this);
60200         this.doScroll = Ext.Function.bind(this.doScroll, this);
60201         this.ddmInstance = ddm;
60202         this.els = {};
60203         this.dragEl = null;
60204         this.proc = {};
60205     },
60206
60207     onStop: function(e){
60208         var sm = Ext.dd.ScrollManager;
60209         sm.dragEl = null;
60210         sm.clearProc();
60211     },
60212
60213     triggerRefresh: function() {
60214         if (this.ddmInstance.dragCurrent) {
60215             this.ddmInstance.refreshCache(this.ddmInstance.dragCurrent.groups);
60216         }
60217     },
60218
60219     doScroll: function() {
60220         if (this.ddmInstance.dragCurrent) {
60221             var proc   = this.proc,
60222                 procEl = proc.el,
60223                 ddScrollConfig = proc.el.ddScrollConfig,
60224                 inc = ddScrollConfig ? ddScrollConfig.increment : this.increment;
60225
60226             if (!this.animate) {
60227                 if (procEl.scroll(proc.dir, inc)) {
60228                     this.triggerRefresh();
60229                 }
60230             } else {
60231                 procEl.scroll(proc.dir, inc, true, this.animDuration, this.triggerRefresh);
60232             }
60233         }
60234     },
60235
60236     clearProc: function() {
60237         var proc = this.proc;
60238         if (proc.id) {
60239             clearInterval(proc.id);
60240         }
60241         proc.id = 0;
60242         proc.el = null;
60243         proc.dir = "";
60244     },
60245
60246     startProc: function(el, dir) {
60247         this.clearProc();
60248         this.proc.el = el;
60249         this.proc.dir = dir;
60250         var group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined,
60251             freq  = (el.ddScrollConfig && el.ddScrollConfig.frequency)
60252                   ? el.ddScrollConfig.frequency
60253                   : this.frequency;
60254
60255         if (group === undefined || this.ddmInstance.dragCurrent.ddGroup == group) {
60256             this.proc.id = setInterval(this.doScroll, freq);
60257         }
60258     },
60259
60260     onFire: function(e, isDrop) {
60261         if (isDrop || !this.ddmInstance.dragCurrent) {
60262             return;
60263         }
60264         if (!this.dragEl || this.dragEl != this.ddmInstance.dragCurrent) {
60265             this.dragEl = this.ddmInstance.dragCurrent;
60266             
60267             this.refreshCache();
60268         }
60269
60270         var xy = e.getXY(),
60271             pt = e.getPoint(),
60272             proc = this.proc,
60273             els = this.els;
60274
60275         for (var id in els) {
60276             var el = els[id], r = el._region;
60277             var c = el.ddScrollConfig ? el.ddScrollConfig : this;
60278             if (r && r.contains(pt) && el.isScrollable()) {
60279                 if (r.bottom - pt.y <= c.vthresh) {
60280                     if(proc.el != el){
60281                         this.startProc(el, "down");
60282                     }
60283                     return;
60284                 }else if (r.right - pt.x <= c.hthresh) {
60285                     if (proc.el != el) {
60286                         this.startProc(el, "left");
60287                     }
60288                     return;
60289                 } else if(pt.y - r.top <= c.vthresh) {
60290                     if (proc.el != el) {
60291                         this.startProc(el, "up");
60292                     }
60293                     return;
60294                 } else if(pt.x - r.left <= c.hthresh) {
60295                     if (proc.el != el) {
60296                         this.startProc(el, "right");
60297                     }
60298                     return;
60299                 }
60300             }
60301         }
60302         this.clearProc();
60303     },
60304
60305     
60306     register : function(el){
60307         if (Ext.isArray(el)) {
60308             for(var i = 0, len = el.length; i < len; i++) {
60309                     this.register(el[i]);
60310             }
60311         } else {
60312             el = Ext.get(el);
60313             this.els[el.id] = el;
60314         }
60315     },
60316
60317     
60318     unregister : function(el){
60319         if(Ext.isArray(el)){
60320             for (var i = 0, len = el.length; i < len; i++) {
60321                 this.unregister(el[i]);
60322             }
60323         }else{
60324             el = Ext.get(el);
60325             delete this.els[el.id];
60326         }
60327     },
60328
60329     
60330     vthresh : 25,
60331     
60332     hthresh : 25,
60333
60334     
60335     increment : 100,
60336
60337     
60338     frequency : 500,
60339
60340     
60341     animate: true,
60342
60343     
60344     animDuration: 0.4,
60345
60346     
60347     ddGroup: undefined,
60348
60349     
60350     refreshCache : function(){
60351         var els = this.els,
60352             id;
60353         for (id in els) {
60354             if(typeof els[id] == 'object'){ 
60355                 els[id]._region = els[id].getRegion();
60356             }
60357         }
60358     }
60359 });
60360
60361
60362 Ext.define('Ext.dd.DropTarget', {
60363     extend: 'Ext.dd.DDTarget',
60364     requires: ['Ext.dd.ScrollManager'],
60365
60366     constructor : function(el, config){
60367         this.el = Ext.get(el);
60368
60369         Ext.apply(this, config);
60370
60371         if(this.containerScroll){
60372             Ext.dd.ScrollManager.register(this.el);
60373         }
60374
60375         this.callParent([this.el.dom, this.ddGroup || this.group,
60376               {isTarget: true}]);
60377     },
60378
60379     
60380     
60381     
60382     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
60383     
60384     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
60385
60386     
60387     isTarget : true,
60388
60389     
60390     isNotifyTarget : true,
60391
60392     
60393     notifyEnter : function(dd, e, data){
60394         if(this.overClass){
60395             this.el.addCls(this.overClass);
60396         }
60397         return this.dropAllowed;
60398     },
60399
60400     
60401     notifyOver : function(dd, e, data){
60402         return this.dropAllowed;
60403     },
60404
60405     
60406     notifyOut : function(dd, e, data){
60407         if(this.overClass){
60408             this.el.removeCls(this.overClass);
60409         }
60410     },
60411
60412     
60413     notifyDrop : function(dd, e, data){
60414         return false;
60415     },
60416
60417     destroy : function(){
60418         this.callParent();
60419         if(this.containerScroll){
60420             Ext.dd.ScrollManager.unregister(this.el);
60421         }
60422     }
60423 });
60424
60425
60426 Ext.define('Ext.dd.Registry', {
60427     singleton: true,
60428     constructor: function() {
60429         this.elements = {}; 
60430         this.handles = {}; 
60431         this.autoIdSeed = 0;
60432     },
60433     
60434     getId: function(el, autogen){
60435         if(typeof el == "string"){
60436             return el;
60437         }
60438         var id = el.id;
60439         if(!id && autogen !== false){
60440             id = "extdd-" + (++this.autoIdSeed);
60441             el.id = id;
60442         }
60443         return id;
60444     },
60445     
60446     
60447     register : function(el, data){
60448         data = data || {};
60449         if (typeof el == "string") {
60450             el = document.getElementById(el);
60451         }
60452         data.ddel = el;
60453         this.elements[this.getId(el)] = data;
60454         if (data.isHandle !== false) {
60455             this.handles[data.ddel.id] = data;
60456         }
60457         if (data.handles) {
60458             var hs = data.handles;
60459             for (var i = 0, len = hs.length; i < len; i++) {
60460                 this.handles[this.getId(hs[i])] = data;
60461             }
60462         }
60463     },
60464
60465     
60466     unregister : function(el){
60467         var id = this.getId(el, false);
60468         var data = this.elements[id];
60469         if(data){
60470             delete this.elements[id];
60471             if(data.handles){
60472                 var hs = data.handles;
60473                 for (var i = 0, len = hs.length; i < len; i++) {
60474                     delete this.handles[this.getId(hs[i], false)];
60475                 }
60476             }
60477         }
60478     },
60479
60480     
60481     getHandle : function(id){
60482         if(typeof id != "string"){ 
60483             id = id.id;
60484         }
60485         return this.handles[id];
60486     },
60487
60488     
60489     getHandleFromEvent : function(e){
60490         var t = e.getTarget();
60491         return t ? this.handles[t.id] : null;
60492     },
60493
60494     
60495     getTarget : function(id){
60496         if(typeof id != "string"){ 
60497             id = id.id;
60498         }
60499         return this.elements[id];
60500     },
60501
60502     
60503     getTargetFromEvent : function(e){
60504         var t = e.getTarget();
60505         return t ? this.elements[t.id] || this.handles[t.id] : null;
60506     }
60507 });
60508
60509 Ext.define('Ext.dd.DropZone', {
60510     extend: 'Ext.dd.DropTarget',
60511     requires: ['Ext.dd.Registry'],
60512
60513     
60514     getTargetFromEvent : function(e){
60515         return Ext.dd.Registry.getTargetFromEvent(e);
60516     },
60517
60518     
60519     onNodeEnter : function(n, dd, e, data){
60520         
60521     },
60522
60523     
60524     onNodeOver : function(n, dd, e, data){
60525         return this.dropAllowed;
60526     },
60527
60528     
60529     onNodeOut : function(n, dd, e, data){
60530         
60531     },
60532
60533     
60534     onNodeDrop : function(n, dd, e, data){
60535         return false;
60536     },
60537
60538     
60539     onContainerOver : function(dd, e, data){
60540         return this.dropNotAllowed;
60541     },
60542
60543     
60544     onContainerDrop : function(dd, e, data){
60545         return false;
60546     },
60547
60548     
60549     notifyEnter : function(dd, e, data){
60550         return this.dropNotAllowed;
60551     },
60552
60553     
60554     notifyOver : function(dd, e, data){
60555         var n = this.getTargetFromEvent(e);
60556         if(!n) { 
60557             if(this.lastOverNode){
60558                 this.onNodeOut(this.lastOverNode, dd, e, data);
60559                 this.lastOverNode = null;
60560             }
60561             return this.onContainerOver(dd, e, data);
60562         }
60563         if(this.lastOverNode != n){
60564             if(this.lastOverNode){
60565                 this.onNodeOut(this.lastOverNode, dd, e, data);
60566             }
60567             this.onNodeEnter(n, dd, e, data);
60568             this.lastOverNode = n;
60569         }
60570         return this.onNodeOver(n, dd, e, data);
60571     },
60572
60573     
60574     notifyOut : function(dd, e, data){
60575         if(this.lastOverNode){
60576             this.onNodeOut(this.lastOverNode, dd, e, data);
60577             this.lastOverNode = null;
60578         }
60579     },
60580
60581     
60582     notifyDrop : function(dd, e, data){
60583         if(this.lastOverNode){
60584             this.onNodeOut(this.lastOverNode, dd, e, data);
60585             this.lastOverNode = null;
60586         }
60587         var n = this.getTargetFromEvent(e);
60588         return n ?
60589             this.onNodeDrop(n, dd, e, data) :
60590             this.onContainerDrop(dd, e, data);
60591     },
60592
60593     
60594     triggerCacheRefresh : function() {
60595         Ext.dd.DDM.refreshCache(this.groups);
60596     }
60597 });
60598
60599 Ext.define('Ext.flash.Component', {
60600     extend: 'Ext.Component',
60601     alternateClassName: 'Ext.FlashComponent',
60602     alias: 'widget.flash',
60603
60604     
60605     flashVersion : '9.0.115',
60606
60607     
60608     backgroundColor: '#ffffff',
60609
60610     
60611     wmode: 'opaque',
60612
60613     
60614
60615     
60616
60617     
60618
60619     
60620
60621     
60622     swfWidth: '100%',
60623
60624     
60625     swfHeight: '100%',
60626
60627     
60628     expressInstall: false,
60629
60630     
60631
60632     
60633     renderTpl: ['<div id="{swfId}"></div>'],
60634
60635     initComponent: function() {
60636         if (!('swfobject' in window)) {
60637             Ext.Error.raise('The SWFObject library is not loaded. Ext.flash.Component requires SWFObject version 2.2 or later: http://code.google.com/p/swfobject/');
60638         }
60639         if (!this.url) {
60640             Ext.Error.raise('The "url" config is required for Ext.flash.Component');
60641         }
60642
60643         this.callParent();
60644         this.addEvents(
60645             
60646             'success',
60647
60648             
60649             'failure'
60650         );
60651     },
60652
60653     onRender: function() {
60654         var me = this,
60655             params, vars, undef,
60656             swfId = me.getSwfId();
60657
60658         me.renderData.swfId = swfId;
60659
60660         me.callParent(arguments);
60661
60662         params = Ext.apply({
60663             allowScriptAccess: 'always',
60664             bgcolor: me.backgroundColor,
60665             wmode: me.wmode
60666         }, me.flashParams);
60667
60668         vars = Ext.apply({
60669             allowedDomain: document.location.hostname
60670         }, me.flashVars);
60671
60672         new swfobject.embedSWF(
60673             me.url,
60674             swfId,
60675             me.swfWidth,
60676             me.swfHeight,
60677             me.flashVersion,
60678             me.expressInstall ? me.statics.EXPRESS_INSTALL_URL : undef,
60679             vars,
60680             params,
60681             me.flashAttributes,
60682             Ext.bind(me.swfCallback, me)
60683         );
60684     },
60685
60686     
60687     swfCallback: function(e) {
60688         var me = this;
60689         if (e.success) {
60690             me.swf = Ext.get(e.ref);
60691             me.onSuccess();
60692             me.fireEvent('success', me);
60693         } else {
60694             me.onFailure();
60695             me.fireEvent('failure', me);
60696         }
60697     },
60698
60699     
60700     getSwfId: function() {
60701         return this.swfId || (this.swfId = "extswf" + this.getAutoId());
60702     },
60703
60704     onSuccess: function() {
60705         
60706         
60707         this.swf.setStyle('visibility', 'inherit');
60708     },
60709
60710     onFailure: Ext.emptyFn,
60711
60712     beforeDestroy: function() {
60713         var me = this,
60714             swf = me.swf;
60715         if (swf) {
60716             swfobject.removeSWF(me.getSwfId());
60717             Ext.destroy(swf);
60718             delete me.swf;
60719         }
60720         me.callParent();
60721     },
60722
60723     statics: {
60724         
60725         EXPRESS_INSTALL_URL: 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf'
60726     }
60727 });
60728
60729
60730 Ext.define('Ext.form.action.Action', {
60731     alternateClassName: 'Ext.form.Action',
60732
60733     
60734
60735     
60736
60737     
60738
60739     
60740
60741     
60742
60743     
60744
60745     
60746
60747     
60748
60749     
60750
60751     
60752
60753     
60754
60755     
60756
60757     
60758
60759     
60760
60761     
60762
60763     
60764
60765     
60766
60767
60768
60769     constructor: function(config) {
60770         if (config) {
60771             Ext.apply(this, config);
60772         }
60773
60774         
60775         var params = config.params;
60776         if (Ext.isString(params)) {
60777             this.params = Ext.Object.fromQueryString(params);
60778         }
60779     },
60780
60781     
60782     run: Ext.emptyFn,
60783
60784     
60785
60786     
60787
60788     
60789     onFailure : function(response){
60790         this.response = response;
60791         this.failureType = Ext.form.action.Action.CONNECT_FAILURE;
60792         this.form.afterAction(this, false);
60793     },
60794
60795     
60796     processResponse : function(response){
60797         this.response = response;
60798         if (!response.responseText && !response.responseXML) {
60799             return true;
60800         }
60801         return (this.result = this.handleResponse(response));
60802     },
60803
60804     
60805     getUrl: function() {
60806         return this.url || this.form.url;
60807     },
60808
60809     
60810     getMethod: function() {
60811         return (this.method || this.form.method || 'POST').toUpperCase();
60812     },
60813
60814     
60815     getParams: function() {
60816         return Ext.apply({}, this.params, this.form.baseParams);
60817     },
60818
60819     
60820     createCallback: function() {
60821         var me = this,
60822             undef,
60823             form = me.form;
60824         return {
60825             success: me.onSuccess,
60826             failure: me.onFailure,
60827             scope: me,
60828             timeout: (this.timeout * 1000) || (form.timeout * 1000),
60829             upload: form.fileUpload ? me.onSuccess : undef
60830         };
60831     },
60832
60833     statics: {
60834         
60835         CLIENT_INVALID: 'client',
60836
60837         
60838         SERVER_INVALID: 'server',
60839
60840         
60841         CONNECT_FAILURE: 'connect',
60842
60843         
60844         LOAD_FAILURE: 'load'
60845
60846
60847     }
60848 });
60849
60850
60851 Ext.define('Ext.form.action.Submit', {
60852     extend:'Ext.form.action.Action',
60853     alternateClassName: 'Ext.form.Action.Submit',
60854     alias: 'formaction.submit',
60855
60856     type: 'submit',
60857
60858     
60859
60860     
60861     run : function(){
60862         var form = this.form;
60863         if (this.clientValidation === false || form.isValid()) {
60864             this.doSubmit();
60865         } else {
60866             
60867             this.failureType = Ext.form.action.Action.CLIENT_INVALID;
60868             form.afterAction(this, false);
60869         }
60870     },
60871
60872     
60873     doSubmit: function() {
60874         var formEl,
60875             ajaxOptions = Ext.apply(this.createCallback(), {
60876                 url: this.getUrl(),
60877                 method: this.getMethod(),
60878                 headers: this.headers
60879             });
60880
60881         
60882         
60883         if (this.form.hasUpload()) {
60884             formEl = ajaxOptions.form = this.buildForm();
60885             ajaxOptions.isUpload = true;
60886         } else {
60887             ajaxOptions.params = this.getParams();
60888         }
60889
60890         Ext.Ajax.request(ajaxOptions);
60891
60892         if (formEl) {
60893             Ext.removeNode(formEl);
60894         }
60895     },
60896
60897     
60898     getParams: function() {
60899         var nope = false,
60900             configParams = this.callParent(),
60901             fieldParams = this.form.getValues(nope, nope, this.submitEmptyText !== nope);
60902         return Ext.apply({}, fieldParams, configParams);
60903     },
60904
60905     
60906     buildForm: function() {
60907         var fieldsSpec = [],
60908             formSpec,
60909             formEl,
60910             basicForm = this.form,
60911             params = this.getParams(),
60912             uploadFields = [];
60913
60914         basicForm.getFields().each(function(field) {
60915             if (field.isFileUpload()) {
60916                 uploadFields.push(field);
60917             }
60918         });
60919
60920         function addField(name, val) {
60921             fieldsSpec.push({
60922                 tag: 'input',
60923                 type: 'hidden',
60924                 name: name,
60925                 value: val
60926             });
60927         }
60928
60929         
60930         Ext.iterate(params, function(key, val) {
60931             if (Ext.isArray(val)) {
60932                 Ext.each(val, function(v) {
60933                     addField(key, v);
60934                 });
60935             } else {
60936                 addField(key, val);
60937             }
60938         });
60939
60940         formSpec = {
60941             tag: 'form',
60942             action: this.getUrl(),
60943             method: this.getMethod(),
60944             target: this.target || '_self',
60945             style: 'display:none',
60946             cn: fieldsSpec
60947         };
60948
60949         
60950         if (uploadFields.length) {
60951             formSpec.encoding = formSpec.enctype = 'multipart/form-data';
60952         }
60953
60954         
60955         formEl = Ext.core.DomHelper.append(Ext.getBody(), formSpec);
60956
60957         
60958         
60959         
60960         Ext.Array.each(uploadFields, function(field) {
60961             if (field.rendered) { 
60962                 formEl.appendChild(field.extractFileInput());
60963             }
60964         });
60965
60966         return formEl;
60967     },
60968
60969
60970
60971     
60972     onSuccess: function(response) {
60973         var form = this.form,
60974             success = true,
60975             result = this.processResponse(response);
60976         if (result !== true && !result.success) {
60977             if (result.errors) {
60978                 form.markInvalid(result.errors);
60979             }
60980             this.failureType = Ext.form.action.Action.SERVER_INVALID;
60981             success = false;
60982         }
60983         form.afterAction(this, success);
60984     },
60985
60986     
60987     handleResponse: function(response) {
60988         var form = this.form,
60989             errorReader = form.errorReader,
60990             rs, errors, i, len, records;
60991         if (errorReader) {
60992             rs = errorReader.read(response);
60993             records = rs.records;
60994             errors = [];
60995             if (records) {
60996                 for(i = 0, len = records.length; i < len; i++) {
60997                     errors[i] = records[i].data;
60998                 }
60999             }
61000             if (errors.length < 1) {
61001                 errors = null;
61002             }
61003             return {
61004                 success : rs.success,
61005                 errors : errors
61006             };
61007         }
61008         return Ext.decode(response.responseText);
61009     }
61010 });
61011
61012
61013 Ext.define('Ext.util.ComponentDragger', {
61014
61015     
61016
61017     
61018
61019     
61020
61021     extend: 'Ext.dd.DragTracker',
61022
61023     autoStart: 500,
61024
61025     constructor: function(comp, config) {
61026         this.comp = comp;
61027         this.initialConstrainTo = config.constrainTo;
61028         this.callParent([ config ]);
61029     },
61030
61031     onStart: function(e) {
61032         var me = this,
61033             comp = me.comp;
61034
61035         
61036         this.startPosition = comp.getPosition();
61037
61038         
61039         
61040         if (comp.ghost && !comp.liveDrag) {
61041              me.proxy = comp.ghost();
61042              me.dragTarget = me.proxy.header.el;
61043         }
61044
61045         
61046         if (me.constrain || me.constrainDelegate) {
61047             me.constrainTo = me.calculateConstrainRegion();
61048         }
61049     },
61050
61051     calculateConstrainRegion: function() {
61052         var me = this,
61053             comp = me.comp,
61054             c = me.initialConstrainTo,
61055             delegateRegion,
61056             elRegion,
61057             shadowSize = comp.el.shadow ? comp.el.shadow.offset : 0;
61058
61059         
61060         if (!(c instanceof Ext.util.Region)) {
61061             c =  Ext.fly(c).getViewRegion();
61062         }
61063
61064         
61065         if (shadowSize) {
61066             c.adjust(0, -shadowSize, -shadowSize, shadowSize);
61067         }
61068
61069         
61070         
61071         
61072         if (!me.constrainDelegate) {
61073             delegateRegion = Ext.fly(me.dragTarget).getRegion();
61074             elRegion = me.proxy ? me.proxy.el.getRegion() : comp.el.getRegion();
61075
61076             c.adjust(
61077                 delegateRegion.top - elRegion.top,
61078                 delegateRegion.right - elRegion.right,
61079                 delegateRegion.bottom - elRegion.bottom,
61080                 delegateRegion.left - elRegion.left
61081             );
61082         }
61083         return c;
61084     },
61085
61086     
61087     onDrag: function(e) {
61088         var me = this,
61089             comp = (me.proxy && !me.comp.liveDrag) ? me.proxy : me.comp,
61090             offset = me.getOffset(me.constrain || me.constrainDelegate ? 'dragTarget' : null);
61091
61092         comp.setPosition.apply(comp, [me.startPosition[0] + offset[0], me.startPosition[1] + offset[1]]);
61093     },
61094
61095     onEnd: function(e) {
61096         if (this.proxy && !this.comp.liveDrag) {
61097             this.comp.unghost();
61098         }
61099     }
61100 });
61101
61102 Ext.define("Ext.form.Labelable", {
61103     requires: ['Ext.XTemplate'],
61104
61105     
61106     labelableRenderTpl: [
61107         '<tpl if="!hideLabel && !(!fieldLabel && hideEmptyLabel)">',
61108             '<label<tpl if="inputId"> for="{inputId}"</tpl> class="{labelCls}"<tpl if="labelStyle"> style="{labelStyle}"</tpl>>',
61109                 '<tpl if="fieldLabel">{fieldLabel}{labelSeparator}</tpl>',
61110             '</label>',
61111         '</tpl>',
61112         '<div class="{baseBodyCls} {fieldBodyCls}"<tpl if="inputId"> id="{baseBodyCls}-{inputId}"</tpl> role="presentation">{subTplMarkup}</div>',
61113         '<div class="{errorMsgCls}" style="display:none"></div>',
61114         '<div class="{clearCls}" role="presentation"><!-- --></div>',
61115         {
61116             compiled: true,
61117             disableFormats: true
61118         }
61119     ],
61120
61121     
61122     activeErrorsTpl: [
61123         '<tpl if="errors && errors.length">',
61124             '<ul><tpl for="errors"><li<tpl if="xindex == xcount"> class="last"</tpl>>{.}</li></tpl></ul>',
61125         '</tpl>'
61126     ],
61127
61128     
61129     isFieldLabelable: true,
61130
61131     
61132     formItemCls: Ext.baseCSSPrefix + 'form-item',
61133
61134     
61135     labelCls: Ext.baseCSSPrefix + 'form-item-label',
61136
61137     
61138     errorMsgCls: Ext.baseCSSPrefix + 'form-error-msg',
61139
61140     
61141     baseBodyCls: Ext.baseCSSPrefix + 'form-item-body',
61142
61143     
61144     fieldBodyCls: '',
61145
61146     
61147     clearCls: Ext.baseCSSPrefix + 'clear',
61148
61149     
61150     invalidCls : Ext.baseCSSPrefix + 'form-invalid',
61151
61152     
61153     fieldLabel: undefined,
61154
61155     
61156     labelAlign : 'left',
61157
61158     
61159     labelWidth: 100,
61160
61161     
61162     labelPad : 5,
61163
61164     
61165     labelSeparator : ':',
61166
61167     
61168
61169     
61170     hideLabel: false,
61171
61172     
61173     hideEmptyLabel: true,
61174
61175     
61176     preventMark: false,
61177
61178     
61179     autoFitErrors: true,
61180
61181     
61182     msgTarget: 'qtip',
61183
61184     
61185
61186
61187     
61188     initLabelable: function() {
61189         this.addCls(this.formItemCls);
61190
61191         this.addEvents(
61192             
61193             'errorchange'
61194         );
61195     },
61196
61197     
61198     getFieldLabel: function() {
61199         return this.fieldLabel || '';
61200     },
61201
61202     
61203     getLabelableRenderData: function() {
61204         var me = this,
61205             labelAlign = me.labelAlign,
61206             labelPad = me.labelPad,
61207             labelStyle;
61208
61209         
61210         
61211         if (labelAlign === 'top') {
61212             labelStyle = 'margin-bottom:' + labelPad + 'px;';
61213         } else {
61214             labelStyle = 'margin-right:' + labelPad + 'px;';
61215             
61216             if (Ext.isBorderBox) {
61217                 labelStyle += 'width:' + me.labelWidth + 'px;';
61218             }
61219         }
61220
61221         return Ext.copyTo(
61222             {
61223                 inputId: me.getInputId(),
61224                 fieldLabel: me.getFieldLabel(),
61225                 labelStyle: labelStyle + (me.labelStyle || ''),
61226                 subTplMarkup: me.getSubTplMarkup()
61227             },
61228             me,
61229             'hideLabel,hideEmptyLabel,labelCls,fieldBodyCls,baseBodyCls,errorMsgCls,clearCls,labelSeparator',
61230             true
61231         );
61232     },
61233
61234     
61235     getLabelableSelectors: function() {
61236         return {
61237             
61238             labelEl: 'label.' + this.labelCls,
61239
61240             
61241             bodyEl: '.' + this.baseBodyCls,
61242
61243             
61244             errorEl: '.' + this.errorMsgCls
61245         };
61246     },
61247
61248     
61249     getSubTplMarkup: function() {
61250         return '';
61251     },
61252
61253     
61254     getInputId: function() {
61255         return '';
61256     },
61257
61258     
61259     getActiveError : function() {
61260         return this.activeError || '';
61261     },
61262
61263     
61264     hasActiveError: function() {
61265         return !!this.getActiveError();
61266     },
61267
61268     
61269     setActiveError: function(msg) {
61270         this.activeError = msg;
61271         this.activeErrors = [msg];
61272         this.renderActiveError();
61273     },
61274
61275     
61276     getActiveErrors: function() {
61277         return this.activeErrors || [];
61278     },
61279
61280     
61281     setActiveErrors: function(errors) {
61282         this.activeErrors = errors;
61283         this.activeError = this.getTpl('activeErrorsTpl').apply({errors: errors});
61284         this.renderActiveError();
61285     },
61286
61287     
61288     unsetActiveError: function() {
61289         delete this.activeError;
61290         delete this.activeErrors;
61291         this.renderActiveError();
61292     },
61293
61294     
61295     renderActiveError: function() {
61296         var me = this,
61297             activeError = me.getActiveError(),
61298             hasError = !!activeError;
61299
61300         if (activeError !== me.lastActiveError) {
61301             me.fireEvent('errorchange', me, activeError);
61302             me.lastActiveError = activeError;
61303         }
61304
61305         if (me.rendered && !me.isDestroyed && !me.preventMark) {
61306             
61307             me.el[hasError ? 'addCls' : 'removeCls'](me.invalidCls);
61308
61309             
61310             me.getActionEl().dom.setAttribute('aria-invalid', hasError);
61311
61312             
61313             me.errorEl.dom.innerHTML = activeError;
61314         }
61315     },
61316
61317     
61318     setFieldDefaults: function(defaults) {
61319         var me = this;
61320         Ext.iterate(defaults, function(key, val) {
61321             if (!me.hasOwnProperty(key)) {
61322                 me[key] = val;
61323             }
61324         });
61325     },
61326
61327     
61328     getBodyNaturalWidth: function() {
61329         return this.bodyEl.getWidth();
61330     }
61331
61332 });
61333
61334
61335 Ext.define('Ext.form.field.Field', {
61336
61337     
61338     isFormField : true,
61339
61340     
61341     
61342     
61343
61344     
61345     disabled : false,
61346
61347     
61348     submitValue: true,
61349
61350     
61351     validateOnChange: true,
61352
61353     
61354     suspendCheckChange: 0,
61355
61356     
61357     initField: function() {
61358         this.addEvents(
61359             
61360             'change',
61361             
61362             'validitychange',
61363             
61364             'dirtychange'
61365         );
61366
61367         this.initValue();
61368     },
61369
61370     
61371     initValue: function() {
61372         var me = this;
61373
61374         
61375         me.originalValue = me.lastValue = me.value;
61376
61377         
61378         me.suspendCheckChange++;
61379         me.setValue(me.value);
61380         me.suspendCheckChange--;
61381     },
61382
61383     
61384     getName: function() {
61385         return this.name;
61386     },
61387
61388     
61389     getValue: function() {
61390         return this.value;
61391     },
61392     
61393     
61394     setValue: function(value) {
61395         var me = this;
61396         me.value = value;
61397         me.checkChange();
61398         return me;
61399     },
61400
61401     
61402     isEqual: function(value1, value2) {
61403         return String(value1) === String(value2);
61404     },
61405
61406     
61407     getSubmitData: function() {
61408         var me = this,
61409             data = null;
61410         if (!me.disabled && me.submitValue && !me.isFileUpload()) {
61411             data = {};
61412             data[me.getName()] = '' + me.getValue();
61413         }
61414         return data;
61415     },
61416
61417     
61418     getModelData: function() {
61419         var me = this,
61420             data = null;
61421         if (!me.disabled && !me.isFileUpload()) {
61422             data = {};
61423             data[me.getName()] = me.getValue();
61424         }
61425         return data;
61426     },
61427
61428     
61429     reset : function(){
61430         var me = this;
61431         
61432         me.setValue(me.originalValue);
61433         me.clearInvalid();
61434         
61435         delete me.wasValid;
61436     },
61437
61438     
61439     resetOriginalValue: function() {
61440         this.originalValue = this.getValue();
61441         this.checkDirty();
61442     },
61443
61444     
61445     checkChange: function() {
61446         if (!this.suspendCheckChange) {
61447             var me = this,
61448                 newVal = me.getValue(),
61449                 oldVal = me.lastValue;
61450             if (!me.isEqual(newVal, oldVal) && !me.isDestroyed) {
61451                 me.lastValue = newVal;
61452                 me.fireEvent('change', me, newVal, oldVal);
61453                 me.onChange(newVal, oldVal);
61454             }
61455         }
61456     },
61457
61458     
61459     onChange: function(newVal, oldVal) {
61460         if (this.validateOnChange) {
61461             this.validate();
61462         }
61463         this.checkDirty();
61464     },
61465
61466     
61467     isDirty : function() {
61468         var me = this;
61469         return !me.disabled && !me.isEqual(me.getValue(), me.originalValue);
61470     },
61471
61472     
61473     checkDirty: function() {
61474         var me = this,
61475             isDirty = me.isDirty();
61476         if (isDirty !== me.wasDirty) {
61477             me.fireEvent('dirtychange', me, isDirty);
61478             me.onDirtyChange(isDirty);
61479             me.wasDirty = isDirty;
61480         }
61481     },
61482
61483     
61484     onDirtyChange: Ext.emptyFn,
61485
61486     
61487     getErrors: function(value) {
61488         return [];
61489     },
61490
61491     
61492     isValid : function() {
61493         var me = this;
61494         return me.disabled || Ext.isEmpty(me.getErrors());
61495     },
61496
61497     
61498     validate : function() {
61499         var me = this,
61500             isValid = me.isValid();
61501         if (isValid !== me.wasValid) {
61502             me.wasValid = isValid;
61503             me.fireEvent('validitychange', me, isValid);
61504         }
61505         return isValid;
61506     },
61507
61508     
61509     batchChanges: function(fn) {
61510         this.suspendCheckChange++;
61511         fn();
61512         this.suspendCheckChange--;
61513         this.checkChange();
61514     },
61515
61516     
61517     isFileUpload: function() {
61518         return false;
61519     },
61520
61521     
61522     extractFileInput: function() {
61523         return null;
61524     },
61525
61526     
61527     markInvalid: Ext.emptyFn,
61528
61529     
61530     clearInvalid: Ext.emptyFn
61531
61532 });
61533
61534
61535 Ext.define('Ext.layout.component.field.Field', {
61536
61537     
61538
61539     alias: ['layout.field'],
61540
61541     extend: 'Ext.layout.component.Component',
61542
61543     uses: ['Ext.tip.QuickTip', 'Ext.util.TextMetrics'],
61544
61545     
61546
61547     type: 'field',
61548
61549     beforeLayout: function(width, height) {
61550         var me = this;
61551         return me.callParent(arguments) || (!me.owner.preventMark && me.activeError !== me.owner.getActiveError());
61552     },
61553
61554     onLayout: function(width, height) {
61555         var me = this,
61556             owner = me.owner,
61557             labelStrategy = me.getLabelStrategy(),
61558             errorStrategy = me.getErrorStrategy(),
61559             isDefined = Ext.isDefined,
61560             isNumber = Ext.isNumber,
61561             lastSize, autoWidth, autoHeight, info, undef;
61562
61563         lastSize = me.lastComponentSize || {};
61564         if (!isDefined(width)) {
61565             width = lastSize.width;
61566             if (width < 0) { 
61567                 width = undef;
61568             }
61569         }
61570         if (!isDefined(height)) {
61571             height = lastSize.height;
61572             if (height < 0) { 
61573                 height = undef;
61574             }
61575         }
61576         autoWidth = !isNumber(width);
61577         autoHeight = !isNumber(height);
61578
61579         info = {
61580             autoWidth: autoWidth,
61581             autoHeight: autoHeight,
61582             width: autoWidth ? owner.getBodyNaturalWidth() : width, 
61583             height: height,
61584
61585             
61586             insets: {
61587                 top: 0,
61588                 right: 0,
61589                 bottom: 0,
61590                 left: 0
61591             }
61592         };
61593
61594         
61595         
61596         
61597
61598         
61599         labelStrategy.prepare(owner, info);
61600         errorStrategy.prepare(owner, info);
61601
61602         
61603         labelStrategy.adjustHorizInsets(owner, info);
61604         errorStrategy.adjustHorizInsets(owner, info);
61605
61606         
61607         labelStrategy.layoutHoriz(owner, info);
61608         errorStrategy.layoutHoriz(owner, info);
61609
61610         
61611         labelStrategy.adjustVertInsets(owner, info);
61612         errorStrategy.adjustVertInsets(owner, info);
61613
61614         
61615         labelStrategy.layoutVert(owner, info);
61616         errorStrategy.layoutVert(owner, info);
61617
61618         
61619         if (autoWidth && autoHeight) {
61620             
61621             me.setElementSize(owner.el, info.width, info.height);
61622         } else {
61623             me.setTargetSize(info.width, info.height);
61624         }
61625         me.sizeBody(info);
61626
61627         me.activeError = owner.getActiveError();
61628     },
61629
61630
61631     
61632     sizeBody: function(info) {
61633         var me = this,
61634             owner = me.owner,
61635             insets = info.insets,
61636             totalWidth = info.width,
61637             totalHeight = info.height,
61638             width = Ext.isNumber(totalWidth) ? totalWidth - insets.left - insets.right : totalWidth,
61639             height = Ext.isNumber(totalHeight) ? totalHeight - insets.top - insets.bottom : totalHeight;
61640
61641         
61642         me.setElementSize(owner.bodyEl, width, height);
61643
61644         
61645         me.sizeBodyContents(width, height);
61646     },
61647
61648     
61649     sizeBodyContents: Ext.emptyFn,
61650
61651
61652     
61653     getLabelStrategy: function() {
61654         var me = this,
61655             strategies = me.labelStrategies,
61656             labelAlign = me.owner.labelAlign;
61657         return strategies[labelAlign] || strategies.base;
61658     },
61659
61660     
61661     getErrorStrategy: function() {
61662         var me = this,
61663             owner = me.owner,
61664             strategies = me.errorStrategies,
61665             msgTarget = owner.msgTarget;
61666         return !owner.preventMark && Ext.isString(msgTarget) ?
61667                 (strategies[msgTarget] || strategies.elementId) :
61668                 strategies.none;
61669     },
61670
61671
61672
61673     
61674     labelStrategies: (function() {
61675         var applyIf = Ext.applyIf,
61676             emptyFn = Ext.emptyFn,
61677             base = {
61678                 prepare: function(owner, info) {
61679                     var cls = owner.labelCls + '-' + owner.labelAlign,
61680                         labelEl = owner.labelEl;
61681                     if (labelEl && !labelEl.hasCls(cls)) {
61682                         labelEl.addCls(cls);
61683                     }
61684                 },
61685                 adjustHorizInsets: emptyFn,
61686                 adjustVertInsets: emptyFn,
61687                 layoutHoriz: emptyFn,
61688                 layoutVert: emptyFn
61689             },
61690             left = applyIf({
61691                 prepare: function(owner, info) {
61692                     base.prepare(owner, info);
61693                     
61694                     if (info.autoWidth) {
61695                         info.width += (!owner.labelEl ? 0 : owner.labelWidth + owner.labelPad);
61696                     }
61697                 },
61698                 adjustHorizInsets: function(owner, info) {
61699                     if (owner.labelEl) {
61700                         info.insets.left += owner.labelWidth + owner.labelPad;
61701                     }
61702                 },
61703                 layoutHoriz: function(owner, info) {
61704                     
61705                     
61706                     
61707                     
61708                     
61709                     var labelEl = owner.labelEl;
61710                     if (labelEl && !owner.isLabelSized && !Ext.isBorderBox) {
61711                         labelEl.setWidth(owner.labelWidth);
61712                         owner.isLabelSized = true;
61713                     }
61714                 }
61715             }, base);
61716
61717
61718         return {
61719             base: base,
61720
61721             
61722             top: applyIf({
61723                 adjustVertInsets: function(owner, info) {
61724                     var labelEl = owner.labelEl;
61725                     if (labelEl) {
61726                         info.insets.top += Ext.util.TextMetrics.measure(labelEl, owner.fieldLabel, info.width).height +
61727                                            labelEl.getFrameWidth('tb') + owner.labelPad;
61728                     }
61729                 }
61730             }, base),
61731
61732             
61733             left: left,
61734
61735             
61736             right: left
61737         };
61738     })(),
61739
61740
61741
61742     
61743     errorStrategies: (function() {
61744         function setDisplayed(el, displayed) {
61745             var wasDisplayed = el.getStyle('display') !== 'none';
61746             if (displayed !== wasDisplayed) {
61747                 el.setDisplayed(displayed);
61748             }
61749         }
61750
61751         function setStyle(el, name, value) {
61752             if (el.getStyle(name) !== value) {
61753                 el.setStyle(name, value);
61754             }
61755         }
61756
61757         var applyIf = Ext.applyIf,
61758             emptyFn = Ext.emptyFn,
61759             base = {
61760                 prepare: function(owner) {
61761                     setDisplayed(owner.errorEl, false);
61762                 },
61763                 adjustHorizInsets: emptyFn,
61764                 adjustVertInsets: emptyFn,
61765                 layoutHoriz: emptyFn,
61766                 layoutVert: emptyFn
61767             };
61768
61769         return {
61770             none: base,
61771
61772             
61773             side: applyIf({
61774                 prepare: function(owner) {
61775                     var errorEl = owner.errorEl;
61776                     errorEl.addCls(Ext.baseCSSPrefix + 'form-invalid-icon');
61777                     Ext.layout.component.field.Field.initTip();
61778                     errorEl.dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
61779                     setDisplayed(errorEl, owner.hasActiveError());
61780                 },
61781                 adjustHorizInsets: function(owner, info) {
61782                     if (owner.autoFitErrors && owner.hasActiveError()) {
61783                         info.insets.right += owner.errorEl.getWidth();
61784                     }
61785                 },
61786                 layoutHoriz: function(owner, info) {
61787                     if (owner.hasActiveError()) {
61788                         setStyle(owner.errorEl, 'left', info.width - info.insets.right + 'px');
61789                     }
61790                 },
61791                 layoutVert: function(owner, info) {
61792                     if (owner.hasActiveError()) {
61793                         setStyle(owner.errorEl, 'top', info.insets.top + 'px');
61794                     }
61795                 }
61796             }, base),
61797
61798             
61799             under: applyIf({
61800                 prepare: function(owner) {
61801                     var errorEl = owner.errorEl,
61802                         cls = Ext.baseCSSPrefix + 'form-invalid-under';
61803                     if (!errorEl.hasCls(cls)) {
61804                         errorEl.addCls(cls);
61805                     }
61806                     setDisplayed(errorEl, owner.hasActiveError());
61807                 },
61808                 adjustVertInsets: function(owner, info) {
61809                     if (owner.autoFitErrors) {
61810                         info.insets.bottom += owner.errorEl.getHeight();
61811                     }
61812                 },
61813                 layoutHoriz: function(owner, info) {
61814                     var errorEl = owner.errorEl,
61815                         insets = info.insets;
61816
61817                     setStyle(errorEl, 'width', info.width - insets.right - insets.left + 'px');
61818                     setStyle(errorEl, 'marginLeft', insets.left + 'px');
61819                 }
61820             }, base),
61821
61822             
61823             qtip: applyIf({
61824                 prepare: function(owner) {
61825                     setDisplayed(owner.errorEl, false);
61826                     Ext.layout.component.field.Field.initTip();
61827                     owner.getActionEl().dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
61828                 }
61829             }, base),
61830
61831             
61832             title: applyIf({
61833                 prepare: function(owner) {
61834                     setDisplayed(owner.errorEl, false);
61835                     owner.el.dom.title = owner.getActiveError() || '';
61836                 }
61837             }, base),
61838
61839             
61840             elementId: applyIf({
61841                 prepare: function(owner) {
61842                     setDisplayed(owner.errorEl, false);
61843                     var targetEl = Ext.fly(owner.msgTarget);
61844                     if (targetEl) {
61845                         targetEl.dom.innerHTML = owner.getActiveError() || '';
61846                         targetEl.setDisplayed(owner.hasActiveError());
61847                     }
61848                 }
61849             }, base)
61850         };
61851     })(),
61852
61853     statics: {
61854         
61855         initTip: function() {
61856             var tip = this.tip;
61857             if (!tip) {
61858                 tip = this.tip = Ext.create('Ext.tip.QuickTip', {
61859                     baseCls: Ext.baseCSSPrefix + 'form-invalid-tip',
61860                     renderTo: Ext.getBody()
61861                 });
61862                 tip.tagConfig = Ext.apply({}, {attribute: 'errorqtip'}, tip.tagConfig);
61863             }
61864         },
61865
61866         
61867         destroyTip: function() {
61868             var tip = this.tip;
61869             if (tip) {
61870                 tip.destroy();
61871                 delete this.tip;
61872             }
61873         }
61874     }
61875
61876 });
61877
61878
61879 Ext.define('Ext.form.field.VTypes', (function(){
61880     
61881     var alpha = /^[a-zA-Z_]+$/,
61882         alphanum = /^[a-zA-Z0-9_]+$/,
61883         email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
61884         url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
61885
61886     
61887     return {
61888         singleton: true,
61889         alternateClassName: 'Ext.form.VTypes',
61890
61891         
61892         'email' : function(v){
61893             return email.test(v);
61894         },
61895         
61896         'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
61897         
61898         'emailMask' : /[a-z0-9_\.\-@\+]/i,
61899
61900         
61901         'url' : function(v){
61902             return url.test(v);
61903         },
61904         
61905         'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
61906
61907         
61908         'alpha' : function(v){
61909             return alpha.test(v);
61910         },
61911         
61912         'alphaText' : 'This field should only contain letters and _',
61913         
61914         'alphaMask' : /[a-z_]/i,
61915
61916         
61917         'alphanum' : function(v){
61918             return alphanum.test(v);
61919         },
61920         
61921         'alphanumText' : 'This field should only contain letters, numbers and _',
61922         
61923         'alphanumMask' : /[a-z0-9_]/i
61924     };
61925 })());
61926
61927
61928 Ext.define('Ext.layout.component.field.Text', {
61929     extend: 'Ext.layout.component.field.Field',
61930     alias: 'layout.textfield',
61931     requires: ['Ext.util.TextMetrics'],
61932
61933     type: 'textfield',
61934
61935
61936     
61937     beforeLayout: function(width, height) {
61938         var me = this,
61939             owner = me.owner,
61940             lastValue = this.lastValue,
61941             value = owner.getRawValue();
61942         this.lastValue = value;
61943         return me.callParent(arguments) || (owner.grow && value !== lastValue);
61944     },
61945
61946
61947     
61948     sizeBodyContents: function(width, height) {
61949         var size = this.adjustForGrow(width, height);
61950         this.setElementSize(this.owner.inputEl, size[0], size[1]);
61951     },
61952
61953
61954     
61955     adjustForGrow: function(width, height) {
61956         var me = this,
61957             owner = me.owner,
61958             inputEl, value, calcWidth,
61959             result = [width, height];
61960
61961         if (owner.grow) {
61962             inputEl = owner.inputEl;
61963
61964             
61965             value = (inputEl.dom.value || (owner.hasFocus ? '' : owner.emptyText) || '') + owner.growAppend;
61966             calcWidth = inputEl.getTextWidth(value) + inputEl.getBorderWidth("lr") + inputEl.getPadding("lr");
61967
61968             
61969             result[0] = Ext.Number.constrain(calcWidth, owner.growMin,
61970                     Math.max(owner.growMin, Math.min(owner.growMax, Ext.isNumber(width) ? width : Infinity)));
61971         }
61972
61973         return result;
61974     }
61975
61976 });
61977
61978
61979 Ext.define('Ext.layout.component.field.TextArea', {
61980     extend: 'Ext.layout.component.field.Text',
61981     alias: 'layout.textareafield',
61982
61983     type: 'textareafield',
61984
61985
61986     
61987     adjustForGrow: function(width, height) {
61988         var me = this,
61989             owner = me.owner,
61990             inputEl, value, max,
61991             curWidth, curHeight, calcHeight,
61992             result = [width, height];
61993
61994         if (owner.grow) {
61995             inputEl = owner.inputEl;
61996             curWidth = inputEl.getWidth(true); 
61997             curHeight = inputEl.getHeight();
61998
61999             
62000             value = inputEl.dom.value || '&#160;';
62001             value += owner.growAppend;
62002
62003             
62004             value = value.replace(/\n/g, '<br>');
62005
62006             
62007             calcHeight = Ext.util.TextMetrics.measure(inputEl, value, curWidth).height +
62008                          inputEl.getBorderWidth("tb") + inputEl.getPadding("tb");
62009
62010             
62011             max = owner.growMax;
62012             if (Ext.isNumber(height)) {
62013                 max = Math.min(max, height);
62014             }
62015             result[1] = Ext.Number.constrain(calcHeight, owner.growMin, max);
62016         }
62017
62018         return result;
62019     }
62020
62021 });
62022
62023
62024 Ext.define('Ext.layout.container.Anchor', {
62025
62026     
62027
62028     alias: 'layout.anchor',
62029     extend: 'Ext.layout.container.Container',
62030     alternateClassName: 'Ext.layout.AnchorLayout',
62031
62032     
62033
62034     
62035
62036     type: 'anchor',
62037
62038     
62039     defaultAnchor: '100%',
62040
62041     parseAnchorRE: /^(r|right|b|bottom)$/i,
62042
62043     
62044     onLayout: function() {
62045         this.callParent(arguments);
62046
62047         var me = this,
62048             size = me.getLayoutTargetSize(),
62049             owner = me.owner,
62050             target = me.getTarget(),
62051             ownerWidth = size.width,
62052             ownerHeight = size.height,
62053             overflow = target.getStyle('overflow'),
62054             components = me.getVisibleItems(owner),
62055             len = components.length,
62056             boxes = [],
62057             box, newTargetSize, anchorWidth, anchorHeight, component, anchorSpec, calcWidth, calcHeight,
62058             anchorsArray, anchor, i, el;
62059
62060         if (ownerWidth < 20 && ownerHeight < 20) {
62061             return;
62062         }
62063
62064         
62065         
62066         
62067         if (!me.clearEl) {
62068             me.clearEl = target.createChild({
62069                 cls: Ext.baseCSSPrefix + 'clear',
62070                 role: 'presentation'
62071             });
62072         }
62073
62074         
62075         if (owner.anchorSize) {
62076             if (typeof owner.anchorSize == 'number') {
62077                 anchorWidth = owner.anchorSize;
62078             }
62079             else {
62080                 anchorWidth = owner.anchorSize.width;
62081                 anchorHeight = owner.anchorSize.height;
62082             }
62083         }
62084         else {
62085             anchorWidth = owner.initialConfig.width;
62086             anchorHeight = owner.initialConfig.height;
62087         }
62088
62089         
62090         if (!Ext.supports.RightMargin) {
62091             target.addCls(Ext.baseCSSPrefix + 'inline-children');
62092         }
62093
62094         for (i = 0; i < len; i++) {
62095             component = components[i];
62096             el = component.el;
62097             anchor = component.anchor;
62098
62099             if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict)) {
62100                 component.anchor = anchor = me.defaultAnchor;
62101             }
62102
62103             if (anchor) {
62104                 anchorSpec = component.anchorSpec;
62105                 
62106                 if (!anchorSpec) {
62107                     anchorsArray = anchor.split(' ');
62108                     component.anchorSpec = anchorSpec = {
62109                         right: me.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
62110                         bottom: me.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
62111                     };
62112                 }
62113                 calcWidth = anchorSpec.right ? me.adjustWidthAnchor(anchorSpec.right(ownerWidth) - el.getMargin('lr'), component) : undefined;
62114                 calcHeight = anchorSpec.bottom ? me.adjustHeightAnchor(anchorSpec.bottom(ownerHeight) - el.getMargin('tb'), component) : undefined;
62115
62116                 boxes.push({
62117                     component: component,
62118                     anchor: true,
62119                     width: calcWidth || undefined,
62120                     height: calcHeight || undefined
62121                 });
62122             } else {
62123                 boxes.push({
62124                     component: component,
62125                     anchor: false
62126                 });
62127             }
62128         }
62129
62130         
62131         if (!Ext.supports.RightMargin) {
62132             target.removeCls(Ext.baseCSSPrefix + 'inline-children');
62133         }
62134
62135         for (i = 0; i < len; i++) {
62136             box = boxes[i];
62137             me.setItemSize(box.component, box.width, box.height);
62138         }
62139
62140         if (overflow && overflow != 'hidden' && !me.adjustmentPass) {
62141             newTargetSize = me.getLayoutTargetSize();
62142             if (newTargetSize.width != size.width || newTargetSize.height != size.height) {
62143                 me.adjustmentPass = true;
62144                 me.onLayout();
62145             }
62146         }
62147
62148         delete me.adjustmentPass;
62149     },
62150
62151     
62152     parseAnchor: function(a, start, cstart) {
62153         if (a && a != 'none') {
62154             var ratio;
62155             
62156             if (this.parseAnchorRE.test(a)) {
62157                 var diff = cstart - start;
62158                 return function(v) {
62159                     return v - diff;
62160                 };
62161             }    
62162             
62163             else if (a.indexOf('%') != -1) {
62164                 ratio = parseFloat(a.replace('%', '')) * 0.01;
62165                 return function(v) {
62166                     return Math.floor(v * ratio);
62167                 };
62168             }    
62169             
62170             else {
62171                 a = parseInt(a, 10);
62172                 if (!isNaN(a)) {
62173                     return function(v) {
62174                         return v + a;
62175                     };
62176                 }
62177             }
62178         }
62179         return null;
62180     },
62181
62182     
62183     adjustWidthAnchor: function(value, comp) {
62184         return value;
62185     },
62186
62187     
62188     adjustHeightAnchor: function(value, comp) {
62189         return value;
62190     }
62191
62192 });
62193
62194 Ext.define('Ext.form.action.Load', {
62195     extend:'Ext.form.action.Action',
62196     requires: ['Ext.data.Connection'],
62197     alternateClassName: 'Ext.form.Action.Load',
62198     alias: 'formaction.load',
62199
62200     type: 'load',
62201
62202     
62203     run: function() {
62204         Ext.Ajax.request(Ext.apply(
62205             this.createCallback(),
62206             {
62207                 method: this.getMethod(),
62208                 url: this.getUrl(),
62209                 headers: this.headers,
62210                 params: this.getParams()
62211             }
62212         ));
62213     },
62214
62215     
62216     onSuccess: function(response){
62217         var result = this.processResponse(response),
62218             form = this.form;
62219         if (result === true || !result.success || !result.data) {
62220             this.failureType = Ext.form.action.Action.LOAD_FAILURE;
62221             form.afterAction(this, false);
62222             return;
62223         }
62224         form.clearInvalid();
62225         form.setValues(result.data);
62226         form.afterAction(this, true);
62227     },
62228
62229     
62230     handleResponse: function(response) {
62231         var reader = this.form.reader,
62232             rs, data;
62233         if (reader) {
62234             rs = reader.read(response);
62235             data = rs.records && rs.records[0] ? rs.records[0].data : null;
62236             return {
62237                 success : rs.success,
62238                 data : data
62239             };
62240         }
62241         return Ext.decode(response.responseText);
62242     }
62243 });
62244
62245
62246
62247 Ext.define('Ext.window.Window', {
62248     extend: 'Ext.panel.Panel',
62249
62250     alternateClassName: 'Ext.Window',
62251
62252     requires: ['Ext.util.ComponentDragger', 'Ext.util.Region', 'Ext.EventManager'],
62253
62254     alias: 'widget.window',
62255
62256     
62257     
62258     
62259     
62260     
62261     
62262     
62263     
62264
62265     
62266     baseCls: Ext.baseCSSPrefix + 'window',
62267
62268     
62269     resizable: true,
62270
62271     
62272     draggable: true,
62273
62274     
62275     constrain: false,
62276
62277     
62278     constrainHeader: false,
62279
62280     
62281     plain: false,
62282
62283     
62284     minimizable: false,
62285
62286     
62287     maximizable: false,
62288
62289     
62290     minHeight: 100,
62291
62292     
62293     minWidth: 200,
62294
62295     
62296     expandOnShow: true,
62297
62298     
62299     collapsible: false,
62300
62301     
62302     closable: true,
62303
62304     
62305     hidden: true,
62306
62307     
62308     autoRender: true,
62309
62310     
62311     hideMode: 'visibility',
62312
62313     
62314     floating: true,
62315
62316     ariaRole: 'alertdialog',
62317     
62318     itemCls: 'x-window-item',
62319
62320     overlapHeader: true,
62321     
62322     ignoreHeaderBorderManagement: true,
62323
62324     
62325     initComponent: function() {
62326         var me = this;
62327         me.callParent();
62328         me.addEvents(
62329             
62330             
62331             
62332             'resize',
62333             
62334             'maximize',
62335             
62336             'minimize',
62337             
62338             'restore'
62339         );
62340
62341         if (me.plain) {
62342             me.addClsWithUI('plain');
62343         }
62344
62345         if (me.modal) {
62346             me.ariaRole = 'dialog';
62347         }
62348     },
62349
62350     
62351     
62352
62353     initStateEvents: function(){
62354         var events = this.stateEvents;
62355         
62356         Ext.each(['maximize', 'restore', 'resize', 'dragend'], function(event){
62357             if (Ext.Array.indexOf(events, event)) {
62358                 events.push(event);
62359             }
62360         });
62361         this.callParent();
62362     },
62363
62364     getState: function() {
62365         var me = this,
62366             state = me.callParent() || {},
62367             maximized = !!me.maximized;
62368
62369         state.maximized = maximized;
62370         Ext.apply(state, {
62371             size: maximized ? me.restoreSize : me.getSize(),
62372             pos: maximized ? me.restorePos : me.getPosition()
62373         });
62374         return state;
62375     },
62376
62377     applyState: function(state){
62378         var me = this;
62379
62380         if (state) {
62381             me.maximized = state.maximized;
62382             if (me.maximized) {
62383                 me.hasSavedRestore = true;
62384                 me.restoreSize = state.size;
62385                 me.restorePos = state.pos;
62386             } else {
62387                 Ext.apply(me, {
62388                     width: state.size.width,
62389                     height: state.size.height,
62390                     x: state.pos[0],
62391                     y: state.pos[1]
62392                 });
62393             }
62394         }
62395     },
62396
62397     
62398     onMouseDown: function () {
62399         if (this.floating) {
62400             this.toFront();
62401         }
62402     },
62403
62404     
62405     onRender: function(ct, position) {
62406         var me = this;
62407         me.callParent(arguments);
62408         me.focusEl = me.el;
62409
62410         
62411         if (me.maximizable) {
62412             me.header.on({
62413                 dblclick: {
62414                     fn: me.toggleMaximize,
62415                     element: 'el',
62416                     scope: me
62417                 }
62418             });
62419         }
62420     },
62421
62422     
62423     afterRender: function() {
62424         var me = this,
62425             hidden = me.hidden,
62426             keyMap;
62427
62428         me.hidden = false;
62429         
62430         me.callParent();
62431         me.hidden = hidden;
62432
62433         
62434         me.proxy = me.getProxy();
62435
62436         
62437         me.mon(me.el, 'mousedown', me.onMouseDown, me);
62438
62439         
62440         if (me.maximized) {
62441             me.maximized = false;
62442             me.maximize();
62443         }
62444
62445         if (me.closable) {
62446             keyMap = me.getKeyMap();
62447             keyMap.on(27, me.onEsc, me);
62448             keyMap.disable();
62449         }
62450     },
62451
62452     
62453     initDraggable: function() {
62454         var me = this,
62455             ddConfig;
62456
62457         if (!me.header) {
62458             me.updateHeader(true);
62459         }
62460
62461         ddConfig = Ext.applyIf({
62462             el: me.el,
62463             delegate: '#' + me.header.id
62464         }, me.draggable);
62465
62466         
62467         if (me.constrain || me.constrainHeader) {
62468             ddConfig.constrain = me.constrain;
62469             ddConfig.constrainDelegate = me.constrainHeader;
62470             ddConfig.constrainTo = me.constrainTo || me.container;
62471         }
62472
62473         
62474         me.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig);
62475         me.relayEvents(me.dd, ['dragstart', 'drag', 'dragend']);
62476     },
62477
62478     
62479     onEsc: function(k, e) {
62480         e.stopEvent();
62481         this[this.closeAction]();
62482     },
62483
62484     
62485     beforeDestroy: function() {
62486         var me = this;
62487         if (me.rendered) {
62488             delete this.animateTarget;
62489             me.hide();
62490             Ext.destroy(
62491                 me.keyMap
62492             );
62493         }
62494         me.callParent();
62495     },
62496
62497     
62498     addTools: function() {
62499         var me = this;
62500
62501         
62502         me.callParent();
62503
62504         if (me.minimizable) {
62505             me.addTool({
62506                 type: 'minimize',
62507                 handler: Ext.Function.bind(me.minimize, me, [])
62508             });
62509         }
62510         if (me.maximizable) {
62511             me.addTool({
62512                 type: 'maximize',
62513                 handler: Ext.Function.bind(me.maximize, me, [])
62514             });
62515             me.addTool({
62516                 type: 'restore',
62517                 handler: Ext.Function.bind(me.restore, me, []),
62518                 hidden: true
62519             });
62520         }
62521     },
62522
62523     
62524     getFocusEl: function() {
62525         var me = this,
62526             f = me.focusEl,
62527             defaultComp = me.defaultButton || me.defaultFocus,
62528             t = typeof db,
62529             el,
62530             ct;
62531
62532         if (Ext.isDefined(defaultComp)) {
62533             if (Ext.isNumber(defaultComp)) {
62534                 f = me.query('button')[defaultComp];
62535             } else if (Ext.isString(defaultComp)) {
62536                 f = me.down('#' + defaultComp);
62537             } else {
62538                 f = defaultComp;
62539             }
62540         }
62541         return f || me.focusEl;
62542     },
62543
62544     
62545     beforeShow: function() {
62546         this.callParent();
62547
62548         if (this.expandOnShow) {
62549             this.expand(false);
62550         }
62551     },
62552
62553     
62554     afterShow: function(animateTarget) {
62555         var me = this,
62556             size;
62557
62558         
62559         
62560         me.callParent(arguments);
62561
62562         if (me.maximized) {
62563             me.fitContainer();
62564         }
62565
62566         if (me.monitorResize || me.constrain || me.constrainHeader) {
62567             Ext.EventManager.onWindowResize(me.onWindowResize, me);
62568         }
62569         me.doConstrain();
62570         if (me.keyMap) {
62571             me.keyMap.enable();
62572         }
62573     },
62574
62575     
62576     doClose: function() {
62577         var me = this;
62578
62579         
62580         if (me.hidden) {
62581             me.fireEvent('close', me);
62582             me[me.closeAction]();
62583         } else {
62584             
62585             me.hide(me.animTarget, me.doClose, me);
62586         }
62587     },
62588
62589     
62590     afterHide: function() {
62591         var me = this;
62592
62593         
62594         if (me.monitorResize || me.constrain || me.constrainHeader) {
62595             Ext.EventManager.removeResizeListener(me.onWindowResize, me);
62596         }
62597
62598         
62599         if (me.keyMap) {
62600             me.keyMap.disable();
62601         }
62602
62603         
62604         me.callParent(arguments);
62605     },
62606
62607     
62608     onWindowResize: function() {
62609         if (this.maximized) {
62610             this.fitContainer();
62611         }
62612         this.doConstrain();
62613     },
62614
62615     
62616     minimize: function() {
62617         this.fireEvent('minimize', this);
62618         return this;
62619     },
62620
62621     afterCollapse: function() {
62622         var me = this;
62623
62624         if (me.maximizable) {
62625             me.tools.maximize.hide();
62626             me.tools.restore.hide();
62627         }
62628         if (me.resizer) {
62629             me.resizer.disable();
62630         }
62631         me.callParent(arguments);
62632     },
62633
62634     afterExpand: function() {
62635         var me = this;
62636
62637         if (me.maximized) {
62638             me.tools.restore.show();
62639         } else if (me.maximizable) {
62640             me.tools.maximize.show();
62641         }
62642         if (me.resizer) {
62643             me.resizer.enable();
62644         }
62645         me.callParent(arguments);
62646     },
62647
62648     
62649     maximize: function() {
62650         var me = this;
62651
62652         if (!me.maximized) {
62653             me.expand(false);
62654             if (!me.hasSavedRestore) {
62655                 me.restoreSize = me.getSize();
62656                 me.restorePos = me.getPosition(true);
62657             }
62658             if (me.maximizable) {
62659                 me.tools.maximize.hide();
62660                 me.tools.restore.show();
62661             }
62662             me.maximized = true;
62663             me.el.disableShadow();
62664
62665             if (me.dd) {
62666                 me.dd.disable();
62667             }
62668             if (me.collapseTool) {
62669                 me.collapseTool.hide();
62670             }
62671             me.el.addCls(Ext.baseCSSPrefix + 'window-maximized');
62672             me.container.addCls(Ext.baseCSSPrefix + 'window-maximized-ct');
62673
62674             me.setPosition(0, 0);
62675             me.fitContainer();
62676             me.fireEvent('maximize', me);
62677         }
62678         return me;
62679     },
62680
62681     
62682     restore: function() {
62683         var me = this,
62684             tools = me.tools;
62685
62686         if (me.maximized) {
62687             delete me.hasSavedRestore;
62688             me.removeCls(Ext.baseCSSPrefix + 'window-maximized');
62689
62690             
62691             if (tools.restore) {
62692                 tools.restore.hide();
62693             }
62694             if (tools.maximize) {
62695                 tools.maximize.show();
62696             }
62697             if (me.collapseTool) {
62698                 me.collapseTool.show();
62699             }
62700
62701             
62702             me.setPosition(me.restorePos);
62703             me.setSize(me.restoreSize);
62704
62705             
62706             delete me.restorePos;
62707             delete me.restoreSize;
62708
62709             me.maximized = false;
62710
62711             me.el.enableShadow(true);
62712
62713             
62714             if (me.dd) {
62715                 me.dd.enable();
62716             }
62717
62718             me.container.removeCls(Ext.baseCSSPrefix + 'window-maximized-ct');
62719
62720             me.doConstrain();
62721             me.fireEvent('restore', me);
62722         }
62723         return me;
62724     },
62725
62726     
62727     toggleMaximize: function() {
62728         return this[this.maximized ? 'restore': 'maximize']();
62729     }
62730
62731     
62732 });
62733
62734 Ext.define('Ext.form.field.Base', {
62735     extend: 'Ext.Component',
62736     mixins: {
62737         labelable: 'Ext.form.Labelable',
62738         field: 'Ext.form.field.Field'
62739     },
62740     alias: 'widget.field',
62741     alternateClassName: ['Ext.form.Field', 'Ext.form.BaseField'],
62742     requires: ['Ext.util.DelayedTask', 'Ext.XTemplate', 'Ext.layout.component.field.Field'],
62743
62744     fieldSubTpl: [
62745         '<input id="{id}" type="{type}" ',
62746         '<tpl if="name">name="{name}" </tpl>',
62747         '<tpl if="size">size="{size}" </tpl>',
62748         '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
62749         'class="{fieldCls} {typeCls}" autocomplete="off" />',
62750         {
62751             compiled: true,
62752             disableFormats: true
62753         }
62754     ],
62755
62756     
62757
62758     
62759     inputType: 'text',
62760
62761     
62762
62763     
62764     invalidText : 'The value in this field is invalid',
62765
62766     
62767     fieldCls : Ext.baseCSSPrefix + 'form-field',
62768
62769     
62770
62771     
62772     focusCls : Ext.baseCSSPrefix + 'form-focus',
62773
62774     
62775     dirtyCls : Ext.baseCSSPrefix + 'form-dirty',
62776
62777     
62778     checkChangeEvents: Ext.isIE && (!document.documentMode || document.documentMode < 9) ?
62779                         ['change', 'propertychange'] :
62780                         ['change', 'input', 'textInput', 'keyup', 'dragdrop'],
62781
62782     
62783     checkChangeBuffer: 50,
62784
62785     componentLayout: 'field',
62786
62787     
62788     readOnly : false,
62789
62790     
62791     readOnlyCls: Ext.baseCSSPrefix + 'form-readonly',
62792
62793     
62794
62795     
62796     validateOnBlur: true,
62797
62798     
62799     hasFocus : false,
62800     
62801     baseCls: Ext.baseCSSPrefix + 'field',
62802     
62803     maskOnDisable: false,
62804
62805     
62806     initComponent : function() {
62807         var me = this;
62808
62809         me.callParent();
62810
62811         me.subTplData = me.subTplData || {};
62812
62813         me.addEvents(
62814             
62815             'focus',
62816             
62817             'blur',
62818             
62819             'specialkey'
62820         );
62821
62822         
62823         me.initLabelable();
62824         me.initField();
62825
62826         
62827         if (!me.name) {
62828             me.name = me.getInputId();
62829         }
62830     },
62831
62832     
62833     getInputId: function() {
62834         return this.inputId || (this.inputId = Ext.id());
62835     },
62836
62837     
62838     getSubTplData: function() {
62839         var me = this,
62840             type = me.inputType,
62841             inputId = me.getInputId();
62842
62843         return Ext.applyIf(me.subTplData, {
62844             id: inputId,
62845             name: me.name || inputId,
62846             type: type,
62847             size: me.size || 20,
62848             cls: me.cls,
62849             fieldCls: me.fieldCls,
62850             tabIdx: me.tabIndex,
62851             typeCls: Ext.baseCSSPrefix + 'form-' + (type === 'password' ? 'text' : type)
62852         });
62853     },
62854
62855     
62856     getSubTplMarkup: function() {
62857         return this.getTpl('fieldSubTpl').apply(this.getSubTplData());
62858     },
62859
62860     initRenderTpl: function() {
62861         var me = this;
62862         if (!me.hasOwnProperty('renderTpl')) {
62863             me.renderTpl = me.getTpl('labelableRenderTpl');
62864         }
62865         return me.callParent();
62866     },
62867
62868     initRenderData: function() {
62869         return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
62870     },
62871
62872     
62873     setFieldStyle: function(style) {
62874         var me = this,
62875             inputEl = me.inputEl;
62876         if (inputEl) {
62877             inputEl.applyStyles(style);
62878         }
62879         me.fieldStyle = style;
62880     },
62881
62882     
62883     onRender : function() {
62884         var me = this,
62885             fieldStyle = me.fieldStyle,
62886             renderSelectors = me.renderSelectors;
62887
62888         Ext.applyIf(renderSelectors, me.getLabelableSelectors());
62889
62890         Ext.applyIf(renderSelectors, {
62891             
62892             inputEl: '.' + me.fieldCls
62893         });
62894
62895         me.callParent(arguments);
62896
62897         
62898         me.setRawValue(me.rawValue);
62899
62900         if (me.readOnly) {
62901             me.setReadOnly(true);
62902         }
62903         if (me.disabled) {
62904             me.disable();
62905         }
62906         if (fieldStyle) {
62907             me.setFieldStyle(fieldStyle);
62908         }
62909
62910         me.renderActiveError();
62911     },
62912
62913     initAria: function() {
62914         var me = this;
62915         me.callParent();
62916
62917         
62918         me.getActionEl().dom.setAttribute('aria-describedby', Ext.id(me.errorEl));
62919     },
62920
62921     getFocusEl: function() {
62922         return this.inputEl;
62923     },
62924
62925     isFileUpload: function() {
62926         return this.inputType === 'file';
62927     },
62928
62929     extractFileInput: function() {
62930         var me = this,
62931             fileInput = me.isFileUpload() ? me.inputEl.dom : null,
62932             clone;
62933         if (fileInput) {
62934             clone = fileInput.cloneNode(true);
62935             fileInput.parentNode.replaceChild(clone, fileInput);
62936             me.inputEl = Ext.get(clone);
62937         }
62938         return fileInput;
62939     },
62940
62941     
62942     getSubmitData: function() {
62943         var me = this,
62944             data = null,
62945             val;
62946         if (!me.disabled && me.submitValue && !me.isFileUpload()) {
62947             val = me.getSubmitValue();
62948             if (val !== null) {
62949                 data = {};
62950                 data[me.getName()] = val;
62951             }
62952         }
62953         return data;
62954     },
62955
62956     
62957     getSubmitValue: function() {
62958         return this.processRawValue(this.getRawValue());
62959     },
62960
62961     
62962     getRawValue: function() {
62963         var me = this,
62964             v = (me.inputEl ? me.inputEl.getValue() : Ext.value(me.rawValue, ''));
62965         me.rawValue = v;
62966         return v;
62967     },
62968
62969     
62970     setRawValue: function(value) {
62971         var me = this;
62972         value = Ext.value(value, '');
62973         me.rawValue = value;
62974
62975         
62976         if (me.inputEl) {
62977             me.inputEl.dom.value = value;
62978         }
62979         return value;
62980     },
62981
62982     
62983     valueToRaw: function(value) {
62984         return '' + Ext.value(value, '');
62985     },
62986
62987     
62988     rawToValue: function(rawValue) {
62989         return rawValue;
62990     },
62991
62992     
62993     processRawValue: function(value) {
62994         return value;
62995     },
62996
62997     
62998     getValue: function() {
62999         var me = this,
63000             val = me.rawToValue(me.processRawValue(me.getRawValue()));
63001         me.value = val;
63002         return val;
63003     },
63004
63005     
63006     setValue: function(value) {
63007         var me = this;
63008         me.setRawValue(me.valueToRaw(value));
63009         return me.mixins.field.setValue.call(me, value);
63010     },
63011
63012
63013     
63014     onDisable: function() {
63015         var me = this,
63016             inputEl = me.inputEl;
63017         me.callParent();
63018         if (inputEl) {
63019             inputEl.dom.disabled = true;
63020         }
63021     },
63022
63023     
63024     onEnable: function() {
63025         var me = this,
63026             inputEl = me.inputEl;
63027         me.callParent();
63028         if (inputEl) {
63029             inputEl.dom.disabled = false;
63030         }
63031     },
63032
63033     
63034     setReadOnly: function(readOnly) {
63035         var me = this,
63036             inputEl = me.inputEl;
63037         if (inputEl) {
63038             inputEl.dom.readOnly = readOnly;
63039             inputEl.dom.setAttribute('aria-readonly', readOnly);
63040         }
63041         me[readOnly ? 'addCls' : 'removeCls'](me.readOnlyCls);
63042         me.readOnly = readOnly;
63043     },
63044
63045     
63046     fireKey: function(e){
63047         if(e.isSpecialKey()){
63048             this.fireEvent('specialkey', this, Ext.create('Ext.EventObjectImpl', e));
63049         }
63050     },
63051
63052     
63053     initEvents : function(){
63054         var me = this,
63055             inputEl = me.inputEl,
63056             onChangeTask,
63057             onChangeEvent;
63058         if (inputEl) {
63059             me.mon(inputEl, Ext.EventManager.getKeyEvent(), me.fireKey,  me);
63060             me.mon(inputEl, 'focus', me.onFocus, me);
63061
63062             
63063             
63064             me.mon(inputEl, 'blur', me.onBlur, me, me.inEditor ? {buffer:10} : null);
63065
63066             
63067             onChangeTask = Ext.create('Ext.util.DelayedTask', me.checkChange, me);
63068             me.onChangeEvent = onChangeEvent = function() {
63069                 onChangeTask.delay(me.checkChangeBuffer);
63070             };
63071             Ext.each(me.checkChangeEvents, function(eventName) {
63072                 if (eventName === 'propertychange') {
63073                     me.usesPropertychange = true;
63074                 }
63075                 me.mon(inputEl, eventName, onChangeEvent);
63076             }, me);
63077         }
63078         me.callParent();
63079     },
63080
63081     doComponentLayout: function() {
63082         var me = this,
63083             inputEl = me.inputEl,
63084             usesPropertychange = me.usesPropertychange,
63085             ename = 'propertychange',
63086             onChangeEvent = me.onChangeEvent;
63087
63088         
63089         
63090         
63091         if (usesPropertychange) {
63092             me.mun(inputEl, ename, onChangeEvent);
63093         }
63094         me.callParent(arguments);
63095         if (usesPropertychange) {
63096             me.mon(inputEl, ename, onChangeEvent);
63097         }
63098     },
63099
63100     
63101     preFocus: Ext.emptyFn,
63102
63103     
63104     onFocus: function() {
63105         var me = this,
63106             focusCls = me.focusCls,
63107             inputEl = me.inputEl;
63108         me.preFocus();
63109         if (focusCls && inputEl) {
63110             inputEl.addCls(focusCls);
63111         }
63112         if (!me.hasFocus) {
63113             me.hasFocus = true;
63114             me.fireEvent('focus', me);
63115         }
63116     },
63117
63118     
63119     beforeBlur : Ext.emptyFn,
63120
63121     
63122     onBlur : function(){
63123         var me = this,
63124             focusCls = me.focusCls,
63125             inputEl = me.inputEl;
63126         me.beforeBlur();
63127         if (focusCls && inputEl) {
63128             inputEl.removeCls(focusCls);
63129         }
63130         if (me.validateOnBlur) {
63131             me.validate();
63132         }
63133         me.hasFocus = false;
63134         me.fireEvent('blur', me);
63135         me.postBlur();
63136     },
63137
63138     
63139     postBlur : Ext.emptyFn,
63140
63141
63142     
63143     onDirtyChange: function(isDirty) {
63144         this[isDirty ? 'addCls' : 'removeCls'](this.dirtyCls);
63145     },
63146
63147
63148     
63149     isValid : function() {
63150         var me = this;
63151         return me.disabled || me.validateValue(me.processRawValue(me.getRawValue()));
63152     },
63153
63154
63155     
63156     validateValue: function(value) {
63157         var me = this,
63158             errors = me.getErrors(value),
63159             isValid = Ext.isEmpty(errors);
63160         if (!me.preventMark) {
63161             if (isValid) {
63162                 me.clearInvalid();
63163             } else {
63164                 me.markInvalid(errors);
63165             }
63166         }
63167
63168         return isValid;
63169     },
63170
63171     
63172     markInvalid : function(errors) {
63173         
63174         var me = this,
63175             oldMsg = me.getActiveError();
63176         me.setActiveErrors(Ext.Array.from(errors));
63177         if (oldMsg !== me.getActiveError()) {
63178             me.doComponentLayout();
63179         }
63180     },
63181
63182     
63183     clearInvalid : function() {
63184         
63185         var me = this,
63186             hadError = me.hasActiveError();
63187         me.unsetActiveError();
63188         if (hadError) {
63189             me.doComponentLayout();
63190         }
63191     },
63192
63193     
63194     renderActiveError: function() {
63195         var me = this,
63196             hasError = me.hasActiveError();
63197         if (me.inputEl) {
63198             
63199             me.inputEl[hasError ? 'addCls' : 'removeCls'](me.invalidCls + '-field');
63200         }
63201         me.mixins.labelable.renderActiveError.call(me);
63202     },
63203
63204
63205     getActionEl: function() {
63206         return this.inputEl || this.el;
63207     }
63208
63209 });
63210
63211
63212 Ext.define('Ext.form.field.Text', {
63213     extend:'Ext.form.field.Base',
63214     alias: 'widget.textfield',
63215     requires: ['Ext.form.field.VTypes', 'Ext.layout.component.field.Text'],
63216     alternateClassName: ['Ext.form.TextField', 'Ext.form.Text'],
63217
63218     
63219     
63220     
63221
63222     
63223     size: 20,
63224
63225     
63226
63227     
63228     growMin : 30,
63229     
63230     
63231     growMax : 800,
63232
63233     
63234     growAppend: 'W',
63235     
63236     
63237
63238     
63239
63240     
63241
63242     
63243     allowBlank : true,
63244     
63245     
63246     minLength : 0,
63247     
63248     
63249     maxLength : Number.MAX_VALUE,
63250     
63251     
63252
63253     
63254     minLengthText : 'The minimum length for this field is {0}',
63255     
63256     
63257     maxLengthText : 'The maximum length for this field is {0}',
63258     
63259     
63260     
63261     
63262     blankText : 'This field is required',
63263     
63264     
63265
63266     
63267
63268     
63269     regexText : '',
63270     
63271     
63272
63273     
63274     emptyCls : Ext.baseCSSPrefix + 'form-empty-field',
63275
63276     ariaRole: 'textbox',
63277
63278     
63279
63280     componentLayout: 'textfield',
63281
63282     initComponent : function(){
63283         this.callParent();
63284         this.addEvents(
63285             
63286             'autosize',
63287
63288             
63289             'keydown',
63290             
63291             'keyup',
63292             
63293             'keypress'
63294         );
63295     },
63296
63297     
63298     initEvents : function(){
63299         var me = this,
63300             el = me.inputEl;
63301         
63302         me.callParent();
63303         if(me.selectOnFocus || me.emptyText){
63304             me.mon(el, 'mousedown', me.onMouseDown, me);
63305         }
63306         if(me.maskRe || (me.vtype && me.disableKeyFilter !== true && (me.maskRe = Ext.form.field.VTypes[me.vtype+'Mask']))){
63307             me.mon(el, 'keypress', me.filterKeys, me);
63308         }
63309
63310         if (me.enableKeyEvents) {
63311             me.mon(el, {
63312                 scope: me,
63313                 keyup: me.onKeyUp,
63314                 keydown: me.onKeyDown,
63315                 keypress: me.onKeyPress
63316             });
63317         }
63318     },
63319
63320     
63321     isEqual: function(value1, value2) {
63322         return String(Ext.value(value1, '')) === String(Ext.value(value2, ''));
63323     },
63324
63325     
63326     onChange: function() {
63327         this.callParent();
63328         this.autoSize();
63329     },
63330     
63331     afterRender: function(){
63332         var me = this;
63333         if (me.enforceMaxLength) {
63334             me.inputEl.dom.maxLength = me.maxLength;
63335         }
63336         me.applyEmptyText();
63337         me.autoSize();
63338         me.callParent();
63339     },
63340
63341     onMouseDown: function(e){
63342         var me = this;
63343         if(!me.hasFocus){
63344             me.mon(me.inputEl, 'mouseup', Ext.emptyFn, me, { single: true, preventDefault: true });
63345         }
63346     },
63347
63348     
63349     processRawValue: function(value) {
63350         var me = this,
63351             stripRe = me.stripCharsRe,
63352             newValue;
63353             
63354         if (stripRe) {
63355             newValue = value.replace(stripRe, '');
63356             if (newValue !== value) {
63357                 me.setRawValue(newValue);
63358                 value = newValue;
63359             }
63360         }
63361         return value;
63362     },
63363
63364     
63365     onDisable: function(){
63366         this.callParent();
63367         if (Ext.isIE) {
63368             this.inputEl.dom.unselectable = 'on';
63369         }
63370     },
63371
63372     
63373     onEnable: function(){
63374         this.callParent();
63375         if (Ext.isIE) {
63376             this.inputEl.dom.unselectable = '';
63377         }
63378     },
63379
63380     onKeyDown: function(e) {
63381         this.fireEvent('keydown', this, e);
63382     },
63383
63384     onKeyUp: function(e) {
63385         this.fireEvent('keyup', this, e);
63386     },
63387
63388     onKeyPress: function(e) {
63389         this.fireEvent('keypress', this, e);
63390     },
63391
63392     
63393     reset : function(){
63394         this.callParent();
63395         this.applyEmptyText();
63396     },
63397
63398     applyEmptyText : function(){
63399         var me = this,
63400             emptyText = me.emptyText,
63401             isEmpty;
63402
63403         if (me.rendered && emptyText) {
63404             isEmpty = me.getRawValue().length < 1 && !me.hasFocus;
63405             
63406             if (Ext.supports.Placeholder) {
63407                 me.inputEl.dom.placeholder = emptyText;
63408             } else if (isEmpty) {
63409                 me.setRawValue(emptyText);
63410             }
63411             
63412             
63413             
63414             if (isEmpty) {
63415                 me.inputEl.addCls(me.emptyCls);
63416             }
63417
63418             me.autoSize();
63419         }
63420     },
63421
63422     
63423     preFocus : function(){
63424         var me = this,
63425             inputEl = me.inputEl,
63426             emptyText = me.emptyText,
63427             isEmpty;
63428
63429         if (emptyText && !Ext.supports.Placeholder && inputEl.dom.value === emptyText) {
63430             me.setRawValue('');
63431             isEmpty = true;
63432             inputEl.removeCls(me.emptyCls);
63433         } else if (Ext.supports.Placeholder) {
63434             me.inputEl.removeCls(me.emptyCls);
63435         }
63436         if (me.selectOnFocus || isEmpty) {
63437             inputEl.dom.select();
63438         }
63439     },
63440
63441     onFocus: function() {
63442         var me = this;
63443         me.callParent(arguments);
63444         if (me.emptyText) {
63445             me.autoSize();
63446         }
63447     },
63448
63449     
63450     postBlur : function(){
63451         this.applyEmptyText();
63452     },
63453
63454     
63455     filterKeys : function(e){
63456         if(e.ctrlKey){
63457             return;
63458         }
63459         var key = e.getKey(),
63460             charCode = String.fromCharCode(e.getCharCode());
63461             
63462         if(Ext.isGecko && (e.isNavKeyPress() || key === e.BACKSPACE || (key === e.DELETE && e.button === -1))){
63463             return;
63464         }
63465         
63466         if(!Ext.isGecko && e.isSpecialKey() && !charCode){
63467             return;
63468         }
63469         if(!this.maskRe.test(charCode)){
63470             e.stopEvent();
63471         }
63472     },
63473
63474     
63475     getRawValue: function() {
63476         var me = this,
63477             v = me.callParent();
63478         if (v === me.emptyText) {
63479             v = '';
63480         }
63481         return v;
63482     },
63483
63484     
63485     setValue: function(value) {
63486         var me = this,
63487             inputEl = me.inputEl;
63488         
63489         if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
63490             inputEl.removeCls(me.emptyCls);
63491         }
63492         
63493         me.callParent(arguments);
63494
63495         me.applyEmptyText();
63496         return me;
63497     },
63498
63499     
63500     getErrors: function(value) {
63501         var me = this,
63502             errors = me.callParent(arguments),
63503             validator = me.validator,
63504             emptyText = me.emptyText,
63505             allowBlank = me.allowBlank,
63506             vtype = me.vtype,
63507             vtypes = Ext.form.field.VTypes,
63508             regex = me.regex,
63509             format = Ext.String.format,
63510             msg;
63511
63512         value = value || me.processRawValue(me.getRawValue());
63513
63514         if (Ext.isFunction(validator)) {
63515             msg = validator.call(me, value);
63516             if (msg !== true) {
63517                 errors.push(msg);
63518             }
63519         }
63520
63521         if (value.length < 1 || value === emptyText) {
63522             if (!allowBlank) {
63523                 errors.push(me.blankText);
63524             }
63525             
63526             return errors;
63527         }
63528
63529         if (value.length < me.minLength) {
63530             errors.push(format(me.minLengthText, me.minLength));
63531         }
63532
63533         if (value.length > me.maxLength) {
63534             errors.push(format(me.maxLengthText, me.maxLength));
63535         }
63536
63537         if (vtype) {
63538             if(!vtypes[vtype](value, me)){
63539                 errors.push(me.vtypeText || vtypes[vtype +'Text']);
63540             }
63541         }
63542
63543         if (regex && !regex.test(value)) {
63544             errors.push(me.regexText || me.invalidText);
63545         }
63546
63547         return errors;
63548     },
63549
63550     
63551     selectText : function(start, end){
63552         var me = this,
63553             v = me.getRawValue(),
63554             doFocus = true,
63555             el = me.inputEl.dom,
63556             undef,
63557             range;
63558             
63559         if (v.length > 0) {
63560             start = start === undef ? 0 : start;
63561             end = end === undef ? v.length : end;
63562             if (el.setSelectionRange) {
63563                 el.setSelectionRange(start, end);
63564             }
63565             else if(el.createTextRange) {
63566                 range = el.createTextRange();
63567                 range.moveStart('character', start);
63568                 range.moveEnd('character', end - v.length);
63569                 range.select();
63570             }
63571             doFocus = Ext.isGecko || Ext.isOpera;
63572         }
63573         if (doFocus) {
63574             me.focus();
63575         }
63576     },
63577
63578     
63579     autoSize: function() {
63580         var me = this,
63581             width;
63582         if (me.grow && me.rendered) {
63583             me.doComponentLayout();
63584             width = me.inputEl.getWidth();
63585             if (width !== me.lastInputWidth) {
63586                 me.fireEvent('autosize', width);
63587                 me.lastInputWidth = width;
63588             }
63589         }
63590     },
63591
63592     initAria: function() {
63593         this.callParent();
63594         this.getActionEl().dom.setAttribute('aria-required', this.allowBlank === false);
63595     },
63596
63597     
63598     getBodyNaturalWidth: function() {
63599         return Math.round(this.size * 6.5) + 20;
63600     }
63601
63602 });
63603
63604
63605 Ext.define('Ext.form.field.TextArea', {
63606     extend:'Ext.form.field.Text',
63607     alias: ['widget.textareafield', 'widget.textarea'],
63608     alternateClassName: 'Ext.form.TextArea',
63609     requires: ['Ext.XTemplate', 'Ext.layout.component.field.TextArea'],
63610
63611     fieldSubTpl: [
63612         '<textarea id="{id}" ',
63613             '<tpl if="name">name="{name}" </tpl>',
63614             '<tpl if="rows">rows="{rows}" </tpl>',
63615             '<tpl if="cols">cols="{cols}" </tpl>',
63616             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
63617             'class="{fieldCls} {typeCls}" ',
63618             'autocomplete="off">',
63619         '</textarea>',
63620         {
63621             compiled: true,
63622             disableFormats: true
63623         }
63624     ],
63625
63626     
63627     growMin: 60,
63628
63629     
63630     growMax: 1000,
63631
63632     
63633     growAppend: '\n-',
63634
63635     
63636     cols: 20,
63637
63638     
63639     rows: 4,
63640
63641     
63642     enterIsSpecial: false,
63643
63644     
63645     preventScrollbars: false,
63646
63647     
63648     componentLayout: 'textareafield',
63649
63650     
63651     onRender: function(ct, position) {
63652         var me = this;
63653         Ext.applyIf(me.subTplData, {
63654             cols: me.cols,
63655             rows: me.rows
63656         });
63657
63658         me.callParent(arguments);
63659     },
63660
63661     
63662     afterRender: function(){
63663         var me = this;
63664
63665         me.callParent(arguments);
63666
63667         if (me.grow) {
63668             if (me.preventScrollbars) {
63669                 me.inputEl.setStyle('overflow', 'hidden');
63670             }
63671             me.inputEl.setHeight(me.growMin);
63672         }
63673     },
63674
63675     
63676     fireKey: function(e) {
63677         if (e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() !== e.ENTER || e.hasModifier()))) {
63678             this.fireEvent('specialkey', this, e);
63679         }
63680     },
63681
63682     
63683     autoSize: function() {
63684         var me = this,
63685             height;
63686
63687         if (me.grow && me.rendered) {
63688             me.doComponentLayout();
63689             height = me.inputEl.getHeight();
63690             if (height !== me.lastInputHeight) {
63691                 me.fireEvent('autosize', height);
63692                 me.lastInputHeight = height;
63693             }
63694         }
63695     },
63696
63697     
63698     initAria: function() {
63699         this.callParent(arguments);
63700         this.getActionEl().dom.setAttribute('aria-multiline', true);
63701     },
63702
63703     
63704     getBodyNaturalWidth: function() {
63705         return Math.round(this.cols * 6.5) + 20;
63706     }
63707
63708 });
63709
63710
63711
63712 Ext.define('Ext.window.MessageBox', {
63713     extend: 'Ext.window.Window',
63714
63715     requires: [
63716         'Ext.toolbar.Toolbar',
63717         'Ext.form.field.Text',
63718         'Ext.form.field.TextArea',
63719         'Ext.button.Button',
63720         'Ext.layout.container.Anchor',
63721         'Ext.layout.container.HBox',
63722         'Ext.ProgressBar'
63723     ],
63724     
63725     alternateClassName: 'Ext.MessageBox',
63726
63727     alias: 'widget.messagebox',
63728
63729     
63730     OK : 1,
63731     
63732     YES : 2,
63733     
63734     NO : 4,
63735     
63736     CANCEL : 8,
63737     
63738     OKCANCEL : 9,
63739     
63740     YESNO : 6,
63741     
63742     YESNOCANCEL : 14,
63743     
63744     INFO : 'ext-mb-info',
63745     
63746     WARNING : 'ext-mb-warning',
63747     
63748     QUESTION : 'ext-mb-question',
63749     
63750     ERROR : 'ext-mb-error',
63751
63752     
63753     hideMode: 'offsets',
63754     closeAction: 'hide',
63755     resizable: false,
63756     title: '&#160;',
63757
63758     width: 600,
63759     height: 500,
63760     minWidth: 250,
63761     maxWidth: 600,
63762     minHeight: 110,
63763     maxHeight: 500,
63764     constrain: true,
63765
63766     cls: Ext.baseCSSPrefix + 'message-box',
63767
63768     layout: {
63769         type: 'anchor'
63770     },
63771
63772     
63773     defaultTextHeight : 75,
63774     
63775     minProgressWidth : 250,
63776     
63777     minPromptWidth: 250,
63778     
63779     buttonText: {
63780         ok: 'OK',
63781         yes: 'Yes',
63782         no: 'No',
63783         cancel: 'Cancel'
63784     },
63785
63786     buttonIds: [
63787         'ok', 'yes', 'no', 'cancel'
63788     ],
63789
63790     titleText: {
63791         confirm: 'Confirm',
63792         prompt: 'Prompt',
63793         wait: 'Loading...',
63794         alert: 'Attention'
63795     },
63796     
63797     iconHeight: 35,
63798
63799     makeButton: function(btnIdx) {
63800         var btnId = this.buttonIds[btnIdx];
63801         return Ext.create('Ext.button.Button', {
63802             handler: this.btnCallback,
63803             itemId: btnId,
63804             scope: this,
63805             text: this.buttonText[btnId],
63806             minWidth: 75
63807         });
63808     },
63809
63810     btnCallback: function(btn) {
63811         var me = this,
63812             value,
63813             field;
63814
63815         if (me.cfg.prompt || me.cfg.multiline) {
63816             if (me.cfg.multiline) {
63817                 field = me.textArea;
63818             } else {
63819                 field = me.textField;
63820             }
63821             value = field.getValue();
63822             field.reset();
63823         }
63824
63825         
63826         btn.blur();
63827         me.hide();
63828         me.userCallback(btn.itemId, value, me.cfg);
63829     },
63830
63831     hide: function() {
63832         var me = this;
63833         me.dd.endDrag();
63834         me.progressBar.reset();
63835         me.removeCls(me.cfg.cls);
63836         me.callParent();
63837     },
63838
63839     initComponent: function() {
63840         var me = this,
63841             i, button;
63842
63843         me.title = '&#160;';
63844
63845         me.topContainer = Ext.create('Ext.container.Container', {
63846             anchor: '100%',
63847             style: {
63848                 padding: '10px',
63849                 overflow: 'hidden'
63850             },
63851             items: [
63852                 me.iconComponent = Ext.create('Ext.Component', {
63853                     cls: 'ext-mb-icon',
63854                     width: 50,
63855                     height: me.iconHeight,
63856                     style: {
63857                         'float': 'left'
63858                     }
63859                 }),
63860                 me.promptContainer = Ext.create('Ext.container.Container', {
63861                     layout: {
63862                         type: 'anchor'
63863                     },
63864                     items: [
63865                         me.msg = Ext.create('Ext.Component', {
63866                             autoEl: { tag: 'span' },
63867                             cls: 'ext-mb-text'
63868                         }),
63869                         me.textField = Ext.create('Ext.form.field.Text', {
63870                             anchor: '100%',
63871                             enableKeyEvents: true,
63872                             listeners: {
63873                                 keydown: me.onPromptKey,
63874                                 scope: me
63875                             }
63876                         }),
63877                         me.textArea = Ext.create('Ext.form.field.TextArea', {
63878                             anchor: '100%',
63879                             height: 75
63880                         })
63881                     ]
63882                 })
63883             ]
63884         });
63885         me.progressBar = Ext.create('Ext.ProgressBar', {
63886             anchor: '-10',
63887             style: 'margin-left:10px'
63888         });
63889
63890         me.items = [me.topContainer, me.progressBar];
63891
63892         
63893         me.msgButtons = [];
63894         for (i = 0; i < 4; i++) {
63895             button = me.makeButton(i);
63896             me.msgButtons[button.itemId] = button;
63897             me.msgButtons.push(button);
63898         }
63899         me.bottomTb = Ext.create('Ext.toolbar.Toolbar', {
63900             ui: 'footer',
63901             dock: 'bottom',
63902             layout: {
63903                 pack: 'center'
63904             },
63905             items: [
63906                 me.msgButtons[0],
63907                 me.msgButtons[1],
63908                 me.msgButtons[2],
63909                 me.msgButtons[3]
63910             ]
63911         });
63912         me.dockedItems = [me.bottomTb];
63913
63914         me.callParent();
63915     },
63916
63917     onPromptKey: function(textField, e) {
63918         var me = this,
63919             blur;
63920             
63921         if (e.keyCode === Ext.EventObject.RETURN || e.keyCode === 10) {
63922             if (me.msgButtons.ok.isVisible()) {
63923                 blur = true;
63924                 me.msgButtons.ok.handler.call(me, me.msgButtons.ok);
63925             } else if (me.msgButtons.yes.isVisible()) {
63926                 me.msgButtons.yes.handler.call(me, me.msgButtons.yes);
63927                 blur = true;
63928             }
63929             
63930             if (blur) {
63931                 me.textField.blur();
63932             }
63933         }
63934     },
63935
63936     reconfigure: function(cfg) {
63937         var me = this,
63938             buttons = cfg.buttons || 0,
63939             hideToolbar = true,
63940             initialWidth = me.maxWidth,
63941             i;
63942
63943         cfg = cfg || {};
63944         me.cfg = cfg;
63945         if (cfg.width) {
63946             initialWidth = cfg.width;
63947         }
63948
63949         
63950         delete me.defaultFocus;
63951         
63952         
63953         me.animateTarget = cfg.animateTarget || undefined;
63954
63955         
63956         me.modal = cfg.modal !== false;
63957
63958         
63959         if (cfg.title) {
63960             me.setTitle(cfg.title||'&#160;');
63961         }
63962
63963         if (!me.rendered) {
63964             me.width = initialWidth;
63965             me.render(Ext.getBody());
63966         } else {
63967             me.setSize(initialWidth, me.maxHeight);
63968         }
63969         me.setPosition(-10000, -10000);
63970
63971         
63972         me.closable = cfg.closable && !cfg.wait;
63973         if (cfg.closable === false) {
63974             me.tools.close.hide();
63975         } else {
63976             me.tools.close.show();
63977         }
63978
63979         
63980         if (!cfg.title && !me.closable) {
63981             me.header.hide();
63982         } else {
63983             me.header.show();
63984         }
63985
63986         
63987         me.liveDrag = !cfg.proxyDrag;
63988
63989         
63990         me.userCallback = Ext.Function.bind(cfg.callback ||cfg.fn || Ext.emptyFn, cfg.scope || Ext.global);
63991
63992         
63993         me.setIcon(cfg.icon);
63994
63995         
63996         if (cfg.msg) {
63997             me.msg.update(cfg.msg);
63998             me.msg.show();
63999         } else {
64000             me.msg.hide();
64001         }
64002
64003         
64004         if (cfg.prompt || cfg.multiline) {
64005             me.multiline = cfg.multiline;
64006             if (cfg.multiline) {
64007                 me.textArea.setValue(cfg.value);
64008                 me.textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight);
64009                 me.textArea.show();
64010                 me.textField.hide();
64011                 me.defaultFocus = me.textArea;
64012             } else {
64013                 me.textField.setValue(cfg.value);
64014                 me.textArea.hide();
64015                 me.textField.show();
64016                 me.defaultFocus = me.textField;
64017             }
64018         } else {
64019             me.textArea.hide();
64020             me.textField.hide();
64021         }
64022
64023         
64024         if (cfg.progress || cfg.wait) {
64025             me.progressBar.show();
64026             me.updateProgress(0, cfg.progressText);
64027             if(cfg.wait === true){
64028                 me.progressBar.wait(cfg.waitConfig);
64029             }
64030         } else {
64031             me.progressBar.hide();
64032         }
64033
64034         
64035         for (i = 0; i < 4; i++) {
64036             if (buttons & Math.pow(2, i)) {
64037
64038                 
64039                 if (!me.defaultFocus) {
64040                     me.defaultFocus = me.msgButtons[i];
64041                 }
64042                 me.msgButtons[i].show();
64043                 hideToolbar = false;
64044             } else {
64045                 me.msgButtons[i].hide();
64046             }
64047         }
64048
64049         
64050         if (hideToolbar) {
64051             me.bottomTb.hide();
64052         } else {
64053             me.bottomTb.show();
64054         }
64055         me.hidden = true;
64056     },
64057
64058     
64059     show: function(cfg) {
64060         var me = this;
64061             
64062         me.reconfigure(cfg);
64063         me.addCls(cfg.cls);
64064         if (cfg.animateTarget) {
64065             me.doAutoSize(false);
64066             me.callParent();
64067         } else {
64068             me.callParent();
64069             me.doAutoSize(true);
64070         }
64071         return me;
64072     },
64073     
64074     afterShow: function(){
64075         if (this.animateTarget) {
64076             this.center();
64077         }    
64078         this.callParent(arguments);
64079     },
64080
64081     doAutoSize: function(center) {
64082         var me = this,
64083             icon = me.iconComponent,
64084             iconHeight = me.iconHeight;
64085
64086         if (!Ext.isDefined(me.frameWidth)) {
64087             me.frameWidth = me.el.getWidth() - me.body.getWidth();
64088         }
64089         
64090         
64091         icon.setHeight(iconHeight);
64092
64093         
64094         me.minWidth = me.cfg.minWidth || Ext.getClass(this).prototype.minWidth;
64095
64096         
64097         
64098         me.topContainer.doLayout();
64099         if (Ext.isIE6 || Ext.isIEQuirks) {
64100             
64101             
64102             
64103             me.textField.setCalculatedSize(9);
64104             me.textArea.setCalculatedSize(9);
64105         }
64106         var width = me.cfg.width || me.msg.getWidth() + icon.getWidth() + 25, 
64107             height = (me.header.rendered ? me.header.getHeight() : 0) +
64108             Math.max(me.promptContainer.getHeight(), icon.getHeight()) +
64109             me.progressBar.getHeight() +
64110             (me.bottomTb.rendered ? me.bottomTb.getHeight() : 0) + 20 ;
64111
64112         
64113         icon.setHeight(Math.max(iconHeight, me.msg.getHeight()));
64114         me.setSize(width + me.frameWidth, height + me.frameWidth);
64115         if (center) {
64116             me.center();
64117         }
64118         return me;
64119     },
64120
64121     updateText: function(text) {
64122         this.msg.update(text);
64123         return this.doAutoSize(true);
64124     },
64125
64126     
64127     setIcon : function(icon) {
64128         var me = this;
64129         me.iconComponent.removeCls(me.iconCls);
64130         if (icon) {
64131             me.iconComponent.show();
64132             me.iconComponent.addCls(Ext.baseCSSPrefix + 'dlg-icon');
64133             me.iconComponent.addCls(me.iconCls = icon);
64134         } else {
64135             me.iconComponent.removeCls(Ext.baseCSSPrefix + 'dlg-icon');
64136             me.iconComponent.hide();
64137         }
64138         return me;
64139     },
64140
64141     
64142     updateProgress : function(value, progressText, msg){
64143         this.progressBar.updateProgress(value, progressText);
64144         if (msg){
64145             this.updateText(msg);
64146         }
64147         return this;
64148     },
64149
64150     onEsc: function() {
64151         if (this.closable !== false) {
64152             this.callParent(arguments);
64153         }
64154     },
64155
64156     
64157     confirm: function(cfg, msg, fn, scope) {
64158         if (Ext.isString(cfg)) {
64159             cfg = {
64160                 title: cfg,
64161                 icon: 'ext-mb-question',
64162                 msg: msg,
64163                 buttons: this.YESNO,
64164                 callback: fn,
64165                 scope: scope
64166             };
64167         }
64168         return this.show(cfg);
64169     },
64170
64171     
64172     prompt : function(cfg, msg, fn, scope, multiline, value){
64173         if (Ext.isString(cfg)) {
64174             cfg = {
64175                 prompt: true,
64176                 title: cfg,
64177                 minWidth: this.minPromptWidth,
64178                 msg: msg,
64179                 buttons: this.OKCANCEL,
64180                 callback: fn,
64181                 scope: scope,
64182                 multiline: multiline,
64183                 value: value
64184             };
64185         }
64186         return this.show(cfg);
64187     },
64188
64189     
64190     wait : function(cfg, title, config){
64191         if (Ext.isString(cfg)) {
64192             cfg = {
64193                 title : title,
64194                 msg : cfg,
64195                 closable: false,
64196                 wait: true,
64197                 modal: true,
64198                 minWidth: this.minProgressWidth,
64199                 waitConfig: config
64200             };
64201         }
64202         return this.show(cfg);
64203     },
64204
64205     
64206     alert: function(cfg, msg, fn, scope) {
64207         if (Ext.isString(cfg)) {
64208             cfg = {
64209                 title : cfg,
64210                 msg : msg,
64211                 buttons: this.OK,
64212                 fn: fn,
64213                 scope : scope,
64214                 minWidth: this.minWidth
64215             };
64216         }
64217         return this.show(cfg);
64218     },
64219
64220     
64221     progress : function(cfg, msg, progressText){
64222         if (Ext.isString(cfg)) {
64223             cfg = {
64224                 title: cfg,
64225                 msg: msg,
64226                 progressText: progressText
64227             };
64228         }
64229         return this.show(cfg);
64230     }
64231 }, function() {
64232     Ext.MessageBox = Ext.Msg = new this();
64233 });
64234
64235
64236
64237
64238 Ext.define('Ext.form.Basic', {
64239     extend: 'Ext.util.Observable',
64240     alternateClassName: 'Ext.form.BasicForm',
64241     requires: ['Ext.util.MixedCollection', 'Ext.form.action.Load', 'Ext.form.action.Submit',
64242                'Ext.window.MessageBox', 'Ext.data.Errors'],
64243
64244     constructor: function(owner, config) {
64245         var me = this,
64246             onItemAddOrRemove = me.onItemAddOrRemove;
64247
64248         
64249         me.owner = owner;
64250
64251         
64252         me.mon(owner, {
64253             add: onItemAddOrRemove,
64254             remove: onItemAddOrRemove,
64255             scope: me
64256         });
64257
64258         Ext.apply(me, config);
64259
64260         
64261         if (Ext.isString(me.paramOrder)) {
64262             me.paramOrder = me.paramOrder.split(/[\s,|]/);
64263         }
64264
64265         me.addEvents(
64266             
64267             'beforeaction',
64268             
64269             'actionfailed',
64270             
64271             'actioncomplete',
64272             
64273             'validitychange',
64274             
64275             'dirtychange'
64276         );
64277         me.callParent();
64278     },
64279
64280     
64281     initialize: function(){
64282         this.initialized = true;
64283         this.onValidityChange(!this.hasInvalidField());
64284     },
64285
64286     
64287     
64288     
64289
64290     
64291
64292     
64293
64294     
64295     timeout: 30,
64296
64297     
64298
64299     
64300
64301     
64302     paramsAsHash: false,
64303
64304     
64305     waitTitle: 'Please Wait...',
64306
64307     
64308     trackResetOnLoad: false,
64309
64310     
64311
64312     
64313
64314
64315     
64316     wasDirty: false,
64317
64318
64319     
64320     destroy: function() {
64321         this.clearListeners();
64322     },
64323
64324     
64325     onItemAddOrRemove: function(parent, child) {
64326         var me = this,
64327             isAdding = !!child.ownerCt,
64328             isContainer = child.isContainer;
64329
64330         function handleField(field) {
64331             
64332             me[isAdding ? 'mon' : 'mun'](field, {
64333                 validitychange: me.checkValidity,
64334                 dirtychange: me.checkDirty,
64335                 scope: me,
64336                 buffer: 100 
64337             });
64338             
64339             delete me._fields;
64340         }
64341
64342         if (child.isFormField) {
64343             handleField(child);
64344         }
64345         else if (isContainer) {
64346             
64347             Ext.Array.forEach(child.query('[isFormField]'), handleField);
64348         }
64349
64350         
64351         delete this._boundItems;
64352
64353         
64354         if (me.initialized) {
64355             me.onValidityChange(!me.hasInvalidField());
64356         }
64357     },
64358
64359     
64360     getFields: function() {
64361         var fields = this._fields;
64362         if (!fields) {
64363             fields = this._fields = Ext.create('Ext.util.MixedCollection');
64364             fields.addAll(this.owner.query('[isFormField]'));
64365         }
64366         return fields;
64367     },
64368
64369     getBoundItems: function() {
64370         var boundItems = this._boundItems;
64371         if (!boundItems) {
64372             boundItems = this._boundItems = Ext.create('Ext.util.MixedCollection');
64373             boundItems.addAll(this.owner.query('[formBind]'));
64374         }
64375         return boundItems;
64376     },
64377
64378     
64379     hasInvalidField: function() {
64380         return !!this.getFields().findBy(function(field) {
64381             var preventMark = field.preventMark,
64382                 isValid;
64383             field.preventMark = true;
64384             isValid = field.isValid();
64385             field.preventMark = preventMark;
64386             return !isValid;
64387         });
64388     },
64389
64390     
64391     isValid: function() {
64392         var me = this,
64393             invalid;
64394         me.batchLayouts(function() {
64395             invalid = me.getFields().filterBy(function(field) {
64396                 return !field.validate();
64397             });
64398         });
64399         return invalid.length < 1;
64400     },
64401
64402     
64403     checkValidity: function() {
64404         var me = this,
64405             valid = !me.hasInvalidField();
64406         if (valid !== me.wasValid) {
64407             me.onValidityChange(valid);
64408             me.fireEvent('validitychange', me, valid);
64409             me.wasValid = valid;
64410         }
64411     },
64412
64413     
64414     onValidityChange: function(valid) {
64415         var boundItems = this.getBoundItems();
64416         if (boundItems) {
64417             boundItems.each(function(cmp) {
64418                 if (cmp.disabled === valid) {
64419                     cmp.setDisabled(!valid);
64420                 }
64421             });
64422         }
64423     },
64424
64425     
64426     isDirty: function() {
64427         return !!this.getFields().findBy(function(f) {
64428             return f.isDirty();
64429         });
64430     },
64431
64432     
64433     checkDirty: function() {
64434         var dirty = this.isDirty();
64435         if (dirty !== this.wasDirty) {
64436             this.fireEvent('dirtychange', this, dirty);
64437             this.wasDirty = dirty;
64438         }
64439     },
64440
64441     
64442     hasUpload: function() {
64443         return !!this.getFields().findBy(function(f) {
64444             return f.isFileUpload();
64445         });
64446     },
64447
64448     
64449     doAction: function(action, options) {
64450         if (Ext.isString(action)) {
64451             action = Ext.ClassManager.instantiateByAlias('formaction.' + action, Ext.apply({}, options, {form: this}));
64452         }
64453         if (this.fireEvent('beforeaction', this, action) !== false) {
64454             this.beforeAction(action);
64455             Ext.defer(action.run, 100, action);
64456         }
64457         return this;
64458     },
64459
64460     
64461     submit: function(options) {
64462         return this.doAction(this.standardSubmit ? 'standardsubmit' : this.api ? 'directsubmit' : 'submit', options);
64463     },
64464
64465     
64466     load: function(options) {
64467         return this.doAction(this.api ? 'directload' : 'load', options);
64468     },
64469
64470     
64471     updateRecord: function(record) {
64472         var fields = record.fields,
64473             values = this.getFieldValues(),
64474             name,
64475             obj = {};
64476
64477         fields.each(function(f) {
64478             name = f.name;
64479             if (name in values) {
64480                 obj[name] = values[name];
64481             }
64482         });
64483
64484         record.beginEdit();
64485         record.set(obj);
64486         record.endEdit();
64487
64488         return this;
64489     },
64490
64491     
64492     loadRecord: function(record) {
64493         this._record = record;
64494         return this.setValues(record.data);
64495     },
64496     
64497     
64498     getRecord: function() {
64499         return this._record;
64500     },
64501
64502     
64503     beforeAction: function(action) {
64504         var waitMsg = action.waitMsg,
64505             maskCls = Ext.baseCSSPrefix + 'mask-loading',
64506             waitMsgTarget;
64507
64508         
64509         this.getFields().each(function(f) {
64510             if (f.isFormField && f.syncValue) {
64511                 f.syncValue();
64512             }
64513         });
64514
64515         if (waitMsg) {
64516             waitMsgTarget = this.waitMsgTarget;
64517             if (waitMsgTarget === true) {
64518                 this.owner.el.mask(waitMsg, maskCls);
64519             } else if (waitMsgTarget) {
64520                 waitMsgTarget = this.waitMsgTarget = Ext.get(waitMsgTarget);
64521                 waitMsgTarget.mask(waitMsg, maskCls);
64522             } else {
64523                 Ext.MessageBox.wait(waitMsg, action.waitTitle || this.waitTitle);
64524             }
64525         }
64526     },
64527
64528     
64529     afterAction: function(action, success) {
64530         if (action.waitMsg) {
64531             var MessageBox = Ext.MessageBox,
64532                 waitMsgTarget = this.waitMsgTarget;
64533             if (waitMsgTarget === true) {
64534                 this.owner.el.unmask();
64535             } else if (waitMsgTarget) {
64536                 waitMsgTarget.unmask();
64537             } else {
64538                 MessageBox.updateProgress(1);
64539                 MessageBox.hide();
64540             }
64541         }
64542         if (success) {
64543             if (action.reset) {
64544                 this.reset();
64545             }
64546             Ext.callback(action.success, action.scope || action, [this, action]);
64547             this.fireEvent('actioncomplete', this, action);
64548         } else {
64549             Ext.callback(action.failure, action.scope || action, [this, action]);
64550             this.fireEvent('actionfailed', this, action);
64551         }
64552     },
64553
64554
64555     
64556     findField: function(id) {
64557         return this.getFields().findBy(function(f) {
64558             return f.id === id || f.getName() === id;
64559         });
64560     },
64561
64562
64563     
64564     markInvalid: function(errors) {
64565         var me = this;
64566
64567         function mark(fieldId, msg) {
64568             var field = me.findField(fieldId);
64569             if (field) {
64570                 field.markInvalid(msg);
64571             }
64572         }
64573
64574         if (Ext.isArray(errors)) {
64575             Ext.each(errors, function(err) {
64576                 mark(err.id, err.msg);
64577             });
64578         }
64579         else if (errors instanceof Ext.data.Errors) {
64580             errors.each(function(err) {
64581                 mark(err.field, err.message);
64582             });
64583         }
64584         else {
64585             Ext.iterate(errors, mark);
64586         }
64587         return this;
64588     },
64589
64590     
64591     setValues: function(values) {
64592         var me = this;
64593
64594         function setVal(fieldId, val) {
64595             var field = me.findField(fieldId);
64596             if (field) {
64597                 field.setValue(val);
64598                 if (me.trackResetOnLoad) {
64599                     field.resetOriginalValue();
64600                 }
64601             }
64602         }
64603
64604         if (Ext.isArray(values)) {
64605             
64606             Ext.each(values, function(val) {
64607                 setVal(val.id, val.value);
64608             });
64609         } else {
64610             
64611             Ext.iterate(values, setVal);
64612         }
64613         return this;
64614     },
64615
64616     
64617     getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) {
64618         var values = {};
64619
64620         this.getFields().each(function(field) {
64621             if (!dirtyOnly || field.isDirty()) {
64622                 var data = field[useDataValues ? 'getModelData' : 'getSubmitData'](includeEmptyText);
64623                 if (Ext.isObject(data)) {
64624                     Ext.iterate(data, function(name, val) {
64625                         if (includeEmptyText && val === '') {
64626                             val = field.emptyText || '';
64627                         }
64628                         if (name in values) {
64629                             var bucket = values[name],
64630                                 isArray = Ext.isArray;
64631                             if (!isArray(bucket)) {
64632                                 bucket = values[name] = [bucket];
64633                             }
64634                             if (isArray(val)) {
64635                                 values[name] = bucket.concat(val);
64636                             } else {
64637                                 bucket.push(val);
64638                             }
64639                         } else {
64640                             values[name] = val;
64641                         }
64642                     });
64643                 }
64644             }
64645         });
64646
64647         if (asString) {
64648             values = Ext.Object.toQueryString(values);
64649         }
64650         return values;
64651     },
64652
64653     
64654     getFieldValues: function(dirtyOnly) {
64655         return this.getValues(false, dirtyOnly, false, true);
64656     },
64657
64658     
64659     clearInvalid: function() {
64660         var me = this;
64661         me.batchLayouts(function() {
64662             me.getFields().each(function(f) {
64663                 f.clearInvalid();
64664             });
64665         });
64666         return me;
64667     },
64668
64669     
64670     reset: function() {
64671         var me = this;
64672         me.batchLayouts(function() {
64673             me.getFields().each(function(f) {
64674                 f.reset();
64675             });
64676         });
64677         return me;
64678     },
64679
64680     
64681     applyToFields: function(obj) {
64682         this.getFields().each(function(f) {
64683             Ext.apply(f, obj);
64684         });
64685         return this;
64686     },
64687
64688     
64689     applyIfToFields: function(obj) {
64690         this.getFields().each(function(f) {
64691             Ext.applyIf(f, obj);
64692         });
64693         return this;
64694     },
64695
64696     
64697     batchLayouts: function(fn) {
64698         var me = this,
64699             suspended = new Ext.util.HashMap();
64700
64701         
64702         me.getFields().each(function(field) {
64703             var ownerCt = field.ownerCt;
64704             if (!suspended.contains(ownerCt)) {
64705                 suspended.add(ownerCt);
64706                 ownerCt.oldSuspendLayout = ownerCt.suspendLayout;
64707                 ownerCt.suspendLayout = true;
64708             }
64709         });
64710
64711         
64712         fn();
64713
64714         
64715         suspended.each(function(id, ct) {
64716             ct.suspendLayout = ct.oldSuspendLayout;
64717             delete ct.oldSuspendLayout;
64718         });
64719
64720         
64721         me.owner.doComponentLayout();
64722     }
64723 });
64724
64725
64726 Ext.define('Ext.form.FieldAncestor', {
64727
64728     
64729
64730
64731     
64732     initFieldAncestor: function() {
64733         var me = this,
64734             onSubtreeChange = me.onFieldAncestorSubtreeChange;
64735
64736         me.addEvents(
64737             
64738             'fieldvaliditychange',
64739
64740             
64741             'fielderrorchange'
64742         );
64743
64744         
64745         me.on('add', onSubtreeChange, me);
64746         me.on('remove', onSubtreeChange, me);
64747
64748         me.initFieldDefaults();
64749     },
64750
64751     
64752     initFieldDefaults: function() {
64753         if (!this.fieldDefaults) {
64754             this.fieldDefaults = {};
64755         }
64756     },
64757
64758     
64759     onFieldAncestorSubtreeChange: function(parent, child) {
64760         var me = this,
64761             isAdding = !!child.ownerCt;
64762
64763         function handleCmp(cmp) {
64764             var isLabelable = cmp.isFieldLabelable,
64765                 isField = cmp.isFormField;
64766             if (isLabelable || isField) {
64767                 if (isLabelable) {
64768                     me['onLabelable' + (isAdding ? 'Added' : 'Removed')](cmp);
64769                 }
64770                 if (isField) {
64771                     me['onField' + (isAdding ? 'Added' : 'Removed')](cmp);
64772                 }
64773             }
64774             else if (cmp.isContainer) {
64775                 Ext.Array.forEach(cmp.getRefItems(), handleCmp);
64776             }
64777         }
64778         handleCmp(child);
64779     },
64780
64781     
64782     onLabelableAdded: function(labelable) {
64783         var me = this;
64784
64785         
64786         me.mon(labelable, 'errorchange', me.handleFieldErrorChange, me, {buffer: 10});
64787
64788         labelable.setFieldDefaults(me.fieldDefaults);
64789     },
64790
64791     
64792     onFieldAdded: function(field) {
64793         var me = this;
64794         me.mon(field, 'validitychange', me.handleFieldValidityChange, me);
64795     },
64796
64797     
64798     onLabelableRemoved: function(labelable) {
64799         var me = this;
64800         me.mun(labelable, 'errorchange', me.handleFieldErrorChange, me);
64801     },
64802
64803     
64804     onFieldRemoved: function(field) {
64805         var me = this;
64806         me.mun(field, 'validitychange', me.handleFieldValidityChange, me);
64807     },
64808
64809     
64810     handleFieldValidityChange: function(field, isValid) {
64811         var me = this;
64812         me.fireEvent('fieldvaliditychange', me, field, isValid);
64813         me.onFieldValidityChange();
64814     },
64815
64816     
64817     handleFieldErrorChange: function(labelable, activeError) {
64818         var me = this;
64819         me.fireEvent('fielderrorchange', me, labelable, activeError);
64820         me.onFieldErrorChange();
64821     },
64822
64823     
64824     onFieldValidityChange: Ext.emptyFn,
64825
64826     
64827     onFieldErrorChange: Ext.emptyFn
64828
64829 });
64830
64831 Ext.define('Ext.layout.container.CheckboxGroup', {
64832     extend: 'Ext.layout.container.Container',
64833     alias: ['layout.checkboxgroup'],
64834
64835
64836     onLayout: function() {
64837         var numCols = this.getColCount(),
64838             shadowCt = this.getShadowCt(),
64839             owner = this.owner,
64840             items = owner.items,
64841             shadowItems = shadowCt.items,
64842             numItems = items.length,
64843             colIndex = 0,
64844             i, numRows;
64845
64846         
64847         
64848         
64849         
64850
64851         shadowItems.each(function(col) {
64852             col.items.clear();
64853         });
64854
64855         
64856         
64857         while (shadowItems.length > numCols) {
64858             shadowCt.remove(shadowItems.last());
64859         }
64860         while (shadowItems.length < numCols) {
64861             shadowCt.add({
64862                 xtype: 'container',
64863                 cls: owner.groupCls,
64864                 flex: 1
64865             });
64866         }
64867
64868         if (owner.vertical) {
64869             numRows = Math.ceil(numItems / numCols);
64870             for (i = 0; i < numItems; i++) {
64871                 if (i > 0 && i % numRows === 0) {
64872                     colIndex++;
64873                 }
64874                 shadowItems.getAt(colIndex).items.add(items.getAt(i));
64875             }
64876         } else {
64877             for (i = 0; i < numItems; i++) {
64878                 colIndex = i % numCols;
64879                 shadowItems.getAt(colIndex).items.add(items.getAt(i));
64880             }
64881         }
64882
64883         if (!shadowCt.rendered) {
64884             shadowCt.render(this.getRenderTarget());
64885         } else {
64886             
64887             
64888             shadowItems.each(function(col) {
64889                 var layout = col.getLayout();
64890                 layout.renderItems(layout.getLayoutItems(), layout.getRenderTarget());
64891             });
64892         }
64893
64894         shadowCt.doComponentLayout();
64895     },
64896
64897
64898     
64899     renderItems: Ext.emptyFn,
64900
64901
64902     
64903     getShadowCt: function() {
64904         var me = this,
64905             shadowCt = me.shadowCt,
64906             owner, items, item, columns, columnsIsArray, numCols, i;
64907
64908         if (!shadowCt) {
64909             
64910             owner = me.owner;
64911             columns = owner.columns;
64912             columnsIsArray = Ext.isArray(columns);
64913             numCols = me.getColCount();
64914             items = [];
64915             for(i = 0; i < numCols; i++) {
64916                 item = {
64917                     xtype: 'container',
64918                     cls: owner.groupCls
64919                 };
64920                 if (columnsIsArray) {
64921                     
64922                     
64923                     if (columns[i] < 1) {
64924                         item.flex = columns[i];
64925                     } else {
64926                         item.width = columns[i];
64927                     }
64928                 }
64929                 else {
64930                     
64931                     item.flex = 1;
64932                 }
64933                 items.push(item);
64934             }
64935
64936             
64937             shadowCt = me.shadowCt = Ext.createWidget('container', {
64938                 layout: 'hbox',
64939                 items: items,
64940                 ownerCt: owner
64941             });
64942         }
64943         
64944         return shadowCt;
64945     },
64946
64947
64948     
64949     getColCount: function() {
64950         var owner = this.owner,
64951             colsCfg = owner.columns;
64952         return Ext.isArray(colsCfg) ? colsCfg.length : (Ext.isNumber(colsCfg) ? colsCfg : owner.items.length);
64953     }
64954
64955 });
64956
64957
64958 Ext.define('Ext.form.FieldContainer', {
64959     extend: 'Ext.container.Container',
64960     mixins: {
64961         labelable: 'Ext.form.Labelable',
64962         fieldAncestor: 'Ext.form.FieldAncestor'
64963     },
64964     alias: 'widget.fieldcontainer',
64965
64966     componentLayout: 'field',
64967
64968     
64969     combineLabels: false,
64970
64971     
64972     labelConnector: ', ',
64973
64974     
64975     combineErrors: false,
64976     
64977     maskOnDisable: false,
64978
64979     initComponent: function() {
64980         var me = this,
64981             onSubCmpAddOrRemove = me.onSubCmpAddOrRemove;
64982
64983         
64984         me.initLabelable();
64985         me.initFieldAncestor();
64986
64987         me.callParent();
64988     },
64989
64990     
64991     onLabelableAdded: function(labelable) {
64992         var me = this;
64993         me.mixins.fieldAncestor.onLabelableAdded.call(this, labelable);
64994         me.updateLabel();
64995     },
64996
64997     
64998     onLabelableRemoved: function(labelable) {
64999         var me = this;
65000         me.mixins.fieldAncestor.onLabelableRemoved.call(this, labelable);
65001         me.updateLabel();
65002     },
65003
65004     onRender: function() {
65005         var me = this,
65006             renderSelectors = me.renderSelectors,
65007             applyIf = Ext.applyIf;
65008
65009         applyIf(renderSelectors, me.getLabelableSelectors());
65010
65011         me.callParent(arguments);
65012     },
65013
65014     initRenderTpl: function() {
65015         var me = this;
65016         if (!me.hasOwnProperty('renderTpl')) {
65017             me.renderTpl = me.getTpl('labelableRenderTpl');
65018         }
65019         return me.callParent();
65020     },
65021
65022     initRenderData: function() {
65023         return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
65024     },
65025
65026     
65027     getFieldLabel: function() {
65028         var label = this.fieldLabel || '';
65029         if (!label && this.combineLabels) {
65030             label = Ext.Array.map(this.query('[isFieldLabelable]'), function(field) {
65031                 return field.getFieldLabel();
65032             }).join(this.labelConnector);
65033         }
65034         return label;
65035     },
65036
65037     
65038     updateLabel: function() {
65039         var me = this,
65040             label = me.labelEl;
65041         if (label) {
65042             label.update(me.getFieldLabel());
65043         }
65044     },
65045
65046
65047     
65048     onFieldErrorChange: function(field, activeError) {
65049         if (this.combineErrors) {
65050             var me = this,
65051                 oldError = me.getActiveError(),
65052                 invalidFields = Ext.Array.filter(me.query('[isFormField]'), function(field) {
65053                     return field.hasActiveError();
65054                 }),
65055                 newErrors = me.getCombinedErrors(invalidFields);
65056
65057             if (newErrors) {
65058                 me.setActiveErrors(newErrors);
65059             } else {
65060                 me.unsetActiveError();
65061             }
65062
65063             if (oldError !== me.getActiveError()) {
65064                 me.doComponentLayout();
65065             }
65066         }
65067     },
65068
65069     
65070     getCombinedErrors: function(invalidFields) {
65071         var forEach = Ext.Array.forEach,
65072             errors = [];
65073         forEach(invalidFields, function(field) {
65074             forEach(field.getActiveErrors(), function(error) {
65075                 var label = field.getFieldLabel();
65076                 errors.push((label ? label + ': ' : '') + error);
65077             });
65078         });
65079         return errors;
65080     },
65081
65082     getTargetEl: function() {
65083         return this.bodyEl || this.callParent();
65084     }
65085 });
65086
65087
65088 Ext.define('Ext.form.CheckboxGroup', {
65089     extend:'Ext.form.FieldContainer',
65090     mixins: {
65091         field: 'Ext.form.field.Field'
65092     },
65093     alias: 'widget.checkboxgroup',
65094     requires: ['Ext.layout.container.CheckboxGroup', 'Ext.form.field.Base'],
65095
65096     
65097
65098     
65099
65100     
65101     columns : 'auto',
65102
65103     
65104     vertical : false,
65105
65106     
65107     allowBlank : true,
65108
65109     
65110     blankText : "You must select at least one item in this group",
65111
65112     
65113     defaultType : 'checkboxfield',
65114
65115     
65116     groupCls : Ext.baseCSSPrefix + 'form-check-group',
65117
65118     
65119     fieldBodyCls: Ext.baseCSSPrefix + 'form-checkboxgroup-body',
65120
65121     
65122     layout: 'checkboxgroup',
65123
65124     initComponent: function() {
65125         var me = this;
65126         me.callParent();
65127         me.initField();
65128     },
65129
65130     
65131     initValue: function() {
65132         var me = this,
65133             valueCfg = me.value;
65134         me.originalValue = me.lastValue = valueCfg || me.getValue();
65135         if (valueCfg) {
65136             me.setValue(valueCfg);
65137         }
65138     },
65139
65140     
65141     onFieldAdded: function(field) {
65142         var me = this;
65143         if (field.isCheckbox) {
65144             me.mon(field, 'change', me.checkChange, me);
65145         }
65146         me.callParent(arguments);
65147     },
65148
65149     onFieldRemoved: function(field) {
65150         var me = this;
65151         if (field.isCheckbox) {
65152             me.mun(field, 'change', me.checkChange, me);
65153         }
65154         me.callParent(arguments);
65155     },
65156
65157     
65158     isEqual: function(value1, value2) {
65159         var toQueryString = Ext.Object.toQueryString;
65160         return toQueryString(value1) === toQueryString(value2);
65161     },
65162
65163     
65164     getErrors: function() {
65165         var errors = [];
65166         if (!this.allowBlank && Ext.isEmpty(this.getChecked())) {
65167             errors.push(this.blankText);
65168         }
65169         return errors;
65170     },
65171
65172     
65173     getBoxes: function() {
65174         return this.query('[isCheckbox]');
65175     },
65176
65177     
65178     eachBox: function(fn, scope) {
65179         Ext.Array.forEach(this.getBoxes(), fn, scope || this);
65180     },
65181
65182     
65183     getChecked: function() {
65184         return Ext.Array.filter(this.getBoxes(), function(cb) {
65185             return cb.getValue();
65186         });
65187     },
65188
65189     
65190     isDirty: function(){
65191         return Ext.Array.some(this.getBoxes(), function(cb) {
65192             return cb.isDirty();
65193         });
65194     },
65195
65196     
65197     setReadOnly: function(readOnly) {
65198         this.eachBox(function(cb) {
65199             cb.setReadOnly(readOnly);
65200         });
65201         this.readOnly = readOnly;
65202     },
65203
65204     
65205     reset: function() {
65206         var me = this,
65207             hadError = me.hasActiveError(),
65208             preventMark = me.preventMark;
65209         me.preventMark = true;
65210         me.batchChanges(function() {
65211             me.eachBox(function(cb) {
65212                 cb.reset();
65213             });
65214         });
65215         me.preventMark = preventMark;
65216         me.unsetActiveError();
65217         if (hadError) {
65218             me.doComponentLayout();
65219         }
65220     },
65221
65222     
65223     resetOriginalValue: function() {
65224         
65225         
65226         Ext.defer(function() {
65227             this.callParent();
65228         }, 1, this);
65229     },
65230
65231
65232     
65233     setValue: function(value) {
65234         var me = this;
65235         me.batchChanges(function() {
65236             me.eachBox(function(cb) {
65237                 var name = cb.getName(),
65238                     cbValue = false;
65239                 if (value && name in value) {
65240                     if (Ext.isArray(value[name])) {
65241                         cbValue = Ext.Array.contains(value[name], cb.inputValue);
65242                     } else {
65243                         
65244                         cbValue = value[name];
65245                     }
65246                 }
65247                 cb.setValue(cbValue);
65248             });
65249         });
65250         return me;
65251     },
65252
65253
65254     
65255     getValue: function() {
65256         var values = {};
65257         this.eachBox(function(cb) {
65258             var name = cb.getName(),
65259                 inputValue = cb.inputValue,
65260                 bucket;
65261             if (cb.getValue()) {
65262                 if (name in values) {
65263                     bucket = values[name];
65264                     if (!Ext.isArray(bucket)) {
65265                         bucket = values[name] = [bucket];
65266                     }
65267                     bucket.push(inputValue);
65268                 } else {
65269                     values[name] = inputValue;
65270                 }
65271             }
65272         });
65273         return values;
65274     },
65275
65276     
65277     getSubmitData: function() {
65278         return null;
65279     },
65280
65281     
65282     getModelData: function() {
65283         return null;
65284     },
65285
65286     validate: function() {
65287         var me = this,
65288             errors = me.getErrors(),
65289             isValid = Ext.isEmpty(errors),
65290             wasValid = !me.hasActiveError();
65291
65292         if (isValid) {
65293             me.unsetActiveError();
65294         } else {
65295             me.setActiveError(errors);
65296         }
65297         if (isValid !== wasValid) {
65298             me.fireEvent('validitychange', me, isValid);
65299             me.doComponentLayout();
65300         }
65301
65302         return isValid;
65303     }
65304
65305 }, function() {
65306
65307     this.borrow(Ext.form.field.Base, ['markInvalid', 'clearInvalid']);
65308
65309 });
65310
65311
65312
65313 Ext.define('Ext.form.CheckboxManager', {
65314     extend: 'Ext.util.MixedCollection',
65315     singleton: true,
65316
65317     getByName: function(name) {
65318         return this.filterBy(function(item) {
65319             return item.name == name;
65320         });
65321     },
65322
65323     getWithValue: function(name, value) {
65324         return this.filterBy(function(item) {
65325             return item.name == name && item.inputValue == value;
65326         });
65327     },
65328
65329     getChecked: function(name) {
65330         return this.filterBy(function(item) {
65331             return item.name == name && item.checked;
65332         });
65333     }
65334 });
65335
65336
65337 Ext.define('Ext.form.FieldSet', {
65338     extend: 'Ext.container.Container',
65339     alias: 'widget.fieldset',
65340     uses: ['Ext.form.field.Checkbox', 'Ext.panel.Tool', 'Ext.layout.container.Anchor', 'Ext.layout.component.FieldSet'],
65341
65342     
65343
65344     
65345
65346     
65347
65348     
65349
65350     
65351     collapsed: false,
65352
65353     
65354
65355     
65356     baseCls: Ext.baseCSSPrefix + 'fieldset',
65357
65358     
65359     layout: 'anchor',
65360
65361     componentLayout: 'fieldset',
65362
65363     
65364     ariaRole: '',
65365
65366     renderTpl: ['<div class="{baseCls}-body"></div>'],
65367     
65368     maskOnDisable: false,
65369
65370     getElConfig: function(){
65371         return {tag: 'fieldset', id: this.id};
65372     },
65373
65374     initComponent: function() {
65375         var me = this,
65376             baseCls = me.baseCls;
65377
65378         me.callParent();
65379
65380         
65381         me.initLegend();
65382
65383         
65384         Ext.applyIf(me.renderSelectors, {
65385             body: '.' + baseCls + '-body'
65386         });
65387
65388         if (me.collapsed) {
65389             me.addCls(baseCls + '-collapsed');
65390             me.collapse();
65391         }
65392     },
65393
65394     
65395     onRender: function(container, position) {
65396         this.callParent(arguments);
65397         
65398         this.initLegend();
65399     },
65400
65401     
65402     initLegend: function() {
65403         var me = this,
65404             legendItems,
65405             legend = me.legend;
65406
65407         
65408         if (!legend && (me.title || me.checkboxToggle || me.collapsible)) {
65409             legendItems = [];
65410
65411             
65412             if (me.checkboxToggle) {
65413                 legendItems.push(me.createCheckboxCmp());
65414             }
65415             
65416             else if (me.collapsible) {
65417                 legendItems.push(me.createToggleCmp());
65418             }
65419
65420             
65421             legendItems.push(me.createTitleCmp());
65422
65423             legend = me.legend = Ext.create('Ext.container.Container', {
65424                 baseCls: me.baseCls + '-header',
65425                 ariaRole: '',
65426                 getElConfig: function(){
65427                     return {tag: 'legend', cls: this.baseCls};
65428                 },
65429                 items: legendItems
65430             });
65431         }
65432
65433         
65434         if (legend && !legend.rendered && me.rendered) {
65435             me.legend.render(me.el, me.body); 
65436         }
65437     },
65438
65439     
65440     createTitleCmp: function() {
65441         var me = this;
65442         me.titleCmp = Ext.create('Ext.Component', {
65443             html: me.title,
65444             cls: me.baseCls + '-header-text'
65445         });
65446         return me.titleCmp;
65447         
65448     },
65449
65450     
65451
65452     
65453     createCheckboxCmp: function() {
65454         var me = this,
65455             suffix = '-checkbox';
65456             
65457         me.checkboxCmp = Ext.create('Ext.form.field.Checkbox', {
65458             name: me.checkboxName || me.id + suffix,
65459             cls: me.baseCls + '-header' + suffix,
65460             checked: !me.collapsed,
65461             listeners: {
65462                 change: me.onCheckChange,
65463                 scope: me
65464             }
65465         });
65466         return me.checkboxCmp;
65467     },
65468
65469     
65470
65471     
65472     createToggleCmp: function() {
65473         var me = this;
65474         me.toggleCmp = Ext.create('Ext.panel.Tool', {
65475             type: 'toggle',
65476             handler: me.toggle,
65477             scope: me
65478         });
65479         return me.toggleCmp;
65480     },
65481     
65482     
65483     setTitle: function(title) {
65484         var me = this;
65485         me.title = title;
65486         me.initLegend();
65487         me.titleCmp.update(title);
65488         return me;
65489     },
65490     
65491     getTargetEl : function() {
65492         return this.body || this.frameBody || this.el;
65493     },
65494     
65495     getContentTarget: function() {
65496         return this.body;
65497     },
65498     
65499     
65500     getRefItems: function(deep) {
65501         var refItems = this.callParent(arguments),
65502             legend = this.legend;
65503
65504         
65505         if (legend) {
65506             refItems.unshift(legend);
65507             if (deep) {
65508                 refItems.unshift.apply(refItems, legend.getRefItems(true));
65509             }
65510         }
65511         return refItems;
65512     },
65513
65514     
65515     expand : function(){
65516         return this.setExpanded(true);
65517     },
65518     
65519     
65520     collapse : function() {
65521         return this.setExpanded(false);
65522     },
65523
65524     
65525     setExpanded: function(expanded) {
65526         var me = this,
65527             checkboxCmp = me.checkboxCmp,
65528             toggleCmp = me.toggleCmp;
65529
65530         expanded = !!expanded;
65531         
65532         if (checkboxCmp) {
65533             checkboxCmp.setValue(expanded);
65534         }
65535         
65536         if (expanded) {
65537             me.removeCls(me.baseCls + '-collapsed');
65538         } else {
65539             me.addCls(me.baseCls + '-collapsed');
65540         }
65541         me.collapsed = !expanded;
65542         me.doComponentLayout();
65543         return me;
65544     },
65545
65546     
65547     toggle: function() {
65548         this.setExpanded(!!this.collapsed);
65549     },
65550
65551     
65552     onCheckChange: function(cmp, checked) {
65553         this.setExpanded(checked);
65554     },
65555
65556     beforeDestroy : function() {
65557         var legend = this.legend;
65558         if (legend) {
65559             legend.destroy();
65560         }
65561         this.callParent();
65562     }
65563 });
65564
65565
65566 Ext.define('Ext.form.Label', {
65567     extend:'Ext.Component',
65568     alias: 'widget.label',
65569     requires: ['Ext.util.Format'],
65570
65571     
65572     
65573     
65574     
65575     maskOnDisable: false,
65576     getElConfig: function(){
65577         var me = this;
65578         return {
65579             tag: 'label', 
65580             id: me.id, 
65581             htmlFor: me.forId || '',
65582             html: me.text ? Ext.util.Format.htmlEncode(me.text) : (me.html || '') 
65583         };
65584     },
65585
65586     
65587     setText : function(text, encode){
65588         var me = this;
65589         
65590         encode = encode !== false;
65591         if(encode) {
65592             me.text = text;
65593             delete me.html;
65594         } else {
65595             me.html = text;
65596             delete me.text;
65597         }
65598         
65599         if(me.rendered){
65600             me.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(text) : text;
65601         }
65602         return this;
65603     }
65604 });
65605
65606
65607
65608 Ext.define('Ext.form.Panel', {
65609     extend:'Ext.panel.Panel',
65610     mixins: {
65611         fieldAncestor: 'Ext.form.FieldAncestor'
65612     },
65613     alias: 'widget.form',
65614     alternateClassName: ['Ext.FormPanel', 'Ext.form.FormPanel'],
65615     requires: ['Ext.form.Basic', 'Ext.util.TaskRunner'],
65616
65617     
65618
65619     
65620
65621     
65622     layout: 'anchor',
65623
65624     ariaRole: 'form',
65625
65626     initComponent: function() {
65627         var me = this;
65628         
65629         if (me.frame) {
65630             me.border = false;
65631         }
65632         
65633         me.initFieldAncestor();
65634         me.callParent();
65635
65636         me.relayEvents(me.form, [
65637             'beforeaction',
65638             'actionfailed',
65639             'actioncomplete',
65640             'validitychange',
65641             'dirtychange'
65642         ]);
65643
65644         
65645         if (me.pollForChanges) {
65646             me.startPolling(me.pollInterval || 500);
65647         }
65648     },
65649
65650     initItems: function() {
65651         
65652         var me = this;
65653         
65654         me.form = me.createForm();
65655         me.callParent();
65656         me.form.initialize();
65657     },
65658
65659     
65660     createForm: function() {
65661         return Ext.create('Ext.form.Basic', this, Ext.applyIf({listeners: {}}, this.initialConfig));
65662     },
65663
65664     
65665     getForm: function() {
65666         return this.form;
65667     },
65668     
65669     
65670     loadRecord: function(record) {
65671         return this.getForm().loadRecord(record);
65672     },
65673     
65674     
65675     getRecord: function() {
65676         return this.getForm().getRecord();
65677     },
65678     
65679     
65680     getValues: function() {
65681         return this.getForm().getValues();
65682     },
65683
65684     beforeDestroy: function() {
65685         this.stopPolling();
65686         this.form.destroy();
65687         this.callParent();
65688     },
65689
65690     
65691     load: function(options) {
65692         this.form.load(options);
65693     },
65694
65695     
65696     submit: function(options) {
65697         this.form.submit(options);
65698     },
65699
65700     
65701     disable: function(silent) {
65702         this.callParent(arguments);
65703         this.form.getFields().each(function(field) {
65704             field.disable();
65705         });
65706     },
65707
65708     
65709     enable: function(silent) {
65710         this.callParent(arguments);
65711         this.form.getFields().each(function(field) {
65712             field.enable();
65713         });
65714     },
65715
65716     
65717     startPolling: function(interval) {
65718         this.stopPolling();
65719         var task = Ext.create('Ext.util.TaskRunner', interval);
65720         task.start({
65721             interval: 0,
65722             run: this.checkChange,
65723             scope: this
65724         });
65725         this.pollTask = task;
65726     },
65727
65728     
65729     stopPolling: function() {
65730         var task = this.pollTask;
65731         if (task) {
65732             task.stopAll();
65733             delete this.pollTask;
65734         }
65735     },
65736
65737     
65738     checkChange: function() {
65739         this.form.getFields().each(function(field) {
65740             field.checkChange();
65741         });
65742     }
65743 });
65744
65745
65746 Ext.define('Ext.form.RadioGroup', {
65747     extend: 'Ext.form.CheckboxGroup',
65748     alias: 'widget.radiogroup',
65749
65750     
65751     
65752     allowBlank : true,
65753     
65754     blankText : 'You must select one item in this group',
65755     
65756     
65757     defaultType : 'radiofield',
65758     
65759     
65760     groupCls : Ext.baseCSSPrefix + 'form-radio-group',
65761
65762     getBoxes: function() {
65763         return this.query('[isRadio]');
65764     }
65765
65766 });
65767
65768
65769 Ext.define('Ext.form.RadioManager', {
65770     extend: 'Ext.util.MixedCollection',
65771     singleton: true,
65772
65773     getByName: function(name) {
65774         return this.filterBy(function(item) {
65775             return item.name == name;
65776         });
65777     },
65778
65779     getWithValue: function(name, value) {
65780         return this.filterBy(function(item) {
65781             return item.name == name && item.inputValue == value;
65782         });
65783     },
65784
65785     getChecked: function(name) {
65786         return this.findBy(function(item) {
65787             return item.name == name && item.checked;
65788         });
65789     }
65790 });
65791
65792
65793 Ext.define('Ext.form.action.DirectLoad', {
65794     extend:'Ext.form.action.Load',
65795     requires: ['Ext.direct.Manager'],
65796     alternateClassName: 'Ext.form.Action.DirectLoad',
65797     alias: 'formaction.directload',
65798
65799     type: 'directload',
65800
65801     run: function() {
65802         this.form.api.load.apply(window, this.getArgs());
65803     },
65804
65805     
65806     getArgs: function() {
65807         var me = this,
65808             args = [],
65809             form = me.form,
65810             paramOrder = form.paramOrder,
65811             params = me.getParams(),
65812             i, len;
65813
65814         
65815         if (paramOrder) {
65816             for (i = 0, len = paramOrder.length; i < len; i++) {
65817                 args.push(params[paramOrder[i]]);
65818             }
65819         }
65820         
65821         else if (form.paramsAsHash) {
65822             args.push(params);
65823         }
65824
65825         
65826         args.push(me.onSuccess, me);
65827
65828         return args;
65829     },
65830
65831     
65832     
65833     
65834     processResponse: function(result) {
65835         return (this.result = result);
65836     },
65837
65838     onSuccess: function(result, trans) {
65839         if (trans.type == Ext.direct.Manager.self.exceptions.SERVER) {
65840             result = {};
65841         }
65842         this.callParent([result]);
65843     }
65844 });
65845
65846
65847
65848
65849 Ext.define('Ext.form.action.DirectSubmit', {
65850     extend:'Ext.form.action.Submit',
65851     requires: ['Ext.direct.Manager'],
65852     alternateClassName: 'Ext.form.Action.DirectSubmit',
65853     alias: 'formaction.directsubmit',
65854
65855     type: 'directsubmit',
65856
65857     doSubmit: function() {
65858         var me = this,
65859             callback = Ext.Function.bind(me.onSuccess, me),
65860             formEl = me.buildForm();
65861         me.form.api.submit(formEl, callback, me);
65862         Ext.removeNode(formEl);
65863     },
65864
65865     
65866     
65867     
65868     processResponse: function(result) {
65869         return (this.result = result);
65870     },
65871
65872     onSuccess: function(response, trans) {
65873         if (trans.type === Ext.direct.Manager.self.exceptions.SERVER) {
65874             response = {};
65875         }
65876         this.callParent([response]);
65877     }
65878 });
65879
65880
65881 Ext.define('Ext.form.action.StandardSubmit', {
65882     extend:'Ext.form.action.Submit',
65883     alias: 'formaction.standardsubmit',
65884
65885     
65886
65887     
65888     doSubmit: function() {
65889         var form = this.buildForm();
65890         form.submit();
65891         Ext.removeNode(form);
65892     }
65893
65894 });
65895
65896
65897 Ext.define('Ext.form.field.Checkbox', {
65898     extend: 'Ext.form.field.Base',
65899     alias: ['widget.checkboxfield', 'widget.checkbox'],
65900     alternateClassName: 'Ext.form.Checkbox',
65901     requires: ['Ext.XTemplate', 'Ext.form.CheckboxManager'],
65902
65903     fieldSubTpl: [
65904         '<tpl if="boxLabel && boxLabelAlign == \'before\'">',
65905             '<label class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
65906         '</tpl>',
65907         
65908         
65909         
65910         '<input type="button" id="{id}" ',
65911             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
65912             'class="{fieldCls} {typeCls}" autocomplete="off" hidefocus="true" />',
65913         '<tpl if="boxLabel && boxLabelAlign == \'after\'">',
65914             '<label class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
65915         '</tpl>',
65916         {
65917             disableFormats: true,
65918             compiled: true
65919         }
65920     ],
65921
65922     isCheckbox: true,
65923
65924     
65925     focusCls: Ext.baseCSSPrefix + 'form-cb-focus',
65926
65927     
65928
65929     
65930     fieldBodyCls: Ext.baseCSSPrefix + 'form-cb-wrap',
65931
65932     
65933     checked: false,
65934
65935     
65936     checkedCls: Ext.baseCSSPrefix + 'form-cb-checked',
65937
65938     
65939
65940     
65941     boxLabelCls: Ext.baseCSSPrefix + 'form-cb-label',
65942
65943     
65944     boxLabelAlign: 'after',
65945
65946     
65947     inputValue: 'on',
65948
65949     
65950
65951     
65952
65953     
65954
65955     
65956     checkChangeEvents: [],
65957     inputType: 'checkbox',
65958     ariaRole: 'checkbox',
65959
65960     
65961     onRe: /^on$/i,
65962
65963     initComponent: function(){
65964         this.callParent(arguments);
65965         this.getManager().add(this);
65966     },
65967
65968     initValue: function() {
65969         var me = this,
65970             checked = !!me.checked;
65971
65972         
65973         me.originalValue = me.lastValue = checked;
65974
65975         
65976         me.setValue(checked);
65977     },
65978
65979     
65980     onRender : function(ct, position) {
65981         var me = this;
65982         Ext.applyIf(me.renderSelectors, {
65983             
65984             boxLabelEl: 'label.' + me.boxLabelCls
65985         });
65986         Ext.applyIf(me.subTplData, {
65987             boxLabel: me.boxLabel,
65988             boxLabelCls: me.boxLabelCls,
65989             boxLabelAlign: me.boxLabelAlign
65990         });
65991
65992         me.callParent(arguments);
65993     },
65994
65995     initEvents: function() {
65996         var me = this;
65997         me.callParent();
65998         me.mon(me.inputEl, 'click', me.onBoxClick, me);
65999     },
66000
66001     
66002     onBoxClick: function(e) {
66003         var me = this;
66004         if (!me.disabled && !me.readOnly) {
66005             this.setValue(!this.checked);
66006         }
66007     },
66008
66009     
66010     getRawValue: function() {
66011         return this.checked;
66012     },
66013
66014     
66015     getValue: function() {
66016         return this.checked;
66017     },
66018
66019     
66020     getSubmitValue: function() {
66021         return this.checked ? this.inputValue : (this.uncheckedValue || null);
66022     },
66023
66024     getModelData: function() {
66025         return this.getSubmitData();
66026     },
66027
66028     
66029     setRawValue: function(value) {
66030         var me = this,
66031             inputEl = me.inputEl,
66032             inputValue = me.inputValue,
66033             checked = (value === true || value === 'true' || value === '1' ||
66034                       ((Ext.isString(value) && inputValue) ? value == inputValue : me.onRe.test(value)));
66035
66036         if (inputEl) {
66037             inputEl.dom.setAttribute('aria-checked', checked);
66038             me[checked ? 'addCls' : 'removeCls'](me.checkedCls);
66039         }
66040
66041         me.checked = me.rawValue = checked;
66042         return checked;
66043     },
66044
66045     
66046     setValue: function(checked) {
66047         var me = this;
66048
66049         
66050         
66051         
66052         
66053         if (Ext.isArray(checked)) {
66054             me.getManager().getByName(me.name).each(function(cb) {
66055                 cb.setValue(Ext.Array.contains(checked, cb.inputValue));
66056             });
66057         } else {
66058             me.callParent(arguments);
66059         }
66060
66061         return me;
66062     },
66063
66064     
66065     valueToRaw: function(value) {
66066         
66067         return value;
66068     },
66069
66070     
66071     onChange: function(newVal, oldVal) {
66072         var me = this,
66073             handler = me.handler;
66074         if (handler) {
66075             handler.call(me.scope || me, me, newVal);
66076         }
66077         me.callParent(arguments);
66078     },
66079
66080     
66081     getManager: function() {
66082         return Ext.form.CheckboxManager;
66083     },
66084
66085     onEnable: function() {
66086         var me = this,
66087             inputEl = me.inputEl;
66088         me.callParent();
66089         if (inputEl) {
66090             
66091             inputEl.dom.disabled = me.readOnly;
66092         }
66093     },
66094
66095     setReadOnly: function(readOnly) {
66096         var me = this,
66097             inputEl = me.inputEl;
66098         if (inputEl) {
66099             
66100             inputEl.dom.disabled = readOnly || me.disabled;
66101         }
66102         me.readOnly = readOnly;
66103     },
66104
66105     
66106     getBodyNaturalWidth: function() {
66107         var me = this,
66108             bodyEl = me.bodyEl,
66109             ws = 'white-space',
66110             width;
66111         bodyEl.setStyle(ws, 'nowrap');
66112         width = bodyEl.getWidth();
66113         bodyEl.setStyle(ws, '');
66114         return width;
66115     }
66116
66117 });
66118
66119
66120
66121 Ext.define('Ext.layout.component.field.Trigger', {
66122
66123     
66124
66125     alias: ['layout.triggerfield'],
66126
66127     extend: 'Ext.layout.component.field.Field',
66128
66129     
66130
66131     type: 'triggerfield',
66132
66133     sizeBodyContents: function(width, height) {
66134         var me = this,
66135             owner = me.owner,
66136             inputEl = owner.inputEl,
66137             triggerWrap = owner.triggerWrap,
66138             triggerWidth = owner.getTriggerWidth();
66139
66140         
66141         
66142         if (owner.hideTrigger || owner.readOnly || triggerWidth > 0) {
66143             
66144             
66145             me.setElementSize(inputEl, Ext.isNumber(width) ? width - triggerWidth : width);
66146     
66147             
66148             triggerWrap.setWidth(triggerWidth);
66149         }
66150     }
66151 });
66152
66153 Ext.define('Ext.view.View', {
66154     extend: 'Ext.view.AbstractView',
66155     alternateClassName: 'Ext.view.View',
66156     alias: 'widget.dataview',
66157     
66158     inheritableStatics: {
66159         EventMap: {
66160             mousedown: 'MouseDown',
66161             mouseup: 'MouseUp',
66162             click: 'Click',
66163             dblclick: 'DblClick',
66164             contextmenu: 'ContextMenu',
66165             mouseover: 'MouseOver',
66166             mouseout: 'MouseOut',
66167             mouseenter: 'MouseEnter',
66168             mouseleave: 'MouseLeave',
66169             keydown: 'KeyDown'
66170         }
66171     },
66172     
66173     addCmpEvents: function() {
66174         this.addEvents(
66175             
66176             'beforeitemmousedown',
66177             
66178             'beforeitemmouseup',
66179             
66180             'beforeitemmouseenter',
66181             
66182             'beforeitemmouseleave',
66183             
66184             'beforeitemclick',
66185             
66186             'beforeitemdblclick',
66187             
66188             'beforeitemcontextmenu',
66189             
66190             'beforeitemkeydown',
66191             
66192             'itemmousedown',
66193             
66194             'itemmouseup',
66195             
66196             'itemmouseenter',
66197             
66198             'itemmouseleave',
66199             
66200             'itemclick',
66201             
66202             'itemdblclick',
66203             
66204             'itemcontextmenu',
66205             
66206             'itemkeydown',
66207             
66208             'beforecontainermousedown',
66209             
66210             'beforecontainermouseup',
66211             
66212             'beforecontainermouseover',
66213             
66214             'beforecontainermouseout',
66215             
66216             'beforecontainerclick',
66217             
66218             'beforecontainerdblclick',
66219             
66220             'beforecontainercontextmenu',
66221             
66222             'beforecontainerkeydown',
66223             
66224             'containermouseup',
66225             
66226             'containermouseover',
66227             
66228             'containermouseout',
66229             
66230             'containerclick',
66231             
66232             'containerdblclick',
66233             
66234             'containercontextmenu',
66235             
66236             'containerkeydown',
66237             
66238             
66239             'selectionchange',
66240             
66241             'beforeselect'
66242         );
66243     },
66244     
66245     afterRender: function(){
66246         var me = this, 
66247             listeners;
66248         
66249         me.callParent();
66250
66251         listeners = {
66252             scope: me,
66253             click: me.handleEvent,
66254             mousedown: me.handleEvent,
66255             mouseup: me.handleEvent,
66256             dblclick: me.handleEvent,
66257             contextmenu: me.handleEvent,
66258             mouseover: me.handleEvent,
66259             mouseout: me.handleEvent,
66260             keydown: me.handleEvent
66261         };
66262         
66263         me.mon(me.getTargetEl(), listeners);
66264         
66265         if (me.store) {
66266             me.bindStore(me.store, true);
66267         }
66268     },
66269     
66270     handleEvent: function(e) {
66271         if (this.processUIEvent(e) !== false) {
66272             this.processSpecialEvent(e);
66273         }
66274     },
66275     
66276     
66277     processItemEvent: Ext.emptyFn,
66278     processContainerEvent: Ext.emptyFn,
66279     processSpecialEvent: Ext.emptyFn,
66280     
66281     processUIEvent: function(e, type) {
66282         type = type || e.type;
66283         var me = this,
66284             item = e.getTarget(me.getItemSelector(), me.getTargetEl()),
66285             map = this.statics().EventMap,
66286             index, record;
66287         
66288         if (!item) {
66289             
66290             
66291             
66292             
66293             
66294             
66295             if (type == 'mouseover' && me.mouseOverItem && typeof me.mouseOverItem.offsetParent === "object" && Ext.fly(me.mouseOverItem).getRegion().contains(e.getPoint())) {
66296                 item = me.mouseOverItem;
66297             }
66298             
66299             
66300             if (type == 'keydown') {
66301                 record = me.getSelectionModel().getLastSelected();
66302                 if (record) {
66303                     item = me.getNode(record);
66304                 }
66305             }
66306         }
66307         
66308         if (item) {
66309             index = me.indexOf(item);
66310             if (!record) {
66311                 record = me.getRecord(item);
66312             }
66313             
66314             if (me.processItemEvent(type, record, item, index, e) === false) {
66315                 return false;
66316             }
66317             
66318             type = me.isNewItemEvent(type, item, e);
66319             if (type === false) {
66320                 return false;
66321             }
66322             
66323             if (
66324                 (me['onBeforeItem' + map[type]](record, item, index, e) === false) ||
66325                 (me.fireEvent('beforeitem' + type, me, record, item, index, e) === false) ||
66326                 (me['onItem' + map[type]](record, item, index, e) === false)
66327             ) { 
66328                 return false;
66329             }
66330             
66331             me.fireEvent('item' + type, me, record, item, index, e);
66332         } 
66333         else {
66334             if (
66335                 (me.processContainerEvent(type, e) === false) ||
66336                 (me['onBeforeContainer' + map[type]](e) === false) ||
66337                 (me.fireEvent('beforecontainer' + type, me, e) === false) ||
66338                 (me['onContainer' + map[type]](e) === false)
66339             ) {
66340                 return false;
66341             }
66342             
66343             me.fireEvent('container' + type, me, e);
66344         }
66345         
66346         return true;
66347     },
66348     
66349     isNewItemEvent: function(type, item, e) {
66350         var me = this,
66351             overItem = me.mouseOverItem,
66352             contains,
66353             isItem;
66354             
66355         switch (type) {
66356             case 'mouseover':
66357                 if (item === overItem) {
66358                     return false;
66359                 }
66360                 me.mouseOverItem = item;
66361                 return 'mouseenter';
66362             break;
66363             
66364             case 'mouseout':
66365                
66366                 if (overItem && typeof overItem.offsetParent === "object") {
66367                     contains = Ext.fly(me.mouseOverItem).getRegion().contains(e.getPoint());
66368                     isItem = Ext.fly(e.getTarget()).hasCls(me.itemSelector);
66369                     if (contains && isItem) {
66370                         return false;
66371                     }
66372                 }
66373                 me.mouseOverItem = null;
66374                 return 'mouseleave';
66375             break;
66376         }
66377         return type;
66378     },
66379     
66380     
66381     onItemMouseEnter: function(record, item, index, e) {
66382         if (this.trackOver) {
66383             this.highlightItem(item);
66384         }
66385     },
66386
66387     
66388     onItemMouseLeave : function(record, item, index, e) {
66389         if (this.trackOver) {
66390             this.clearHighlight();
66391         }
66392     },
66393
66394     
66395     onItemMouseDown: Ext.emptyFn,
66396     onItemMouseUp: Ext.emptyFn,
66397     onItemClick: Ext.emptyFn,
66398     onItemDblClick: Ext.emptyFn,
66399     onItemContextMenu: Ext.emptyFn,
66400     onItemKeyDown: Ext.emptyFn,
66401     onBeforeItemMouseDown: Ext.emptyFn,
66402     onBeforeItemMouseUp: Ext.emptyFn,
66403     onBeforeItemMouseEnter: Ext.emptyFn,
66404     onBeforeItemMouseLeave: Ext.emptyFn,
66405     onBeforeItemClick: Ext.emptyFn,
66406     onBeforeItemDblClick: Ext.emptyFn,
66407     onBeforeItemContextMenu: Ext.emptyFn,
66408     onBeforeItemKeyDown: Ext.emptyFn,
66409     
66410     
66411     onContainerMouseDown: Ext.emptyFn,
66412     onContainerMouseUp: Ext.emptyFn,
66413     onContainerMouseOver: Ext.emptyFn,
66414     onContainerMouseOut: Ext.emptyFn,
66415     onContainerClick: Ext.emptyFn,
66416     onContainerDblClick: Ext.emptyFn,
66417     onContainerContextMenu: Ext.emptyFn,
66418     onContainerKeyDown: Ext.emptyFn,
66419     onBeforeContainerMouseDown: Ext.emptyFn,
66420     onBeforeContainerMouseUp: Ext.emptyFn,
66421     onBeforeContainerMouseOver: Ext.emptyFn,
66422     onBeforeContainerMouseOut: Ext.emptyFn,
66423     onBeforeContainerClick: Ext.emptyFn,
66424     onBeforeContainerDblClick: Ext.emptyFn,
66425     onBeforeContainerContextMenu: Ext.emptyFn,
66426     onBeforeContainerKeyDown: Ext.emptyFn,
66427     
66428     
66429     highlightItem: function(item) {
66430         var me = this;
66431         me.clearHighlight();
66432         me.highlightedItem = item;
66433         Ext.fly(item).addCls(me.overItemCls);
66434     },
66435
66436     
66437     clearHighlight: function() {
66438         var me = this,
66439             highlighted = me.highlightedItem;
66440             
66441         if (highlighted) {
66442             Ext.fly(highlighted).removeCls(me.overItemCls);
66443             delete me.highlightedItem;
66444         }
66445     },
66446
66447     refresh: function() {
66448         this.clearHighlight();
66449         this.callParent(arguments);
66450     }
66451 });
66452
66453 Ext.define('Ext.layout.component.BoundList', {
66454     extend: 'Ext.layout.component.Component',
66455     alias: 'layout.boundlist',
66456
66457     type: 'component',
66458
66459     beforeLayout: function() {
66460         return this.callParent(arguments) || this.owner.refreshed > 0;
66461     },
66462
66463     onLayout : function(width, height) {
66464         var me = this,
66465             owner = me.owner,
66466             floating = owner.floating,
66467             el = owner.el,
66468             xy = el.getXY(),
66469             isNumber = Ext.isNumber,
66470             minWidth, maxWidth, minHeight, maxHeight,
66471             naturalWidth, naturalHeight, constrainedWidth, constrainedHeight, undef;
66472
66473         if (floating) {
66474             
66475             el.setXY([-9999,-9999]);
66476         }
66477
66478         
66479         me.setTargetSize(width, height);
66480
66481         
66482         if (!isNumber(width)) {
66483             minWidth = owner.minWidth;
66484             maxWidth = owner.maxWidth;
66485             if (isNumber(minWidth) || isNumber(maxWidth)) {
66486                 naturalWidth = el.getWidth();
66487                 if (naturalWidth < minWidth) {
66488                     constrainedWidth = minWidth;
66489                 }
66490                 else if (naturalWidth > maxWidth) {
66491                     constrainedWidth = maxWidth;
66492                 }
66493                 if (constrainedWidth) {
66494                     me.setTargetSize(constrainedWidth);
66495                 }
66496             }
66497         }
66498         
66499         if (!isNumber(height)) {
66500             minHeight = owner.minHeight;
66501             maxHeight = owner.maxHeight;
66502             if (isNumber(minHeight) || isNumber(maxHeight)) {
66503                 naturalHeight = el.getHeight();
66504                 if (naturalHeight < minHeight) {
66505                     constrainedHeight = minHeight;
66506                 }
66507                 else if (naturalHeight > maxHeight) {
66508                     constrainedHeight = maxHeight;
66509                 }
66510                 if (constrainedHeight) {
66511                     me.setTargetSize(undef, constrainedHeight);
66512                 }
66513             }
66514         }
66515
66516         if (floating) {
66517             
66518             el.setXY(xy);
66519         }
66520     },
66521
66522     afterLayout: function() {
66523         var me = this,
66524             toolbar = me.owner.pagingToolbar;
66525         me.callParent();
66526         if (toolbar) {
66527             toolbar.doComponentLayout();
66528         }
66529     },
66530
66531     setTargetSize : function(width, height) {
66532         var me = this,
66533             owner = me.owner,
66534             listHeight = null,
66535             toolbar;
66536
66537         
66538         if (Ext.isNumber(height)) {
66539             listHeight = height - owner.el.getFrameWidth('tb');
66540             toolbar = owner.pagingToolbar;
66541             if (toolbar) {
66542                 listHeight -= toolbar.getHeight();
66543             }
66544         }
66545         me.setElementSize(owner.listEl, null, listHeight);
66546
66547         me.callParent(arguments);
66548     }
66549
66550 });
66551
66552
66553 Ext.define('Ext.toolbar.TextItem', {
66554     extend: 'Ext.toolbar.Item',
66555     requires: ['Ext.XTemplate'],
66556     alias: 'widget.tbtext',
66557     alternateClassName: 'Ext.Toolbar.TextItem',
66558     
66559     
66560     text: '',
66561     
66562     renderTpl: '{text}',
66563     
66564     baseCls: Ext.baseCSSPrefix + 'toolbar-text',
66565     
66566     onRender : function() {
66567         Ext.apply(this.renderData, {
66568             text: this.text
66569         });
66570         this.callParent(arguments);
66571     },
66572
66573     
66574     setText : function(t) {
66575         if (this.rendered) {
66576             this.el.update(t);
66577             this.ownerCt.doLayout(); 
66578         } else {
66579             this.text = t;
66580         }
66581     }
66582 });
66583
66584 Ext.define('Ext.form.field.Trigger', {
66585     extend:'Ext.form.field.Text',
66586     alias: ['widget.triggerfield', 'widget.trigger'],
66587     requires: ['Ext.core.DomHelper', 'Ext.util.ClickRepeater', 'Ext.layout.component.field.Trigger'],
66588     alternateClassName: ['Ext.form.TriggerField', 'Ext.form.TwinTriggerField', 'Ext.form.Trigger'],
66589
66590     fieldSubTpl: [
66591         '<input id="{id}" type="{type}" ',
66592             '<tpl if="name">name="{name}" </tpl>',
66593             '<tpl if="size">size="{size}" </tpl>',
66594             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
66595             'class="{fieldCls} {typeCls}" autocomplete="off" />',
66596         '<div class="{triggerWrapCls}" role="presentation">',
66597             '{triggerEl}',
66598             '<div class="{clearCls}" role="presentation"></div>',
66599         '</div>',
66600         {
66601             compiled: true,
66602             disableFormats: true
66603         }
66604     ],
66605
66606     
66607
66608     
66609     triggerBaseCls: Ext.baseCSSPrefix + 'form-trigger',
66610
66611     
66612     triggerWrapCls: Ext.baseCSSPrefix + 'form-trigger-wrap',
66613
66614     
66615     hideTrigger: false,
66616
66617     
66618     editable: true,
66619
66620     
66621     readOnly: false,
66622
66623     
66624
66625     
66626     repeatTriggerClick: false,
66627
66628
66629     
66630     autoSize: Ext.emptyFn,
66631     
66632     monitorTab: true,
66633     
66634     mimicing: false,
66635     
66636     triggerIndexRe: /trigger-index-(\d+)/,
66637
66638     componentLayout: 'triggerfield',
66639
66640     initComponent: function() {
66641         this.wrapFocusCls = this.triggerWrapCls + '-focus';
66642         this.callParent(arguments);
66643     },
66644
66645     
66646     onRender: function(ct, position) {
66647         var me = this,
66648             triggerCls,
66649             triggerBaseCls = me.triggerBaseCls,
66650             triggerWrapCls = me.triggerWrapCls,
66651             triggerConfigs = [],
66652             i;
66653
66654         
66655         
66656         
66657         
66658         if (!me.trigger1Cls) {
66659             me.trigger1Cls = me.triggerCls;
66660         }
66661
66662         
66663         for (i = 0; (triggerCls = me['trigger' + (i + 1) + 'Cls']) || i < 1; i++) {
66664             triggerConfigs.push({
66665                 cls: [Ext.baseCSSPrefix + 'trigger-index-' + i, triggerBaseCls, triggerCls].join(' '),
66666                 role: 'button'
66667             });
66668         }
66669         triggerConfigs[i - 1].cls += ' ' + triggerBaseCls + '-last';
66670
66671         Ext.applyIf(me.renderSelectors, {
66672             
66673             triggerWrap: '.' + triggerWrapCls
66674         });
66675         Ext.applyIf(me.subTplData, {
66676             triggerWrapCls: triggerWrapCls,
66677             triggerEl: Ext.core.DomHelper.markup(triggerConfigs),
66678             clearCls: me.clearCls
66679         });
66680
66681         me.callParent(arguments);
66682
66683         
66684         me.triggerEl = Ext.select('.' + triggerBaseCls, true, me.triggerWrap.dom);
66685
66686         me.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
66687         me.initTrigger();
66688     },
66689
66690     onEnable: function() {
66691         this.callParent();
66692         this.triggerWrap.unmask();
66693     },
66694     
66695     onDisable: function() {
66696         this.callParent();
66697         this.triggerWrap.mask();
66698     },
66699     
66700     afterRender: function() {
66701         this.callParent();
66702         this.updateEditState();
66703     },
66704
66705     updateEditState: function() {
66706         var me = this,
66707             inputEl = me.inputEl,
66708             triggerWrap = me.triggerWrap,
66709             noeditCls = Ext.baseCSSPrefix + 'trigger-noedit',
66710             displayed,
66711             readOnly;
66712
66713         if (me.rendered) {
66714             if (me.readOnly) {
66715                 inputEl.addCls(noeditCls);
66716                 readOnly = true;
66717                 displayed = false;
66718             } else {
66719                 if (me.editable) {
66720                     inputEl.removeCls(noeditCls);
66721                     readOnly = false;
66722                 } else {
66723                     inputEl.addCls(noeditCls);
66724                     readOnly = true;
66725                 }
66726                 displayed = !me.hideTrigger;
66727             }
66728
66729             triggerWrap.setDisplayed(displayed);
66730             inputEl.dom.readOnly = readOnly;
66731             me.doComponentLayout();
66732         }
66733     },
66734
66735     
66736     getTriggerWidth: function() {
66737         var me = this,
66738             triggerWrap = me.triggerWrap,
66739             totalTriggerWidth = 0;
66740         if (triggerWrap && !me.hideTrigger && !me.readOnly) {
66741             me.triggerEl.each(function(trigger) {
66742                 totalTriggerWidth += trigger.getWidth();
66743             });
66744             totalTriggerWidth += me.triggerWrap.getFrameWidth('lr');
66745         }
66746         return totalTriggerWidth;
66747     },
66748
66749     setHideTrigger: function(hideTrigger) {
66750         if (hideTrigger != this.hideTrigger) {
66751             this.hideTrigger = hideTrigger;
66752             this.updateEditState();
66753         }
66754     },
66755
66756     
66757     setEditable: function(editable) {
66758         if (editable != this.editable) {
66759             this.editable = editable;
66760             this.updateEditState();
66761         }
66762     },
66763
66764     
66765     setReadOnly: function(readOnly) {
66766         if (readOnly != this.readOnly) {
66767             this.readOnly = readOnly;
66768             this.updateEditState();
66769         }
66770     },
66771
66772     
66773     initTrigger: function() {
66774         var me = this,
66775             triggerWrap = me.triggerWrap,
66776             triggerEl = me.triggerEl;
66777
66778         if (me.repeatTriggerClick) {
66779             me.triggerRepeater = Ext.create('Ext.util.ClickRepeater', triggerWrap, {
66780                 preventDefault: true,
66781                 handler: function(cr, e) {
66782                     me.onTriggerWrapClick(e);
66783                 }
66784             });
66785         } else {
66786             me.mon(me.triggerWrap, 'click', me.onTriggerWrapClick, me);
66787         }
66788
66789         triggerEl.addClsOnOver(me.triggerBaseCls + '-over');
66790         triggerEl.each(function(el, c, i) {
66791             el.addClsOnOver(me['trigger' + (i + 1) + 'Cls'] + '-over');
66792         });
66793         triggerEl.addClsOnClick(me.triggerBaseCls + '-click');
66794         triggerEl.each(function(el, c, i) {
66795             el.addClsOnClick(me['trigger' + (i + 1) + 'Cls'] + '-click');
66796         });
66797     },
66798
66799     
66800     onDestroy: function() {
66801         var me = this;
66802         Ext.destroyMembers(me, 'triggerRepeater', 'triggerWrap', 'triggerEl');
66803         delete me.doc;
66804         me.callParent();
66805     },
66806
66807     
66808     onFocus: function() {
66809         var me = this;
66810         this.callParent();
66811         if (!me.mimicing) {
66812             me.bodyEl.addCls(me.wrapFocusCls);
66813             me.mimicing = true;
66814             me.mon(me.doc, 'mousedown', me.mimicBlur, me, {
66815                 delay: 10
66816             });
66817             if (me.monitorTab) {
66818                 me.on('specialkey', me.checkTab, me);
66819             }
66820         }
66821     },
66822
66823     
66824     checkTab: function(me, e) {
66825         if (!this.ignoreMonitorTab && e.getKey() == e.TAB) {
66826             this.triggerBlur();
66827         }
66828     },
66829
66830     
66831     onBlur: Ext.emptyFn,
66832
66833     
66834     mimicBlur: function(e) {
66835         if (!this.isDestroyed && !this.bodyEl.contains(e.target) && this.validateBlur(e)) {
66836             this.triggerBlur();
66837         }
66838     },
66839
66840     
66841     triggerBlur: function() {
66842         var me = this;
66843         me.mimicing = false;
66844         me.mun(me.doc, 'mousedown', me.mimicBlur, me);
66845         if (me.monitorTab && me.inputEl) {
66846             me.un('specialkey', me.checkTab, me);
66847         }
66848         Ext.form.field.Trigger.superclass.onBlur.call(me);
66849         if (me.bodyEl) {
66850             me.bodyEl.removeCls(me.wrapFocusCls);
66851         }
66852     },
66853
66854     beforeBlur: Ext.emptyFn,
66855
66856     
66857     
66858     validateBlur: function(e) {
66859         return true;
66860     },
66861
66862     
66863     
66864     
66865     onTriggerWrapClick: function(e) {
66866         var me = this,
66867             t = e && e.getTarget('.' + Ext.baseCSSPrefix + 'form-trigger', null),
66868             match = t && t.className.match(me.triggerIndexRe),
66869             idx,
66870             triggerClickMethod;
66871
66872         if (match && !me.readOnly) {
66873             idx = parseInt(match[1], 10);
66874             triggerClickMethod = me['onTrigger' + (idx + 1) + 'Click'] || me.onTriggerClick;
66875             if (triggerClickMethod) {
66876                 triggerClickMethod.call(me, e);
66877             }
66878         }
66879     },
66880
66881     
66882     onTriggerClick: Ext.emptyFn
66883
66884     
66885     
66886     
66887 });
66888
66889
66890 Ext.define('Ext.form.field.Picker', {
66891     extend: 'Ext.form.field.Trigger',
66892     alias: 'widget.pickerfield',
66893     alternateClassName: 'Ext.form.Picker',
66894     requires: ['Ext.util.KeyNav'],
66895
66896     
66897     matchFieldWidth: true,
66898
66899     
66900     pickerAlign: 'tl-bl?',
66901
66902     
66903
66904     
66905     openCls: Ext.baseCSSPrefix + 'pickerfield-open',
66906
66907     
66908
66909     
66910     editable: true,
66911
66912
66913     initComponent: function() {
66914         this.callParent();
66915
66916         
66917         this.addEvents(
66918             
66919             'expand',
66920             
66921             'collapse',
66922             
66923             'select'
66924         );
66925     },
66926
66927
66928     initEvents: function() {
66929         var me = this;
66930         me.callParent();
66931
66932         
66933         me.keyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
66934             down: function() {
66935                 if (!me.isExpanded) {
66936                     
66937                     
66938                     me.onTriggerClick();
66939                 }
66940             },
66941             esc: me.collapse,
66942             scope: me,
66943             forceKeyDown: true
66944         });
66945
66946         
66947         if (!me.editable) {
66948             me.mon(me.inputEl, 'click', me.onTriggerClick, me);
66949         }
66950
66951         
66952         if (Ext.isGecko) {
66953             me.inputEl.dom.setAttribute('autocomplete', 'off');
66954         }
66955     },
66956
66957
66958     
66959     expand: function() {
66960         var me = this,
66961             bodyEl, picker, collapseIf;
66962
66963         if (me.rendered && !me.isExpanded && !me.isDestroyed) {
66964             bodyEl = me.bodyEl;
66965             picker = me.getPicker();
66966             collapseIf = me.collapseIf;
66967
66968             
66969             picker.show();
66970             me.isExpanded = true;
66971             me.alignPicker();
66972             bodyEl.addCls(me.openCls);
66973
66974             
66975             me.mon(Ext.getDoc(), {
66976                 mousewheel: collapseIf,
66977                 mousedown: collapseIf,
66978                 scope: me
66979             });
66980
66981             me.fireEvent('expand', me);
66982             me.onExpand();
66983         }
66984     },
66985
66986     onExpand: Ext.emptyFn,
66987
66988     
66989     alignPicker: function() {
66990         var me = this,
66991             picker, isAbove,
66992             aboveSfx = '-above';
66993
66994         if (this.isExpanded) {
66995             picker = me.getPicker();
66996             if (me.matchFieldWidth) {
66997                 
66998                 picker.setSize(me.bodyEl.getWidth(), picker.store && picker.store.getCount() ? null : 0);
66999             }
67000             if (picker.isFloating()) {
67001                 picker.alignTo(me.inputEl, me.pickerAlign, me.pickerOffset);
67002
67003                 
67004                 
67005                 isAbove = picker.el.getY() < me.inputEl.getY();
67006                 me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls + aboveSfx);
67007                 picker.el[isAbove ? 'addCls' : 'removeCls'](picker.baseCls + aboveSfx);
67008             }
67009         }
67010     },
67011
67012     
67013     collapse: function() {
67014         if (this.isExpanded && !this.isDestroyed) {
67015             var me = this,
67016                 openCls = me.openCls,
67017                 picker = me.picker,
67018                 doc = Ext.getDoc(),
67019                 collapseIf = me.collapseIf,
67020                 aboveSfx = '-above';
67021
67022             
67023             picker.hide();
67024             me.isExpanded = false;
67025
67026             
67027             me.bodyEl.removeCls([openCls, openCls + aboveSfx]);
67028             picker.el.removeCls(picker.baseCls + aboveSfx);
67029
67030             
67031             doc.un('mousewheel', collapseIf, me);
67032             doc.un('mousedown', collapseIf, me);
67033
67034             me.fireEvent('collapse', me);
67035             me.onCollapse();
67036         }
67037     },
67038
67039     onCollapse: Ext.emptyFn,
67040
67041
67042     
67043     collapseIf: function(e) {
67044         var me = this;
67045         if (!me.isDestroyed && !e.within(me.bodyEl, false, true) && !e.within(me.picker.el, false, true)) {
67046             me.collapse();
67047         }
67048     },
67049
67050     
67051     getPicker: function() {
67052         var me = this;
67053         return me.picker || (me.picker = me.createPicker());
67054     },
67055
67056     
67057     createPicker: Ext.emptyFn,
67058
67059     
67060     onTriggerClick: function() {
67061         var me = this;
67062         if (!me.readOnly && !me.disabled) {
67063             if (me.isExpanded) {
67064                 me.collapse();
67065             } else {
67066                 me.expand();
67067             }
67068             me.inputEl.focus();
67069         }
67070     },
67071
67072     mimicBlur: function(e) {
67073         var me = this,
67074             picker = me.picker;
67075         
67076         if (!picker || !e.within(picker.el, false, true)) {
67077             me.callParent(arguments);
67078         }
67079     },
67080
67081     onDestroy : function(){
67082         var me = this;
67083         Ext.destroy(me.picker, me.keyNav);
67084         me.callParent();
67085     }
67086
67087 });
67088
67089
67090
67091 Ext.define('Ext.form.field.Spinner', {
67092     extend: 'Ext.form.field.Trigger',
67093     alias: 'widget.spinnerfield',
67094     alternateClassName: 'Ext.form.Spinner',
67095     requires: ['Ext.util.KeyNav'],
67096
67097     trigger1Cls: Ext.baseCSSPrefix + 'form-spinner-up',
67098     trigger2Cls: Ext.baseCSSPrefix + 'form-spinner-down',
67099
67100     
67101     spinUpEnabled: true,
67102
67103     
67104     spinDownEnabled: true,
67105
67106     
67107     keyNavEnabled: true,
67108
67109     
67110     mouseWheelEnabled: true,
67111
67112     
67113     repeatTriggerClick: true,
67114
67115     
67116     onSpinUp: Ext.emptyFn,
67117
67118     
67119     onSpinDown: Ext.emptyFn,
67120
67121     initComponent: function() {
67122         this.callParent();
67123
67124         this.addEvents(
67125             
67126             'spin',
67127
67128             
67129             'spinup',
67130
67131             
67132             'spindown'
67133         );
67134     },
67135
67136     
67137     onRender: function() {
67138         var me = this,
67139             triggers;
67140
67141         me.callParent(arguments);
67142         triggers = me.triggerEl;
67143
67144         
67145         me.spinUpEl = triggers.item(0);
67146         
67147         me.spinDownEl = triggers.item(1);
67148
67149         
67150         me.setSpinUpEnabled(me.spinUpEnabled);
67151         me.setSpinDownEnabled(me.spinDownEnabled);
67152
67153         
67154         if (me.keyNavEnabled) {
67155             me.spinnerKeyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
67156                 scope: me,
67157                 up: me.spinUp,
67158                 down: me.spinDown
67159             });
67160         }
67161
67162         
67163         if (me.mouseWheelEnabled) {
67164             me.mon(me.bodyEl, 'mousewheel', me.onMouseWheel, me);
67165         }
67166     },
67167
67168     
67169     getTriggerWidth: function() {
67170         return this.hideTrigger || this.readOnly ? 0 : this.spinUpEl.getWidth() + this.triggerWrap.getFrameWidth('lr');
67171     },
67172
67173     
67174     onTrigger1Click: function() {
67175         this.spinUp();
67176     },
67177
67178     
67179     onTrigger2Click: function() {
67180         this.spinDown();
67181     },
67182
67183     
67184     spinUp: function() {
67185         var me = this;
67186         if (me.spinUpEnabled && !me.disabled) {
67187             me.fireEvent('spin', me, 'up');
67188             me.fireEvent('spinup', me);
67189             me.onSpinUp();
67190         }
67191     },
67192
67193     
67194     spinDown: function() {
67195         var me = this;
67196         if (me.spinDownEnabled && !me.disabled) {
67197             me.fireEvent('spin', me, 'down');
67198             me.fireEvent('spindown', me);
67199             me.onSpinDown();
67200         }
67201     },
67202
67203     
67204     setSpinUpEnabled: function(enabled) {
67205         var me = this,
67206             wasEnabled = me.spinUpEnabled;
67207         me.spinUpEnabled = enabled;
67208         if (wasEnabled !== enabled && me.rendered) {
67209             me.spinUpEl[enabled ? 'removeCls' : 'addCls'](me.trigger1Cls + '-disabled');
67210         }
67211     },
67212
67213     
67214     setSpinDownEnabled: function(enabled) {
67215         var me = this,
67216             wasEnabled = me.spinDownEnabled;
67217         me.spinDownEnabled = enabled;
67218         if (wasEnabled !== enabled && me.rendered) {
67219             me.spinDownEl[enabled ? 'removeCls' : 'addCls'](me.trigger2Cls + '-disabled');
67220         }
67221     },
67222
67223     
67224     onMouseWheel: function(e) {
67225         var me = this,
67226             delta;
67227         if (me.hasFocus) {
67228             delta = e.getWheelDelta();
67229             if (delta > 0) {
67230                 me.spinUp();
67231             }
67232             else if (delta < 0) {
67233                 me.spinDown();
67234             }
67235             e.stopEvent();
67236         }
67237     },
67238
67239     onDestroy: function() {
67240         Ext.destroyMembers(this, 'spinnerKeyNav', 'spinUpEl', 'spinDownEl');
67241         this.callParent();
67242     }
67243
67244 });
67245
67246 Ext.define('Ext.form.field.Number', {
67247     extend:'Ext.form.field.Spinner',
67248     alias: 'widget.numberfield',
67249     alternateClassName: ['Ext.form.NumberField', 'Ext.form.Number'],
67250
67251     
67252     
67253
67254     
67255     allowDecimals : true,
67256
67257     
67258     decimalSeparator : '.',
67259
67260     
67261     decimalPrecision : 2,
67262
67263     
67264     minValue: Number.NEGATIVE_INFINITY,
67265
67266     
67267     maxValue: Number.MAX_VALUE,
67268
67269     
67270     step: 1,
67271
67272     
67273     minText : 'The minimum value for this field is {0}',
67274
67275     
67276     maxText : 'The maximum value for this field is {0}',
67277
67278     
67279     nanText : '{0} is not a valid number',
67280
67281     
67282     negativeText : 'The value cannot be negative',
67283
67284     
67285     baseChars : '0123456789',
67286
67287     
67288     autoStripChars: false,
67289
67290     initComponent: function() {
67291         var me = this,
67292             allowed;
67293
67294         this.callParent();
67295
67296         me.setMinValue(me.minValue);
67297         me.setMaxValue(me.maxValue);
67298
67299         
67300         allowed = me.baseChars + '';
67301         if (me.allowDecimals) {
67302             allowed += me.decimalSeparator;
67303         }
67304         if (me.minValue < 0) {
67305             allowed += '-';
67306         }
67307         allowed = Ext.String.escapeRegex(allowed);
67308         me.maskRe = new RegExp('[' + allowed + ']');
67309         if (me.autoStripChars) {
67310             me.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
67311         }
67312     },
67313
67314     
67315     getErrors: function(value) {
67316         var me = this,
67317             errors = me.callParent(arguments),
67318             format = Ext.String.format,
67319             num;
67320
67321         value = Ext.isDefined(value) ? value : this.processRawValue(this.getRawValue());
67322
67323         if (value.length < 1) { 
67324              return errors;
67325         }
67326
67327         value = String(value).replace(me.decimalSeparator, '.');
67328
67329         if(isNaN(value)){
67330             errors.push(format(me.nanText, value));
67331         }
67332
67333         num = me.parseValue(value);
67334
67335         if (me.minValue === 0 && num < 0) {
67336             errors.push(this.negativeText);
67337         }
67338         else if (num < me.minValue) {
67339             errors.push(format(me.minText, me.minValue));
67340         }
67341
67342         if (num > me.maxValue) {
67343             errors.push(format(me.maxText, me.maxValue));
67344         }
67345
67346
67347         return errors;
67348     },
67349
67350     rawToValue: function(rawValue) {
67351         return this.fixPrecision(this.parseValue(rawValue)) || rawValue || null;
67352     },
67353
67354     valueToRaw: function(value) {
67355         var me = this,
67356             decimalSeparator = me.decimalSeparator;
67357         value = me.parseValue(value);
67358         value = me.fixPrecision(value);
67359         value = Ext.isNumber(value) ? value : parseFloat(String(value).replace(decimalSeparator, '.'));
67360         value = isNaN(value) ? '' : String(value).replace('.', decimalSeparator);
67361         return value;
67362     },
67363
67364     onChange: function() {
67365         var me = this,
67366             value = me.getValue(),
67367             valueIsNull = value === null;
67368
67369         me.callParent(arguments);
67370
67371         
67372         me.setSpinUpEnabled(valueIsNull || value < me.maxValue);
67373         me.setSpinDownEnabled(valueIsNull || value > me.minValue);
67374     },
67375
67376     
67377     setMinValue : function(value) {
67378         this.minValue = Ext.Number.from(value, Number.NEGATIVE_INFINITY);
67379     },
67380
67381     
67382     setMaxValue: function(value) {
67383         this.maxValue = Ext.Number.from(value, Number.MAX_VALUE);
67384     },
67385
67386     
67387     parseValue : function(value) {
67388         value = parseFloat(String(value).replace(this.decimalSeparator, '.'));
67389         return isNaN(value) ? null : value;
67390     },
67391
67392     
67393     fixPrecision : function(value) {
67394         var me = this,
67395             nan = isNaN(value),
67396             precision = me.decimalPrecision;
67397
67398         if (nan || !value) {
67399             return nan ? '' : value;
67400         } else if (!me.allowDecimals || precision <= 0) {
67401             precision = 0;
67402         }
67403
67404         return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
67405     },
67406
67407     beforeBlur : function() {
67408         var me = this,
67409             v = me.parseValue(me.getRawValue());
67410
67411         if (!Ext.isEmpty(v)) {
67412             me.setValue(v);
67413         }
67414     },
67415
67416     onSpinUp: function() {
67417         var me = this;
67418         if (!me.readOnly) {
67419             me.setValue(Ext.Number.constrain(me.getValue() + me.step, me.minValue, me.maxValue));
67420         }
67421     },
67422
67423     onSpinDown: function() {
67424         var me = this;
67425         if (!me.readOnly) {
67426             me.setValue(Ext.Number.constrain(me.getValue() - me.step, me.minValue, me.maxValue));
67427         }
67428     }
67429 });
67430
67431
67432 Ext.define('Ext.toolbar.Paging', {
67433     extend: 'Ext.toolbar.Toolbar',
67434     alias: 'widget.pagingtoolbar',
67435     alternateClassName: 'Ext.PagingToolbar',
67436     requires: ['Ext.toolbar.TextItem', 'Ext.form.field.Number'],
67437     
67438     
67439     displayInfo: false,
67440     
67441     prependButtons: false,
67442     
67443     displayMsg : 'Displaying {0} - {1} of {2}',
67444     
67445     emptyMsg : 'No data to display',
67446     
67447     beforePageText : 'Page',
67448     
67449     afterPageText : 'of {0}',
67450     
67451     firstText : 'First Page',
67452     
67453     prevText : 'Previous Page',
67454     
67455     nextText : 'Next Page',
67456     
67457     lastText : 'Last Page',
67458     
67459     refreshText : 'Refresh',
67460     
67461     inputItemWidth : 30,
67462     
67463     
67464     getPagingItems: function() {
67465         var me = this;
67466         
67467         return [{
67468             itemId: 'first',
67469             tooltip: me.firstText,
67470             overflowText: me.firstText,
67471             iconCls: Ext.baseCSSPrefix + 'tbar-page-first',
67472             disabled: true,
67473             handler: me.moveFirst,
67474             scope: me
67475         },{
67476             itemId: 'prev',
67477             tooltip: me.prevText,
67478             overflowText: me.prevText,
67479             iconCls: Ext.baseCSSPrefix + 'tbar-page-prev',
67480             disabled: true,
67481             handler: me.movePrevious,
67482             scope: me
67483         },
67484         '-',
67485         me.beforePageText,
67486         {
67487             xtype: 'numberfield',
67488             itemId: 'inputItem',
67489             name: 'inputItem',
67490             cls: Ext.baseCSSPrefix + 'tbar-page-number',
67491             allowDecimals: false,
67492             minValue: 1,
67493             hideTrigger: true,
67494             enableKeyEvents: true,
67495             selectOnFocus: true,
67496             submitValue: false,
67497             width: me.inputItemWidth,
67498             margins: '-1 2 3 2',
67499             listeners: {
67500                 scope: me,
67501                 keydown: me.onPagingKeyDown,
67502                 blur: me.onPagingBlur
67503             }
67504         },{
67505             xtype: 'tbtext',
67506             itemId: 'afterTextItem',
67507             text: Ext.String.format(me.afterPageText, 1)
67508         },
67509         '-',
67510         {
67511             itemId: 'next',
67512             tooltip: me.nextText,
67513             overflowText: me.nextText,
67514             iconCls: Ext.baseCSSPrefix + 'tbar-page-next',
67515             disabled: true,
67516             handler: me.moveNext,
67517             scope: me
67518         },{
67519             itemId: 'last',
67520             tooltip: me.lastText,
67521             overflowText: me.lastText,
67522             iconCls: Ext.baseCSSPrefix + 'tbar-page-last',
67523             disabled: true,
67524             handler: me.moveLast,
67525             scope: me
67526         },
67527         '-',
67528         {
67529             itemId: 'refresh',
67530             tooltip: me.refreshText,
67531             overflowText: me.refreshText,
67532             iconCls: Ext.baseCSSPrefix + 'tbar-loading',
67533             handler: me.doRefresh,
67534             scope: me
67535         }];
67536     },
67537
67538     initComponent : function(){
67539         var me = this,
67540             pagingItems = me.getPagingItems(),
67541             userItems   = me.items || me.buttons || [];
67542             
67543         if (me.prependButtons) {
67544             me.items = userItems.concat(pagingItems);
67545         } else {
67546             me.items = pagingItems.concat(userItems);
67547         }
67548         delete me.buttons;
67549         
67550         if (me.displayInfo) {
67551             me.items.push('->');
67552             me.items.push({xtype: 'tbtext', itemId: 'displayItem'});
67553         }
67554         
67555         me.callParent();
67556         
67557         me.addEvents(
67558             
67559             'change',
67560             
67561             'beforechange'
67562         );
67563         me.on('afterlayout', me.onLoad, me, {single: true});
67564
67565         me.bindStore(me.store, true);
67566     },
67567     
67568     updateInfo : function(){
67569         var me = this,
67570             displayItem = me.child('#displayItem'),
67571             store = me.store,
67572             pageData = me.getPageData(),
67573             count, msg;
67574
67575         if (displayItem) {
67576             count = store.getCount();
67577             if (count === 0) {
67578                 msg = me.emptyMsg;
67579             } else {
67580                 msg = Ext.String.format(
67581                     me.displayMsg,
67582                     pageData.fromRecord,
67583                     pageData.toRecord,
67584                     pageData.total
67585                 );
67586             }
67587             displayItem.setText(msg);
67588             me.doComponentLayout();
67589         }
67590     },
67591
67592     
67593     onLoad : function(){
67594         var me = this,
67595             pageData,
67596             currPage,
67597             pageCount,
67598             afterText;
67599             
67600         if (!me.rendered) {
67601             return;
67602         }
67603
67604         pageData = me.getPageData();
67605         currPage = pageData.currentPage;
67606         pageCount = pageData.pageCount;
67607         afterText = Ext.String.format(me.afterPageText, isNaN(pageCount) ? 1 : pageCount);
67608
67609         me.child('#afterTextItem').setText(afterText);
67610         me.child('#inputItem').setValue(currPage);
67611         me.child('#first').setDisabled(currPage === 1);
67612         me.child('#prev').setDisabled(currPage === 1);
67613         me.child('#next').setDisabled(currPage === pageCount);
67614         me.child('#last').setDisabled(currPage === pageCount);
67615         me.child('#refresh').enable();
67616         me.updateInfo();
67617         me.fireEvent('change', me, pageData);
67618     },
67619
67620     
67621     getPageData : function(){
67622         var store = this.store,
67623             totalCount = store.getTotalCount();
67624             
67625         return {
67626             total : totalCount,
67627             currentPage : store.currentPage,
67628             pageCount: Math.ceil(totalCount / store.pageSize),
67629             
67630             fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
67631             toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
67632             
67633         };
67634     },
67635
67636     
67637     onLoadError : function(){
67638         if (!this.rendered) {
67639             return;
67640         }
67641         this.child('#refresh').enable();
67642     },
67643
67644     
67645     readPageFromInput : function(pageData){
67646         var v = this.child('#inputItem').getValue(),
67647             pageNum = parseInt(v, 10);
67648             
67649         if (!v || isNaN(pageNum)) {
67650             this.child('#inputItem').setValue(pageData.currentPage);
67651             return false;
67652         }
67653         return pageNum;
67654     },
67655
67656     onPagingFocus : function(){
67657         this.child('#inputItem').select();
67658     },
67659
67660     
67661     onPagingBlur : function(e){
67662         var curPage = this.getPageData().currentPage;
67663         this.child('#inputItem').setValue(curPage);
67664     },
67665
67666     
67667     onPagingKeyDown : function(field, e){
67668         var k = e.getKey(),
67669             pageData = this.getPageData(),
67670             increment = e.shiftKey ? 10 : 1,
67671             pageNum,
67672             me = this;
67673
67674         if (k == e.RETURN) {
67675             e.stopEvent();
67676             pageNum = me.readPageFromInput(pageData);
67677             if (pageNum !== false) {
67678                 pageNum = Math.min(Math.max(1, pageNum), pageData.total);
67679                 if(me.fireEvent('beforechange', me, pageNum) !== false){
67680                     me.store.loadPage(pageNum);
67681                 }
67682             }
67683         } else if (k == e.HOME || k == e.END) {
67684             e.stopEvent();
67685             pageNum = k == e.HOME ? 1 : pageData.pageCount;
67686             field.setValue(pageNum);
67687         } else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN) {
67688             e.stopEvent();
67689             pageNum = me.readPageFromInput(pageData);
67690             if (pageNum) {
67691                 if (k == e.DOWN || k == e.PAGEDOWN) {
67692                     increment *= -1;
67693                 }
67694                 pageNum += increment;
67695                 if (pageNum >= 1 && pageNum <= pageData.pages) {
67696                     field.setValue(pageNum);
67697                 }
67698             }
67699         }
67700     },
67701
67702     
67703     beforeLoad : function(){
67704         if(this.rendered && this.refresh){
67705             this.refresh.disable();
67706         }
67707     },
67708
67709     
67710     doLoad : function(start){
67711         if(this.fireEvent('beforechange', this, o) !== false){
67712             this.store.load();
67713         }
67714     },
67715
67716     
67717     moveFirst : function(){
67718         var me = this;
67719         if(me.fireEvent('beforechange', me, 1) !== false){
67720             me.store.loadPage(1);
67721         }
67722     },
67723
67724     
67725     movePrevious : function(){
67726         var me = this,
67727             prev = me.store.currentPage - 1;
67728         
67729         if(me.fireEvent('beforechange', me, prev) !== false){
67730             me.store.previousPage();
67731         }
67732     },
67733
67734     
67735     moveNext : function(){
67736         var me = this;        
67737         if(me.fireEvent('beforechange', me, me.store.currentPage + 1) !== false){
67738             me.store.nextPage();
67739         }
67740     },
67741
67742     
67743     moveLast : function(){
67744         var me = this, 
67745             last = this.getPageData().pageCount;
67746         
67747         if(me.fireEvent('beforechange', me, last) !== false){
67748             me.store.loadPage(last);
67749         }
67750     },
67751
67752     
67753     doRefresh : function(){
67754         var me = this,
67755             current = me.store.currentPage;
67756         
67757         if(me.fireEvent('beforechange', me, current) !== false){
67758             me.store.loadPage(current);
67759         }
67760     },
67761
67762     
67763     bindStore : function(store, initial){
67764         var me = this;
67765         
67766         if (!initial && me.store) {
67767             if(store !== me.store && me.store.autoDestroy){
67768                 me.store.destroy();
67769             }else{
67770                 me.store.un('beforeload', me.beforeLoad, me);
67771                 me.store.un('load', me.onLoad, me);
67772                 me.store.un('exception', me.onLoadError, me);
67773             }
67774             if(!store){
67775                 me.store = null;
67776             }
67777         }
67778         if (store) {
67779             store = Ext.data.StoreManager.lookup(store);
67780             store.on({
67781                 scope: me,
67782                 beforeload: me.beforeLoad,
67783                 load: me.onLoad,
67784                 exception: me.onLoadError
67785             });
67786         }
67787         me.store = store;
67788     },
67789
67790     
67791     unbind : function(store){
67792         this.bindStore(null);
67793     },
67794
67795     
67796     bind : function(store){
67797         this.bindStore(store);
67798     },
67799
67800     
67801     onDestroy : function(){
67802         this.bindStore(null);
67803         this.callParent();
67804     }
67805 });
67806
67807
67808 Ext.define('Ext.view.BoundList', {
67809     extend: 'Ext.view.View',
67810     alias: 'widget.boundlist',
67811     alternateClassName: 'Ext.BoundList',
67812     requires: ['Ext.layout.component.BoundList', 'Ext.toolbar.Paging'],
67813
67814     
67815     pageSize: 0,
67816
67817     
67818
67819     
67820     autoScroll: true,
67821     baseCls: Ext.baseCSSPrefix + 'boundlist',
67822     listItemCls: '',
67823     shadow: false,
67824     trackOver: true,
67825     refreshed: 0,
67826
67827     ariaRole: 'listbox',
67828
67829     componentLayout: 'boundlist',
67830
67831     renderTpl: ['<div class="list-ct"></div>'],
67832
67833     initComponent: function() {
67834         var me = this,
67835             baseCls = me.baseCls,
67836             itemCls = baseCls + '-item';
67837         me.itemCls = itemCls;
67838         me.selectedItemCls = baseCls + '-selected';
67839         me.overItemCls = baseCls + '-item-over';
67840         me.itemSelector = "." + itemCls;
67841
67842         if (me.floating) {
67843             me.addCls(baseCls + '-floating');
67844         }
67845
67846         
67847         
67848         me.tpl = Ext.create('Ext.XTemplate', 
67849             '<ul><tpl for=".">',
67850                 '<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
67851             '</tpl></ul>'
67852         );
67853
67854         if (me.pageSize) {
67855             me.pagingToolbar = me.createPagingToolbar();
67856         }
67857
67858         me.callParent();
67859
67860         Ext.applyIf(me.renderSelectors, {
67861             listEl: '.list-ct'
67862         });
67863     },
67864
67865     createPagingToolbar: function() {
67866         return Ext.widget('pagingtoolbar', {
67867             pageSize: this.pageSize,
67868             store: this.store,
67869             border: false
67870         });
67871     },
67872
67873     onRender: function() {
67874         var me = this,
67875             toolbar = me.pagingToolbar;
67876         me.callParent(arguments);
67877         if (toolbar) {
67878             toolbar.render(me.el);
67879         }
67880     },
67881
67882     bindStore : function(store, initial) {
67883         var me = this,
67884             toolbar = me.pagingToolbar;
67885         me.callParent(arguments);
67886         if (toolbar) {
67887             toolbar.bindStore(store, initial);
67888         }
67889     },
67890
67891     getTargetEl: function() {
67892         return this.listEl || this.el;
67893     },
67894
67895     getInnerTpl: function(displayField) {
67896         return '{' + displayField + '}';
67897     },
67898
67899     refresh: function() {
67900         var me = this;
67901         me.callParent();
67902         if (me.isVisible()) {
67903             me.refreshed++;
67904             me.doComponentLayout();
67905             me.refreshed--;
67906         }
67907     },
67908     
67909     initAria: function() {
67910         this.callParent();
67911         
67912         var selModel = this.getSelectionModel(),
67913             mode     = selModel.getSelectionMode(),
67914             actionEl = this.getActionEl();
67915         
67916         
67917         if (mode !== 'SINGLE') {
67918             actionEl.dom.setAttribute('aria-multiselectable', true);
67919         }
67920     },
67921
67922     onDestroy: function() {
67923         Ext.destroyMembers(this, 'pagingToolbar', 'listEl');
67924         this.callParent();
67925     }
67926 });
67927
67928
67929 Ext.define('Ext.view.BoundListKeyNav', {
67930     extend: 'Ext.util.KeyNav',
67931     requires: 'Ext.view.BoundList',
67932
67933     
67934
67935     constructor: function(el, config) {
67936         var me = this;
67937         me.boundList = config.boundList;
67938         me.callParent([el, Ext.apply({}, config, me.defaultHandlers)]);
67939     },
67940
67941     defaultHandlers: {
67942         up: function() {
67943             var me = this,
67944                 boundList = me.boundList,
67945                 allItems = boundList.all,
67946                 oldItem = boundList.highlightedItem,
67947                 oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1,
67948                 newItemIdx = oldItemIdx > 0 ? oldItemIdx - 1 : allItems.getCount() - 1; 
67949             me.highlightAt(newItemIdx);
67950         },
67951
67952         down: function() {
67953             var me = this,
67954                 boundList = me.boundList,
67955                 allItems = boundList.all,
67956                 oldItem = boundList.highlightedItem,
67957                 oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1,
67958                 newItemIdx = oldItemIdx < allItems.getCount() - 1 ? oldItemIdx + 1 : 0; 
67959             me.highlightAt(newItemIdx);
67960         },
67961
67962         pageup: function() {
67963             
67964         },
67965
67966         pagedown: function() {
67967             
67968         },
67969
67970         home: function() {
67971             this.highlightAt(0);
67972         },
67973
67974         end: function() {
67975             var me = this;
67976             me.highlightAt(me.boundList.all.getCount() - 1);
67977         },
67978
67979         enter: function(e) {
67980             this.selectHighlighted(e);
67981         }
67982     },
67983
67984     
67985     highlightAt: function(index) {
67986         var boundList = this.boundList,
67987             item = boundList.all.item(index);
67988         if (item) {
67989             item = item.dom;
67990             boundList.highlightItem(item);
67991             boundList.getTargetEl().scrollChildIntoView(item, false);
67992         }
67993     },
67994
67995     
67996     selectHighlighted: function(e) {
67997         var me = this,
67998             boundList = me.boundList,
67999             highlighted = boundList.highlightedItem,
68000             selModel = boundList.getSelectionModel();
68001         if (highlighted) {
68002             selModel.selectWithEvent(boundList.getRecord(highlighted), e);
68003         }
68004     }
68005
68006 });
68007
68008 Ext.define('Ext.form.field.ComboBox', {
68009     extend:'Ext.form.field.Picker',
68010     requires: ['Ext.util.DelayedTask', 'Ext.EventObject', 'Ext.view.BoundList', 'Ext.view.BoundListKeyNav', 'Ext.data.StoreManager'],
68011     alternateClassName: 'Ext.form.ComboBox',
68012     alias: ['widget.combobox', 'widget.combo'],
68013
68014     
68015     triggerCls: Ext.baseCSSPrefix + 'form-arrow-trigger',
68016
68017     
68018
68019     
68020     multiSelect: false,
68021
68022     
68023     delimiter: ', ',
68024
68025     
68026     displayField: 'text',
68027
68028     
68029
68030     
68031     triggerAction: 'all',
68032
68033     
68034     allQuery: '',
68035
68036     
68037     queryParam: 'query',
68038
68039     
68040     queryMode: 'remote',
68041
68042     queryCaching: true,
68043
68044     
68045     pageSize: 0,
68046
68047     
68048
68049     
68050
68051     
68052     autoSelect: true,
68053
68054     
68055     typeAhead: false,
68056
68057     
68058     typeAheadDelay: 250,
68059
68060     
68061     selectOnTab: true,
68062
68063     
68064     forceSelection: false,
68065
68066     
68067
68068     
68069
68070     
68071     defaultListConfig: {
68072         emptyText: '',
68073         loadingText: 'Loading...',
68074         loadingHeight: 70,
68075         minWidth: 70,
68076         maxHeight: 300,
68077         shadow: 'sides'
68078     },
68079
68080     
68081
68082     
68083
68084     
68085     ignoreSelection: 0,
68086
68087     initComponent: function() {
68088         var me = this,
68089             isDefined = Ext.isDefined,
68090             store = me.store,
68091             transform = me.transform,
68092             transformSelect, isLocalMode;
68093
68094         if (!store && !transform) {
68095             Ext.Error.raise('Either a valid store, or a HTML select to transform, must be configured on the combo.');
68096         }
68097         if (me.typeAhead && me.multiSelect) {
68098             Ext.Error.raise('typeAhead and multiSelect are mutually exclusive options -- please remove one of them.');
68099         }
68100         if (me.typeAhead && !me.editable) {
68101             Ext.Error.raise('If typeAhead is enabled the combo must be editable: true -- please change one of those settings.');
68102         }
68103         if (me.selectOnFocus && !me.editable) {
68104             Ext.Error.raise('If selectOnFocus is enabled the combo must be editable: true -- please change one of those settings.');
68105         }
68106
68107         this.addEvents(
68108             
68109
68110             
68111             'beforequery',
68112
68113             
68114             'select'
68115         );
68116
68117         
68118         if (!store && transform) {
68119             transformSelect = Ext.getDom(transform);
68120             if (transformSelect) {
68121                 store = Ext.Array.map(Ext.Array.from(transformSelect.options), function(option) {
68122                     return [option.value, option.text];
68123                 });
68124                 if (!me.name) {
68125                     me.name = transformSelect.name;
68126                 }
68127                 if (!('value' in me)) {
68128                     me.value = transformSelect.value;
68129                 }
68130             }
68131         }
68132
68133         me.bindStore(store, true);
68134         store = me.store;
68135         if (store.autoCreated) {
68136             me.queryMode = 'local';
68137             me.valueField = me.displayField = 'field1';
68138             if (!store.expanded) {
68139                 me.displayField = 'field2';
68140             }
68141         }
68142
68143
68144         if (!isDefined(me.valueField)) {
68145             me.valueField = me.displayField;
68146         }
68147
68148         isLocalMode = me.queryMode === 'local';
68149         if (!isDefined(me.queryDelay)) {
68150             me.queryDelay = isLocalMode ? 10 : 500;
68151         }
68152         if (!isDefined(me.minChars)) {
68153             me.minChars = isLocalMode ? 0 : 4;
68154         }
68155
68156         if (!me.displayTpl) {
68157             me.displayTpl = Ext.create('Ext.XTemplate',
68158                 '<tpl for=".">' +
68159                     '{[typeof values === "string" ? values : values.' + me.displayField + ']}' +
68160                     '<tpl if="xindex < xcount">' + me.delimiter + '</tpl>' +
68161                 '</tpl>'
68162             );
68163         } else if (Ext.isString(me.displayTpl)) {
68164             me.displayTpl = Ext.create('Ext.XTemplate', me.displayTpl);
68165         }
68166
68167         me.callParent();
68168
68169         me.doQueryTask = Ext.create('Ext.util.DelayedTask', me.doRawQuery, me);
68170
68171         
68172         if (me.store.getCount() > 0) {
68173             me.setValue(me.value);
68174         }
68175
68176         
68177         if (transformSelect) {
68178             me.render(transformSelect.parentNode, transformSelect);
68179             Ext.removeNode(transformSelect);
68180             delete me.renderTo;
68181         }
68182     },
68183
68184     beforeBlur: function() {
68185         var me = this;
68186         me.doQueryTask.cancel();
68187         if (me.forceSelection) {
68188             me.assertValue();
68189         } else {
68190             me.collapse();
68191         }
68192     },
68193
68194     
68195     assertValue: function() {
68196         var me = this,
68197             value = me.getRawValue(),
68198             rec;
68199
68200         if (me.multiSelect) {
68201             
68202             
68203             if (value !== me.getDisplayValue()) {
68204                 me.setValue(me.lastSelection);
68205             }
68206         } else {
68207             
68208             
68209             rec = me.findRecordByDisplay(value);
68210             if (rec) {
68211                 me.select(rec);
68212             } else {
68213                 me.setValue(me.lastSelection);
68214             }
68215         }
68216         me.collapse();
68217     },
68218
68219     onTypeAhead: function() {
68220         var me = this,
68221             displayField = me.displayField,
68222             record = me.store.findRecord(displayField, me.getRawValue()),
68223             boundList = me.getPicker(),
68224             newValue, len, selStart;
68225
68226         if (record) {
68227             newValue = record.get(displayField);
68228             len = newValue.length;
68229             selStart = me.getRawValue().length;
68230
68231             boundList.highlightItem(boundList.getNode(record));
68232
68233             if (selStart !== 0 && selStart !== len) {
68234                 me.setRawValue(newValue);
68235                 me.selectText(selStart, newValue.length);
68236             }
68237         }
68238     },
68239
68240     
68241     
68242     resetToDefault: function() {
68243
68244     },
68245
68246     bindStore: function(store, initial) {
68247         var me = this,
68248             oldStore = me.store;
68249
68250         
68251         
68252         if (oldStore && !initial) {
68253             if (oldStore !== store && oldStore.autoDestroy) {
68254                 oldStore.destroy();
68255             } else {
68256                 oldStore.un({
68257                     scope: me,
68258                     load: me.onLoad,
68259                     exception: me.collapse
68260                 });
68261             }
68262             if (!store) {
68263                 me.store = null;
68264                 if (me.picker) {
68265                     me.picker.bindStore(null);
68266                 }
68267             }
68268         }
68269         if (store) {
68270             if (!initial) {
68271                 me.resetToDefault();
68272             }
68273
68274             me.store = Ext.data.StoreManager.lookup(store);
68275             me.store.on({
68276                 scope: me,
68277                 load: me.onLoad,
68278                 exception: me.collapse
68279             });
68280
68281             if (me.picker) {
68282                 me.picker.bindStore(store);
68283             }
68284         }
68285     },
68286
68287     onLoad: function() {
68288         var me = this,
68289             value = me.value;
68290
68291         me.syncSelection();
68292         if (me.picker && !me.picker.getSelectionModel().hasSelection()) {
68293             me.doAutoSelect();
68294         }
68295     },
68296
68297     
68298     doRawQuery: function() {
68299         this.doQuery(this.getRawValue());
68300     },
68301
68302     
68303     doQuery: function(queryString, forceAll) {
68304         queryString = queryString || '';
68305
68306         
68307         
68308         var me = this,
68309             qe = {
68310                 query: queryString,
68311                 forceAll: forceAll,
68312                 combo: me,
68313                 cancel: false
68314             },
68315             store = me.store,
68316             isLocalMode = me.queryMode === 'local';
68317
68318         if (me.fireEvent('beforequery', qe) === false || qe.cancel) {
68319             return false;
68320         }
68321
68322         
68323         queryString = qe.query;
68324         forceAll = qe.forceAll;
68325
68326         
68327         if (forceAll || (queryString.length >= me.minChars)) {
68328             
68329             me.expand();
68330
68331             
68332             if (!me.queryCaching || me.lastQuery !== queryString) {
68333                 me.lastQuery = queryString;
68334                 store.clearFilter(!forceAll);
68335                 if (isLocalMode) {
68336                     if (!forceAll) {
68337                         store.filter(me.displayField, queryString);
68338                     }
68339                 } else {
68340                     store.load({
68341                         params: me.getParams(queryString)
68342                     });
68343                 }
68344             }
68345
68346             
68347             if (me.getRawValue() !== me.getDisplayValue()) {
68348                 me.ignoreSelection++;
68349                 me.picker.getSelectionModel().deselectAll();
68350                 me.ignoreSelection--;
68351             }
68352
68353             if (isLocalMode) {
68354                 me.doAutoSelect();
68355             }
68356             if (me.typeAhead) {
68357                 me.doTypeAhead();
68358             }
68359         }
68360         return true;
68361     },
68362
68363     
68364     getParams: function(queryString) {
68365         var p = {},
68366             pageSize = this.pageSize;
68367         p[this.queryParam] = queryString;
68368         if (pageSize) {
68369             p.start = 0;
68370             p.limit = pageSize;
68371         }
68372         return p;
68373     },
68374
68375     
68376     doAutoSelect: function() {
68377         var me = this,
68378             picker = me.picker,
68379             lastSelected, itemNode;
68380         if (picker && me.autoSelect && me.store.getCount() > 0) {
68381             
68382             lastSelected = picker.getSelectionModel().lastSelected;
68383             itemNode = picker.getNode(lastSelected || 0);
68384             if (itemNode) {
68385                 picker.highlightItem(itemNode);
68386                 picker.listEl.scrollChildIntoView(itemNode, false);
68387             }
68388         }
68389     },
68390
68391     doTypeAhead: function() {
68392         if (!this.typeAheadTask) {
68393             this.typeAheadTask = Ext.create('Ext.util.DelayedTask', this.onTypeAhead, this);
68394         }
68395         if (this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE) {
68396             this.typeAheadTask.delay(this.typeAheadDelay);
68397         }
68398     },
68399
68400     onTriggerClick: function() {
68401         var me = this;
68402         if (!me.readOnly && !me.disabled) {
68403             if (me.isExpanded) {
68404                 me.collapse();
68405             } else {
68406                 me.onFocus({});
68407                 if (me.triggerAction === 'all') {
68408                     me.doQuery(me.allQuery, true);
68409                 } else {
68410                     me.doQuery(me.getRawValue());
68411                 }
68412             }
68413             me.inputEl.focus();
68414         }
68415     },
68416
68417
68418     
68419     onKeyUp: function(e, t) {
68420         var me = this,
68421             key = e.getKey();
68422
68423         if (!me.readOnly && !me.disabled && me.editable) {
68424             me.lastKey = key;
68425             
68426             
68427
68428             
68429             if (!e.isSpecialKey() || key == e.BACKSPACE || key == e.DELETE) {
68430                 me.doQueryTask.delay(me.queryDelay);
68431             }
68432         }
68433     },
68434
68435     initEvents: function() {
68436         var me = this;
68437         me.callParent();
68438
68439         
68440         me.mon(me.inputEl, 'keyup', me.onKeyUp, me);
68441     },
68442
68443     createPicker: function() {
68444         var me = this,
68445             picker,
68446             menuCls = Ext.baseCSSPrefix + 'menu',
68447             opts = Ext.apply({
68448                 selModel: {
68449                     mode: me.multiSelect ? 'SIMPLE' : 'SINGLE'
68450                 },
68451                 floating: true,
68452                 hidden: true,
68453                 ownerCt: me.ownerCt,
68454                 cls: me.el.up('.' + menuCls) ? menuCls : '',
68455                 store: me.store,
68456                 displayField: me.displayField,
68457                 focusOnToFront: false,
68458                 pageSize: me.pageSize
68459             }, me.listConfig, me.defaultListConfig);
68460
68461         picker = me.picker = Ext.create('Ext.view.BoundList', opts);
68462
68463         me.mon(picker, {
68464             itemclick: me.onItemClick,
68465             refresh: me.onListRefresh,
68466             scope: me
68467         });
68468
68469         me.mon(picker.getSelectionModel(), {
68470             selectionChange: me.onListSelectionChange,
68471             scope: me
68472         });
68473
68474         return picker;
68475     },
68476
68477     onListRefresh: function() {
68478         this.alignPicker();
68479         this.syncSelection();
68480     },
68481     
68482     onItemClick: function(picker, record){
68483         
68484         var me = this,
68485             lastSelection = me.lastSelection,
68486             valueField = me.valueField,
68487             selected;
68488         
68489         if (!me.multiSelect && lastSelection) {
68490             selected = lastSelection[0];
68491             if (record.get(valueField) === selected.get(valueField)) {
68492                 me.collapse();
68493             }
68494         }   
68495     },
68496
68497     onListSelectionChange: function(list, selectedRecords) {
68498         var me = this;
68499         
68500         
68501         if (!me.ignoreSelection && me.isExpanded) {
68502             if (!me.multiSelect) {
68503                 Ext.defer(me.collapse, 1, me);
68504             }
68505             me.setValue(selectedRecords, false);
68506             if (selectedRecords.length > 0) {
68507                 me.fireEvent('select', me, selectedRecords);
68508             }
68509             me.inputEl.focus();
68510         }
68511     },
68512
68513     
68514     onExpand: function() {
68515         var me = this,
68516             keyNav = me.listKeyNav,
68517             selectOnTab = me.selectOnTab,
68518             picker = me.getPicker();
68519
68520         
68521         if (keyNav) {
68522             keyNav.enable();
68523         } else {
68524             keyNav = me.listKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
68525                 boundList: picker,
68526                 forceKeyDown: true,
68527                 tab: function(e) {
68528                     if (selectOnTab) {
68529                         this.selectHighlighted(e);
68530                         me.triggerBlur();
68531                     }
68532                     
68533                     return true;
68534                 }
68535             });
68536         }
68537
68538         
68539         if (selectOnTab) {
68540             me.ignoreMonitorTab = true;
68541         }
68542
68543         Ext.defer(keyNav.enable, 1, keyNav); 
68544         me.inputEl.focus();
68545     },
68546
68547     
68548     onCollapse: function() {
68549         var me = this,
68550             keyNav = me.listKeyNav;
68551         if (keyNav) {
68552             keyNav.disable();
68553             me.ignoreMonitorTab = false;
68554         }
68555     },
68556
68557     
68558     select: function(r) {
68559         this.setValue(r, true);
68560     },
68561
68562     
68563     findRecord: function(field, value) {
68564         var ds = this.store,
68565             idx = ds.findExact(field, value);
68566         return idx !== -1 ? ds.getAt(idx) : false;
68567     },
68568     findRecordByValue: function(value) {
68569         return this.findRecord(this.valueField, value);
68570     },
68571     findRecordByDisplay: function(value) {
68572         return this.findRecord(this.displayField, value);
68573     },
68574
68575     
68576     setValue: function(value, doSelect) {
68577         var me = this,
68578             valueNotFoundText = me.valueNotFoundText,
68579             inputEl = me.inputEl,
68580             i, len, record,
68581             models = [],
68582             displayTplData = [],
68583             processedValue = [];
68584
68585         if (me.store.loading) {
68586             
68587             me.value = value;
68588             return me;
68589         }
68590
68591         
68592         value = Ext.Array.from(value);
68593
68594         
68595         for (i = 0, len = value.length; i < len; i++) {
68596             record = value[i];
68597             if (!record || !record.isModel) {
68598                 record = me.findRecordByValue(record);
68599             }
68600             
68601             if (record) {
68602                 models.push(record);
68603                 displayTplData.push(record.data);
68604                 processedValue.push(record.get(me.valueField));
68605             }
68606             
68607             
68608             else {
68609                 
68610                 if (Ext.isDefined(valueNotFoundText)) {
68611                     displayTplData.push(valueNotFoundText);
68612                 }
68613                 processedValue.push(value[i]);
68614             }
68615         }
68616
68617         
68618         me.value = me.multiSelect ? processedValue : processedValue[0];
68619         if (!Ext.isDefined(me.value)) {
68620             me.value = null;
68621         }
68622         me.displayTplData = displayTplData; 
68623         me.lastSelection = me.valueModels = models;
68624
68625         if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
68626             inputEl.removeCls(me.emptyCls);
68627         }
68628
68629         
68630         me.setRawValue(me.getDisplayValue());
68631         me.checkChange();
68632
68633         if (doSelect !== false) {
68634             me.syncSelection();
68635         }
68636         me.applyEmptyText();
68637
68638         return me;
68639     },
68640
68641     
68642     getDisplayValue: function() {
68643         return this.displayTpl.apply(this.displayTplData);
68644     },
68645
68646     getValue: function() {
68647         
68648         
68649         
68650         var me = this,
68651             picker = me.picker,
68652             rawValue = me.getRawValue(), 
68653             value = me.value; 
68654
68655         if (me.getDisplayValue() !== rawValue) {
68656             value = rawValue;
68657             me.value = me.displayTplData = me.valueModels = null;
68658             if (picker) {
68659                 me.ignoreSelection++;
68660                 picker.getSelectionModel().deselectAll();
68661                 me.ignoreSelection--;
68662             }
68663         }
68664
68665         return value;
68666     },
68667
68668     getSubmitValue: function() {
68669         return this.getValue();
68670     },
68671
68672     isEqual: function(v1, v2) {
68673         var fromArray = Ext.Array.from,
68674             i, len;
68675
68676         v1 = fromArray(v1);
68677         v2 = fromArray(v2);
68678         len = v1.length;
68679
68680         if (len !== v2.length) {
68681             return false;
68682         }
68683
68684         for(i = 0; i < len; i++) {
68685             if (v2[i] !== v1[i]) {
68686                 return false;
68687             }
68688         }
68689
68690         return true;
68691     },
68692
68693     
68694     clearValue: function() {
68695         this.setValue([]);
68696     },
68697
68698     
68699     syncSelection: function() {
68700         var me = this,
68701             ExtArray = Ext.Array,
68702             picker = me.picker,
68703             selection, selModel;
68704         if (picker) {
68705             
68706             selection = [];
68707             ExtArray.forEach(me.valueModels || [], function(value) {
68708                 if (value && value.isModel && me.store.indexOf(value) >= 0) {
68709                     selection.push(value);
68710                 }
68711             });
68712
68713             
68714             me.ignoreSelection++;
68715             selModel = picker.getSelectionModel();
68716             selModel.deselectAll();
68717             if (selection.length) {
68718                 selModel.select(selection);
68719             }
68720             me.ignoreSelection--;
68721         }
68722     }
68723 });
68724
68725
68726 Ext.define('Ext.picker.Month', {
68727     extend: 'Ext.Component',
68728     requires: ['Ext.XTemplate', 'Ext.util.ClickRepeater', 'Ext.Date', 'Ext.button.Button'],
68729     alias: 'widget.monthpicker',
68730     alternateClassName: 'Ext.MonthPicker',
68731
68732     renderTpl: [
68733         '<div class="{baseCls}-body">',
68734           '<div class="{baseCls}-months">',
68735               '<tpl for="months">',
68736                   '<div class="{parent.baseCls}-item {parent.baseCls}-month"><a href="#" hidefocus="on">{.}</a></div>',
68737               '</tpl>',
68738           '</div>',
68739           '<div class="{baseCls}-years">',
68740               '<div class="{baseCls}-yearnav">',
68741                   '<button class="{baseCls}-yearnav-prev"></button>',
68742                   '<button class="{baseCls}-yearnav-next"></button>',
68743               '</div>',
68744               '<tpl for="years">',
68745                   '<div class="{parent.baseCls}-item {parent.baseCls}-year"><a href="#" hidefocus="on">{.}</a></div>',
68746               '</tpl>',
68747           '</div>',
68748         '</div>',
68749         '<div class="' + Ext.baseCSSPrefix + 'clear"></div>',
68750         '<tpl if="showButtons">',
68751           '<div class="{baseCls}-buttons"></div>',
68752         '</tpl>'
68753     ],
68754
68755     
68756     okText: 'OK',
68757
68758     
68759     cancelText: 'Cancel',
68760
68761     
68762     baseCls: Ext.baseCSSPrefix + 'monthpicker',
68763
68764     
68765     showButtons: true,
68766
68767     
68768
68769     
68770
68771     width: 175,
68772
68773     height: 195,
68774
68775
68776     
68777     totalYears: 10,
68778     yearOffset: 5, 
68779     monthOffset: 6, 
68780
68781     
68782     initComponent: function(){
68783         var me = this;
68784
68785         me.selectedCls = me.baseCls + '-selected';
68786         me.addEvents(
68787             
68788             'cancelclick',
68789
68790             
68791             'monthclick',
68792
68793             
68794             'monthdblclick',
68795
68796             
68797             'okclick',
68798
68799             
68800             'select',
68801
68802             
68803             'yearclick',
68804
68805             
68806             'yeardblclick'
68807         );
68808
68809         me.setValue(me.value);
68810         me.activeYear = me.getYear(new Date().getFullYear() - 4, -4);
68811         this.callParent();
68812     },
68813
68814     
68815     onRender: function(ct, position){
68816         var me = this,
68817             i = 0,
68818             months = [],
68819             shortName = Ext.Date.getShortMonthName,
68820             monthLen = me.monthOffset;
68821
68822         for (; i < monthLen; ++i) {
68823             months.push(shortName(i), shortName(i + monthLen));
68824         }
68825
68826         Ext.apply(me.renderData, {
68827             months: months,
68828             years: me.getYears(),
68829             showButtons: me.showButtons
68830         });
68831
68832         Ext.apply(me.renderSelectors, {
68833             bodyEl: '.' + me.baseCls + '-body',
68834             prevEl: '.' + me.baseCls + '-yearnav-prev',
68835             nextEl: '.' + me.baseCls + '-yearnav-next',
68836             buttonsEl: '.' + me.baseCls + '-buttons'
68837         });
68838         this.callParent([ct, position]);
68839     },
68840
68841     
68842     afterRender: function(){
68843         var me = this,
68844             body = me.bodyEl,
68845             buttonsEl = me.buttonsEl;
68846
68847         me.callParent();
68848
68849         me.mon(body, 'click', me.onBodyClick, me);
68850         me.mon(body, 'dblclick', me.onBodyClick, me);
68851
68852         
68853         me.years = body.select('.' + me.baseCls + '-year a');
68854         me.months = body.select('.' + me.baseCls + '-month a');
68855
68856         if (me.showButtons) {
68857             me.okBtn = Ext.create('Ext.button.Button', {
68858                 text: me.okText,
68859                 renderTo: buttonsEl,
68860                 handler: me.onOkClick,
68861                 scope: me
68862             });
68863             me.cancelBtn = Ext.create('Ext.button.Button', {
68864                 text: me.cancelText,
68865                 renderTo: buttonsEl,
68866                 handler: me.onCancelClick,
68867                 scope: me
68868             });
68869         }
68870
68871         me.backRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
68872             handler: Ext.Function.bind(me.adjustYear, me, [-me.totalYears])
68873         });
68874
68875         me.prevEl.addClsOnOver(me.baseCls + '-yearnav-prev-over');
68876         me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
68877             handler: Ext.Function.bind(me.adjustYear, me, [me.totalYears])
68878         });
68879         me.nextEl.addClsOnOver(me.baseCls + '-yearnav-next-over');
68880         me.updateBody();
68881     },
68882
68883     
68884     setValue: function(value){
68885         var me = this,
68886             active = me.activeYear,
68887             offset = me.monthOffset,
68888             year,
68889             index;
68890
68891         if (!value) {
68892             me.value = [null, null];
68893         } else if (Ext.isDate(value)) {
68894             me.value = [value.getMonth(), value.getFullYear()];
68895         } else {
68896             me.value = [value[0], value[1]];
68897         }
68898
68899         if (me.rendered) {
68900             year = me.value[1];
68901             if (year !== null) {
68902                 if ((year < active || year > active + me.yearOffset)) {
68903                     me.activeYear = year - me.yearOffset + 1;
68904                 }
68905             }
68906             me.updateBody();
68907         }
68908
68909         return me;
68910     },
68911
68912     
68913     getValue: function(){
68914         return this.value;
68915     },
68916
68917     
68918     hasSelection: function(){
68919         var value = this.value;
68920         return value[0] !== null && value[1] !== null;
68921     },
68922
68923     
68924     getYears: function(){
68925         var me = this,
68926             offset = me.yearOffset,
68927             start = me.activeYear, 
68928             end = start + offset,
68929             i = start,
68930             years = [];
68931
68932         for (; i < end; ++i) {
68933             years.push(i, i + offset);
68934         }
68935
68936         return years;
68937     },
68938
68939     
68940     updateBody: function(){
68941         var me = this,
68942             years = me.years,
68943             months = me.months,
68944             yearNumbers = me.getYears(),
68945             cls = me.selectedCls,
68946             value = me.getYear(null),
68947             month = me.value[0],
68948             monthOffset = me.monthOffset,
68949             year;
68950
68951         if (me.rendered) {
68952             years.removeCls(cls);
68953             months.removeCls(cls);
68954             years.each(function(el, all, index){
68955                 year = yearNumbers[index];
68956                 el.dom.innerHTML = year;
68957                 if (year == value) {
68958                     el.dom.className = cls;
68959                 }
68960             });
68961             if (month !== null) {
68962                 if (month < monthOffset) {
68963                     month = month * 2;
68964                 } else {
68965                     month = (month - monthOffset) * 2 + 1;
68966                 }
68967                 months.item(month).addCls(cls);
68968             }
68969         }
68970     },
68971
68972     
68973     getYear: function(defaultValue, offset) {
68974         var year = this.value[1];
68975         offset = offset || 0;
68976         return year === null ? defaultValue : year + offset;
68977     },
68978
68979     
68980     onBodyClick: function(e, t) {
68981         var me = this,
68982             isDouble = e.type == 'dblclick';
68983
68984         if (e.getTarget('.' + me.baseCls + '-month')) {
68985             e.stopEvent();
68986             me.onMonthClick(t, isDouble);
68987         } else if (e.getTarget('.' + me.baseCls + '-year')) {
68988             e.stopEvent();
68989             me.onYearClick(t, isDouble);
68990         }
68991     },
68992
68993     
68994     adjustYear: function(offset){
68995         if (typeof offset != 'number') {
68996             offset = this.totalYears;
68997         }
68998         this.activeYear += offset;
68999         this.updateBody();
69000     },
69001
69002     
69003     onOkClick: function(){
69004         this.fireEvent('okclick', this, this.value);
69005     },
69006
69007     
69008     onCancelClick: function(){
69009         this.fireEvent('cancelclick', this);
69010     },
69011
69012     
69013     onMonthClick: function(target, isDouble){
69014         var me = this;
69015         me.value[0] = me.resolveOffset(me.months.indexOf(target), me.monthOffset);
69016         me.updateBody();
69017         me.fireEvent('month' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
69018         me.fireEvent('select', me, me.value);
69019     },
69020
69021     
69022     onYearClick: function(target, isDouble){
69023         var me = this;
69024         me.value[1] = me.activeYear + me.resolveOffset(me.years.indexOf(target), me.yearOffset);
69025         me.updateBody();
69026         me.fireEvent('year' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
69027         me.fireEvent('select', me, me.value);
69028
69029     },
69030
69031     
69032     resolveOffset: function(index, offset){
69033         if (index % 2 === 0) {
69034             return (index / 2);
69035         } else {
69036             return offset + Math.floor(index / 2);
69037         }
69038     },
69039
69040     
69041     beforeDestroy: function(){
69042         var me = this;
69043         me.years = me.months = null;
69044         Ext.destroyMembers('backRepeater', 'nextRepeater', 'okBtn', 'cancelBtn');
69045         this.callParent();
69046     }
69047 });
69048
69049
69050 Ext.define('Ext.picker.Date', {
69051     extend: 'Ext.Component',
69052     requires: [
69053         'Ext.XTemplate',
69054         'Ext.button.Button',
69055         'Ext.button.Split',
69056         'Ext.util.ClickRepeater',
69057         'Ext.util.KeyNav',
69058         'Ext.EventObject',
69059         'Ext.fx.Manager',
69060         'Ext.picker.Month'
69061     ],
69062     alias: 'widget.datepicker',
69063     alternateClassName: 'Ext.DatePicker',
69064
69065     renderTpl: [
69066         '<div class="{cls}" id="{id}" role="grid" title="{ariaTitle} {value:this.longDay}">',
69067             '<div role="presentation" class="{baseCls}-header">',
69068                 '<div class="{baseCls}-prev"><a href="#" role="button" title="{prevText}"></a></div>',
69069                 '<div class="{baseCls}-month"></div>',
69070                 '<div class="{baseCls}-next"><a href="#" role="button" title="{nextText}"></a></div>',
69071             '</div>',
69072             '<table class="{baseCls}-inner" cellspacing="0" role="presentation">',
69073                 '<thead role="presentation"><tr role="presentation">',
69074                     '<tpl for="dayNames">',
69075                         '<th role="columnheader" title="{.}"><span>{.:this.firstInitial}</span></th>',
69076                     '</tpl>',
69077                 '</tr></thead>',
69078                 '<tbody role="presentation"><tr role="presentation">',
69079                     '<tpl for="days">',
69080                         '{#:this.isEndOfWeek}',
69081                         '<td role="gridcell" id="{[Ext.id()]}">',
69082                             '<a role="presentation" href="#" hidefocus="on" class="{parent.baseCls}-date" tabIndex="1">',
69083                                 '<em role="presentation"><span role="presentation"></span></em>',
69084                             '</a>',
69085                         '</td>',
69086                     '</tpl>',
69087                 '</tr></tbody>',
69088             '</table>',
69089             '<tpl if="showToday">',
69090                 '<div role="presentation" class="{baseCls}-footer"></div>',
69091             '</tpl>',
69092         '</div>',
69093         {
69094             firstInitial: function(value) {
69095                 return value.substr(0,1);
69096             },
69097             isEndOfWeek: function(value) {
69098                 
69099                 
69100                 value--;
69101                 var end = value % 7 === 0 && value !== 0;
69102                 return end ? '</tr><tr role="row">' : '';
69103             },
69104             longDay: function(value){
69105                 return Ext.Date.format(value, this.longDayFormat);
69106             }
69107         }
69108     ],
69109
69110     ariaTitle: 'Date Picker',
69111     
69112     todayText : 'Today',
69113     
69114     
69115     
69116     todayTip : '{0} (Spacebar)',
69117     
69118     minText : 'This date is before the minimum date',
69119     
69120     maxText : 'This date is after the maximum date',
69121     
69122     
69123     disabledDaysText : 'Disabled',
69124     
69125     disabledDatesText : 'Disabled',
69126     
69127     
69128     
69129     nextText : 'Next Month (Control+Right)',
69130     
69131     prevText : 'Previous Month (Control+Left)',
69132     
69133     monthYearText : 'Choose a month (Control+Up/Down to move years)',
69134     
69135     startDay : 0,
69136     
69137     showToday : true,
69138     
69139     
69140     
69141     
69142     
69143
69144     
69145     disableAnim: true,
69146
69147     
69148     baseCls: Ext.baseCSSPrefix + 'datepicker',
69149
69150     
69151
69152     
69153
69154     
69155     longDayFormat: 'F d, Y',
69156
69157     
69158
69159     
69160     focusOnShow: false,
69161
69162     
69163     
69164     focusOnSelect: true,
69165
69166     width: 178,
69167
69168     
69169     
69170     initHour: 12, 
69171
69172     numDays: 42,
69173
69174     
69175     initComponent : function() {
69176         var me = this,
69177             clearTime = Ext.Date.clearTime;
69178
69179         me.selectedCls = me.baseCls + '-selected';
69180         me.disabledCellCls = me.baseCls + '-disabled';
69181         me.prevCls = me.baseCls + '-prevday';
69182         me.activeCls = me.baseCls + '-active';
69183         me.nextCls = me.baseCls + '-prevday';
69184         me.todayCls = me.baseCls + '-today';
69185         me.dayNames = me.dayNames.slice(me.startDay).concat(me.dayNames.slice(0, me.startDay));
69186         this.callParent();
69187
69188         me.value = me.value ?
69189                  clearTime(me.value, true) : clearTime(new Date());
69190
69191         me.addEvents(
69192             
69193             'select'
69194         );
69195
69196         me.initDisabledDays();
69197     },
69198
69199     
69200     onRender : function(container, position){
69201         
69202
69203         var me = this,
69204             days = new Array(me.numDays),
69205             today = Ext.Date.format(new Date(), me.format);
69206
69207         Ext.applyIf(me, {
69208             renderData: {},
69209             renderSelectors: {}
69210         });
69211
69212         Ext.apply(me.renderData, {
69213             dayNames: me.dayNames,
69214             ariaTitle: me.ariaTitle,
69215             value: me.value,
69216             showToday: me.showToday,
69217             prevText: me.prevText,
69218             nextText: me.nextText,
69219             days: days
69220         });
69221         me.getTpl('renderTpl').longDayFormat = me.longDayFormat;
69222
69223         Ext.apply(me.renderSelectors, {
69224             eventEl: 'table.' + me.baseCls + '-inner',
69225             prevEl: '.' + me.baseCls + '-prev a',
69226             nextEl: '.' + me.baseCls + '-next a',
69227             middleBtnEl: '.' + me.baseCls + '-month',
69228             footerEl: '.' + me.baseCls + '-footer'
69229         });
69230
69231         this.callParent(arguments);
69232         me.el.unselectable();
69233
69234         me.cells = me.eventEl.select('tbody td');
69235         me.textNodes = me.eventEl.query('tbody td span');
69236
69237         me.monthBtn = Ext.create('Ext.button.Split', {
69238             text: '',
69239             tooltip: me.monthYearText,
69240             renderTo: me.middleBtnEl
69241         });
69242         
69243
69244
69245         me.todayBtn = Ext.create('Ext.button.Button', {
69246             renderTo: me.footerEl,
69247             text: Ext.String.format(me.todayText, today),
69248             tooltip: Ext.String.format(me.todayTip, today),
69249             handler: me.selectToday,
69250             scope: me
69251         });
69252     },
69253
69254     
69255     initEvents: function(){
69256         var me = this,
69257             eDate = Ext.Date,
69258             day = eDate.DAY;
69259
69260         this.callParent();
69261
69262         me.prevRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
69263             handler: me.showPrevMonth,
69264             scope: me,
69265             preventDefault: true,
69266             stopDefault: true
69267         });
69268
69269         me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
69270             handler: me.showNextMonth,
69271             scope: me,
69272             preventDefault:true,
69273             stopDefault:true
69274         });
69275
69276         me.keyNav = Ext.create('Ext.util.KeyNav', me.eventEl, Ext.apply({
69277             scope: me,
69278             'left' : function(e){
69279                 if(e.ctrlKey){
69280                     me.showPrevMonth();
69281                 }else{
69282                     me.update(eDate.add(me.activeDate, day, -1));
69283                 }
69284             },
69285
69286             'right' : function(e){
69287                 if(e.ctrlKey){
69288                     me.showNextMonth();
69289                 }else{
69290                     me.update(eDate.add(me.activeDate, day, 1));
69291                 }
69292             },
69293
69294             'up' : function(e){
69295                 if(e.ctrlKey){
69296                     me.showNextYear();
69297                 }else{
69298                     me.update(eDate.add(me.activeDate, day, -7));
69299                 }
69300             },
69301
69302             'down' : function(e){
69303                 if(e.ctrlKey){
69304                     me.showPrevYear();
69305                 }else{
69306                     me.update(eDate.add(me.activeDate, day, 7));
69307                 }
69308             },
69309             'pageUp' : me.showNextMonth,
69310             'pageDown' : me.showPrevMonth,
69311             'enter' : function(e){
69312                 e.stopPropagation();
69313                 return true;
69314             }
69315         }, me.keyNavConfig));
69316
69317         if(me.showToday){
69318             me.todayKeyListener = me.eventEl.addKeyListener(Ext.EventObject.SPACE, me.selectToday,  me);
69319         }
69320         me.mon(me.eventEl, 'mousewheel', me.handleMouseWheel, me);
69321         me.mon(me.eventEl, 'click', me.handleDateClick,  me, {delegate: 'a.' + me.baseCls + '-date'});
69322         me.mon(me.monthBtn, 'click', me.showMonthPicker, me);
69323         me.mon(me.monthBtn, 'arrowclick', me.showMonthPicker, me);
69324         me.update(me.value);
69325     },
69326
69327     
69328     initDisabledDays : function(){
69329         var me = this,
69330             dd = me.disabledDates,
69331             re = '(?:',
69332             len;
69333
69334         if(!me.disabledDatesRE && dd){
69335                 len = dd.length - 1;
69336
69337             Ext.each(dd, function(d, i){
69338                 re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(Ext.Date.dateFormat(d, me.format)) + '$' : dd[i];
69339                 if(i != len){
69340                     re += '|';
69341                 }
69342             }, me);
69343             me.disabledDatesRE = new RegExp(re + ')');
69344         }
69345     },
69346
69347     
69348     setDisabledDates : function(dd){
69349         var me = this;
69350
69351         if(Ext.isArray(dd)){
69352             me.disabledDates = dd;
69353             me.disabledDatesRE = null;
69354         }else{
69355             me.disabledDatesRE = dd;
69356         }
69357         me.initDisabledDays();
69358         me.update(me.value, true);
69359         return me;
69360     },
69361
69362     
69363     setDisabledDays : function(dd){
69364         this.disabledDays = dd;
69365         return this.update(this.value, true);
69366     },
69367
69368     
69369     setMinDate : function(dt){
69370         this.minDate = dt;
69371         return this.update(this.value, true);
69372     },
69373
69374     
69375     setMaxDate : function(dt){
69376         this.maxDate = dt;
69377         return this.update(this.value, true);
69378     },
69379
69380     
69381     setValue : function(value){
69382         this.value = Ext.Date.clearTime(value, true);
69383         return this.update(this.value);
69384     },
69385
69386     
69387     getValue : function(){
69388         return this.value;
69389     },
69390
69391     
69392     focus : function(){
69393         this.update(this.activeDate);
69394     },
69395
69396     
69397     onEnable: function(){
69398         this.callParent();
69399         this.setDisabledStatus(false);
69400         this.update(this.activeDate);
69401
69402     },
69403
69404     
69405     onDisable : function(){
69406         this.callParent();
69407         this.setDisabledStatus(true);
69408     },
69409
69410     
69411     setDisabledStatus : function(disabled){
69412         var me = this;
69413
69414         me.keyNav.setDisabled(disabled);
69415         me.prevRepeater.setDisabled(disabled);
69416         me.nextRepeater.setDisabled(disabled);
69417         if (me.showToday) {
69418             me.todayKeyListener.setDisabled(disabled);
69419             me.todayBtn.setDisabled(disabled);
69420         }
69421     },
69422
69423     
69424     getActive: function(){
69425         return this.activeDate || me.value;
69426     },
69427
69428     
69429     runAnimation: function(isHide){
69430         var options = {
69431                 target: this.monthPicker,
69432                 duration: 200
69433             };
69434
69435         Ext.fx.Manager.run();
69436         if (isHide) {
69437             
69438         } else {
69439             
69440         }
69441         Ext.create('Ext.fx.Anim', options);
69442     },
69443
69444     
69445     hideMonthPicker : function(){
69446         var me = this,
69447             picker = me.monthPicker;
69448
69449         if (picker) {
69450             if (me.disableAnim) {
69451                 picker.hide();
69452             } else {
69453                 this.runAnimation(true);
69454             }
69455         }
69456         return me;
69457     },
69458
69459     
69460     showMonthPicker : function(){
69461
69462         var me = this,
69463             picker,
69464             size,
69465             top,
69466             left;
69467
69468
69469         if (me.rendered && !me.disabled) {
69470             size = me.getSize();
69471             picker = me.createMonthPicker();
69472             picker.show();
69473             picker.setSize(size);
69474             picker.setValue(me.getActive());
69475
69476             if (me.disableAnim) {
69477                 picker.setPosition(-1, -1);
69478             } else {
69479                 me.runAnimation(false);
69480             }
69481         }
69482         return me;
69483     },
69484
69485     
69486     createMonthPicker: function(){
69487         var me = this,
69488             picker = me.monthPicker;
69489
69490         if (!picker) {
69491             me.monthPicker = picker = Ext.create('Ext.picker.Month', {
69492                 renderTo: me.el,
69493                 floating: true,
69494                 shadow: false,
69495                 listeners: {
69496                     scope: me,
69497                     cancelclick: me.onCancelClick,
69498                     okclick: me.onOkClick,
69499                     yeardblclick: me.onOkClick,
69500                     monthdblclick: me.onOkClick
69501                 }
69502             });
69503
69504             me.on('beforehide', me.hideMonthPicker, me);
69505         }
69506         return picker;
69507     },
69508
69509     
69510     onOkClick: function(picker, value){
69511         var me = this,
69512             month = value[0],
69513             year = value[1],
69514             date = new Date(year, month, me.getActive().getDate());
69515
69516         if (date.getMonth() !== month) {
69517             
69518             date = new Date(year, month, 1).getLastDateOfMonth();
69519         }
69520         me.update(date);
69521         me.hideMonthPicker();
69522     },
69523
69524     
69525     onCancelClick: function(){
69526         this.hideMonthPicker();
69527     },
69528
69529     
69530     showPrevMonth : function(e){
69531         return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, -1));
69532     },
69533
69534     
69535     showNextMonth : function(e){
69536         return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, 1));
69537     },
69538
69539     
69540     showPrevYear : function(){
69541         this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, -1));
69542     },
69543
69544     
69545     showNextYear : function(){
69546         this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, 1));
69547     },
69548
69549     
69550     handleMouseWheel : function(e){
69551         e.stopEvent();
69552         if(!this.disabled){
69553             var delta = e.getWheelDelta();
69554             if(delta > 0){
69555                 this.showPrevMonth();
69556             } else if(delta < 0){
69557                 this.showNextMonth();
69558             }
69559         }
69560     },
69561
69562     
69563     handleDateClick : function(e, t){
69564         var me = this,
69565             handler = me.handler;
69566
69567         e.stopEvent();
69568         if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)){
69569             me.cancelFocus = me.focusOnSelect === false;
69570             me.setValue(new Date(t.dateValue));
69571             delete me.cancelFocus;
69572             me.fireEvent('select', me, me.value);
69573             if (handler) {
69574                 handler.call(me.scope || me, me, me.value);
69575             }
69576             
69577             
69578             
69579             
69580             me.onSelect();
69581         }
69582     },
69583
69584     
69585     onSelect: function() {
69586         if (this.hideOnSelect) {
69587              this.hide();
69588          }
69589     },
69590
69591     
69592     selectToday : function(){
69593         var me = this,
69594             btn = me.todayBtn,
69595             handler = me.handler;
69596
69597         if(btn && !btn.disabled){
69598             me.setValue(Ext.Date.clearTime(new Date()));
69599             me.fireEvent('select', me, me.value);
69600             if (handler) {
69601                 handler.call(me.scope || me, me, me.value);
69602             }
69603             me.onSelect();
69604         }
69605         return me;
69606     },
69607
69608     
69609     selectedUpdate: function(date, active){
69610         var me = this,
69611             t = date.getTime(),
69612             cells = me.cells,
69613             cls = me.selectedCls;
69614
69615         cells.removeCls(cls);
69616         cells.each(function(c){
69617             if (c.dom.firstChild.dateValue == t) {
69618                 me.el.dom.setAttribute('aria-activedescendent', c.dom.id);
69619                 c.addCls(cls);
69620                 if(me.isVisible() && !me.cancelFocus){
69621                     Ext.fly(c.dom.firstChild).focus(50);
69622                 }
69623                 return false;
69624             }
69625         }, this);
69626     },
69627
69628     
69629     fullUpdate: function(date, active){
69630         var me = this,
69631             cells = me.cells.elements,
69632             textNodes = me.textNodes,
69633             disabledCls = me.disabledCellCls,
69634             eDate = Ext.Date,
69635             i = 0,
69636             extraDays = 0,
69637             visible = me.isVisible(),
69638             sel = +eDate.clearTime(date, true),
69639             today = +eDate.clearTime(new Date()),
69640             min = me.minDate ? eDate.clearTime(me.minDate, true) : Number.NEGATIVE_INFINITY,
69641             max = me.maxDate ? eDate.clearTime(me.maxDate, true) : Number.POSITIVE_INFINITY,
69642             ddMatch = me.disabledDatesRE,
69643             ddText = me.disabledDatesText,
69644             ddays = me.disabledDays ? me.disabledDays.join('') : false,
69645             ddaysText = me.disabledDaysText,
69646             format = me.format,
69647             days = eDate.getDaysInMonth(date),
69648             firstOfMonth = eDate.getFirstDateOfMonth(date),
69649             startingPos = firstOfMonth.getDay() - me.startDay,
69650             previousMonth = eDate.add(date, eDate.MONTH, -1),
69651             longDayFormat = me.longDayFormat,
69652             prevStart,
69653             current,
69654             disableToday,
69655             tempDate,
69656             setCellClass,
69657             html,
69658             cls,
69659             formatValue,
69660             value;
69661
69662         if (startingPos < 0) {
69663             startingPos += 7;
69664         }
69665
69666         days += startingPos;
69667         prevStart = eDate.getDaysInMonth(previousMonth) - startingPos;
69668         current = new Date(previousMonth.getFullYear(), previousMonth.getMonth(), prevStart, me.initHour);
69669
69670         if (me.showToday) {
69671             tempDate = eDate.clearTime(new Date());
69672             disableToday = (tempDate < min || tempDate > max ||
69673                 (ddMatch && format && ddMatch.test(eDate.dateFormat(tempDate, format))) ||
69674                 (ddays && ddays.indexOf(tempDate.getDay()) != -1));
69675
69676             if (!me.disabled) {
69677                 me.todayBtn.setDisabled(disableToday);
69678                 me.todayKeyListener.setDisabled(disableToday);
69679             }
69680         }
69681
69682         setCellClass = function(cell){
69683             value = +eDate.clearTime(current, true);
69684             cell.title = eDate.format(current, longDayFormat);
69685             
69686             cell.firstChild.dateValue = value;
69687             if(value == today){
69688                 cell.className += ' ' + me.todayCls;
69689                 cell.title = me.todayText;
69690             }
69691             if(value == sel){
69692                 cell.className += ' ' + me.selectedCls;
69693                 me.el.dom.setAttribute('aria-activedescendant', cell.id);
69694                 if (visible && me.floating) {
69695                     Ext.fly(cell.firstChild).focus(50);
69696                 }
69697             }
69698             
69699             if(value < min) {
69700                 cell.className = disabledCls;
69701                 cell.title = me.minText;
69702                 return;
69703             }
69704             if(value > max) {
69705                 cell.className = disabledCls;
69706                 cell.title = me.maxText;
69707                 return;
69708             }
69709             if(ddays){
69710                 if(ddays.indexOf(current.getDay()) != -1){
69711                     cell.title = ddaysText;
69712                     cell.className = disabledCls;
69713                 }
69714             }
69715             if(ddMatch && format){
69716                 formatValue = eDate.dateFormat(current, format);
69717                 if(ddMatch.test(formatValue)){
69718                     cell.title = ddText.replace('%0', formatValue);
69719                     cell.className = disabledCls;
69720                 }
69721             }
69722         };
69723
69724         for(; i < me.numDays; ++i) {
69725             if (i < startingPos) {
69726                 html = (++prevStart);
69727                 cls = me.prevCls;
69728             } else if (i >= days) {
69729                 html = (++extraDays);
69730                 cls = me.nextCls;
69731             } else {
69732                 html = i - startingPos + 1;
69733                 cls = me.activeCls;
69734             }
69735             textNodes[i].innerHTML = html;
69736             cells[i].className = cls;
69737             current.setDate(current.getDate() + 1);
69738             setCellClass(cells[i]);
69739         }
69740
69741         me.monthBtn.setText(me.monthNames[date.getMonth()] + ' ' + date.getFullYear());
69742     },
69743
69744     
69745     update : function(date, forceRefresh){
69746         var me = this,
69747             active = me.activeDate;
69748
69749         if (me.rendered) {
69750             me.activeDate = date;
69751             if(!forceRefresh && active && me.el && active.getMonth() == date.getMonth() && active.getFullYear() == date.getFullYear()){
69752                 me.selectedUpdate(date, active);
69753             } else {
69754                 me.fullUpdate(date, active);
69755             }
69756         }
69757         return me;
69758     },
69759
69760     
69761     beforeDestroy : function() {
69762         var me = this;
69763
69764         if (me.rendered) {
69765             Ext.destroy(
69766                 me.todayKeyListener,
69767                 me.keyNav,
69768                 me.monthPicker,
69769                 me.monthBtn,
69770                 me.nextRepeater,
69771                 me.prevRepeater,
69772                 me.todayBtn
69773             );
69774             delete me.textNodes;
69775             delete me.cells.elements;
69776         }
69777     },
69778
69779     
69780     onShow: function() {
69781         this.callParent(arguments);
69782         if (this.focusOnShow) {
69783             this.focus();
69784         }
69785     }
69786 },
69787
69788
69789 function() {
69790     var proto = this.prototype;
69791
69792     proto.monthNames = Ext.Date.monthNames;
69793
69794     proto.dayNames = Ext.Date.dayNames;
69795
69796     proto.format = Ext.Date.defaultFormat;
69797 });
69798
69799
69800 Ext.define('Ext.form.field.Date', {
69801     extend:'Ext.form.field.Picker',
69802     alias: 'widget.datefield',
69803     requires: ['Ext.picker.Date'],
69804     alternateClassName: ['Ext.form.DateField', 'Ext.form.Date'],
69805
69806     
69807     format : "m/d/Y",
69808     
69809     altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j",
69810     
69811     disabledDaysText : "Disabled",
69812     
69813     disabledDatesText : "Disabled",
69814     
69815     minText : "The date in this field must be equal to or after {0}",
69816     
69817     maxText : "The date in this field must be equal to or before {0}",
69818     
69819     invalidText : "{0} is not a valid date - it must be in the format {1}",
69820     
69821     triggerCls : Ext.baseCSSPrefix + 'form-date-trigger',
69822     
69823     showToday : true,
69824     
69825     
69826     
69827     
69828     
69829     
69830
69831     
69832     
69833     initTime: '12', 
69834
69835     initTimeFormat: 'H',
69836
69837     matchFieldWidth: false,
69838     
69839     startDay: 0,
69840     
69841     initComponent : function(){
69842         var me = this,
69843             isString = Ext.isString,
69844             min, max;
69845
69846         min = me.minValue;
69847         max = me.maxValue;
69848         if(isString(min)){
69849             me.minValue = me.parseDate(min);
69850         }
69851         if(isString(max)){
69852             me.maxValue = me.parseDate(max);
69853         }
69854         me.disabledDatesRE = null;
69855         me.initDisabledDays();
69856
69857         me.callParent();
69858     },
69859
69860     initValue: function() {
69861         var me = this,
69862             value = me.value;
69863
69864         
69865         if (Ext.isString(value)) {
69866             me.value = me.rawToValue(value);
69867         }
69868
69869         me.callParent();
69870     },
69871
69872     
69873     initDisabledDays : function(){
69874         if(this.disabledDates){
69875             var dd = this.disabledDates,
69876                 len = dd.length - 1,
69877                 re = "(?:";
69878
69879             Ext.each(dd, function(d, i){
69880                 re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(d.dateFormat(this.format)) + '$' : dd[i];
69881                 if (i !== len) {
69882                     re += '|';
69883                 }
69884             }, this);
69885             this.disabledDatesRE = new RegExp(re + ')');
69886         }
69887     },
69888
69889     
69890     setDisabledDates : function(dd){
69891         var me = this,
69892             picker = me.picker;
69893             
69894         me.disabledDates = dd;
69895         me.initDisabledDays();
69896         if (picker) {
69897             picker.setDisabledDates(me.disabledDatesRE);
69898         }
69899     },
69900
69901     
69902     setDisabledDays : function(dd){
69903         var picker = this.picker;
69904             
69905         this.disabledDays = dd;
69906         if (picker) {
69907             picker.setDisabledDays(dd);
69908         }
69909     },
69910
69911     
69912     setMinValue : function(dt){
69913         var me = this,
69914             picker = me.picker,
69915             minValue = (Ext.isString(dt) ? me.parseDate(dt) : dt);
69916             
69917         me.minValue = minValue;
69918         if (picker) {
69919             picker.minText = Ext.String.format(me.minText, me.formatDate(me.minValue));
69920             picker.setMinDate(minValue);
69921         }
69922     },
69923
69924     
69925     setMaxValue : function(dt){
69926         var me = this,
69927             picker = me.picker,
69928             maxValue = (Ext.isString(dt) ? me.parseDate(dt) : dt);
69929             
69930         me.maxValue = maxValue;
69931         if (picker) {
69932             picker.maxText = Ext.String.format(me.maxText, me.formatDate(me.maxValue));
69933             picker.setMaxDate(maxValue);
69934         }
69935     },
69936
69937     
69938     getErrors: function(value) {
69939         var me = this,
69940             format = Ext.String.format,
69941             clearTime = Ext.Date.clearTime,
69942             errors = me.callParent(arguments),
69943             disabledDays = me.disabledDays,
69944             disabledDatesRE = me.disabledDatesRE,
69945             minValue = me.minValue,
69946             maxValue = me.maxValue,
69947             len = disabledDays ? disabledDays.length : 0,
69948             i = 0,
69949             svalue,
69950             fvalue,
69951             day,
69952             time;
69953
69954         value = me.formatDate(value || me.processRawValue(me.getRawValue()));
69955
69956         if (value === null || value.length < 1) { 
69957              return errors;
69958         }
69959
69960         svalue = value;
69961         value = me.parseDate(value);
69962         if (!value) {
69963             errors.push(format(me.invalidText, svalue, me.format));
69964             return errors;
69965         }
69966
69967         time = value.getTime();
69968         if (minValue && time < clearTime(minValue).getTime()) {
69969             errors.push(format(me.minText, me.formatDate(minValue)));
69970         }
69971
69972         if (maxValue && time > clearTime(maxValue).getTime()) {
69973             errors.push(format(me.maxText, me.formatDate(maxValue)));
69974         }
69975
69976         if (disabledDays) {
69977             day = value.getDay();
69978
69979             for(; i < len; i++) {
69980                 if (day === disabledDays[i]) {
69981                     errors.push(me.disabledDaysText);
69982                     break;
69983                 }
69984             }
69985         }
69986
69987         fvalue = me.formatDate(value);
69988         if (disabledDatesRE && disabledDatesRE.test(fvalue)) {
69989             errors.push(format(me.disabledDatesText, fvalue));
69990         }
69991
69992         return errors;
69993     },
69994
69995     rawToValue: function(rawValue) {
69996         return this.parseDate(rawValue) || rawValue || null;
69997     },
69998
69999     valueToRaw: function(value) {
70000         return this.formatDate(this.parseDate(value));
70001     },
70002
70003     
70004
70005     
70006     safeParse : function(value, format) {
70007         var me = this,
70008             utilDate = Ext.Date,
70009             parsedDate,
70010             result = null;
70011             
70012         if (utilDate.formatContainsHourInfo(format)) {
70013             
70014             result = utilDate.parse(value, format);
70015         } else {
70016             
70017             parsedDate = utilDate.parse(value + ' ' + me.initTime, format + ' ' + me.initTimeFormat);
70018             if (parsedDate) {
70019                 result = utilDate.clearTime(parsedDate);
70020             }
70021         }
70022         return result;
70023     },
70024     
70025     
70026     getSubmitValue: function() {
70027         var me = this,
70028             format = me.submitFormat || me.format,
70029             value = me.getValue();
70030             
70031         return value ? Ext.Date.format(value, format) : null;
70032     },
70033
70034     
70035     parseDate : function(value) {
70036         if(!value || Ext.isDate(value)){
70037             return value;
70038         }
70039
70040         var me = this,
70041             val = me.safeParse(value, me.format),
70042             altFormats = me.altFormats,
70043             altFormatsArray = me.altFormatsArray,
70044             i = 0,
70045             len;
70046
70047         if (!val && altFormats) {
70048             altFormatsArray = altFormatsArray || altFormats.split('|');
70049             len = altFormatsArray.length;
70050             for (; i < len && !val; ++i) {
70051                 val = me.safeParse(value, altFormatsArray[i]);
70052             }
70053         }
70054         return val;
70055     },
70056
70057     
70058     formatDate : function(date){
70059         return Ext.isDate(date) ? Ext.Date.dateFormat(date, this.format) : date;
70060     },
70061
70062     createPicker: function() {
70063         var me = this,
70064             format = Ext.String.format;
70065
70066         return Ext.create('Ext.picker.Date', {
70067             ownerCt: this.ownerCt,
70068             renderTo: document.body,
70069             floating: true,
70070             hidden: true,
70071             focusOnShow: true,
70072             minDate: me.minValue,
70073             maxDate: me.maxValue,
70074             disabledDatesRE: me.disabledDatesRE,
70075             disabledDatesText: me.disabledDatesText,
70076             disabledDays: me.disabledDays,
70077             disabledDaysText: me.disabledDaysText,
70078             format: me.format,
70079             showToday: me.showToday,
70080             startDay: me.startDay,
70081             minText: format(me.minText, me.formatDate(me.minValue)),
70082             maxText: format(me.maxText, me.formatDate(me.maxValue)),
70083             listeners: {
70084                 scope: me,
70085                 select: me.onSelect
70086             },
70087             keyNavConfig: {
70088                 esc: function() {
70089                     me.collapse();
70090                 }
70091             }
70092         });
70093     },
70094
70095     onSelect: function(m, d) {
70096         this.setValue(d);
70097         this.fireEvent('select', this, d);
70098         this.collapse();
70099     },
70100
70101     
70102     onExpand: function() {
70103         var me = this,
70104             value = me.getValue();
70105         me.picker.setValue(value instanceof Date ? value : new Date());
70106     },
70107
70108     
70109     onCollapse: function() {
70110         this.focus(false, 60);
70111     },
70112
70113     
70114     beforeBlur : function(){
70115         var v = this.parseDate(this.getRawValue());
70116         if(v){
70117             this.setValue(v);
70118         }
70119     }
70120
70121     
70122     
70123     
70124     
70125 });
70126
70127
70128 Ext.define('Ext.form.field.Display', {
70129     extend:'Ext.form.field.Base',
70130     alias: 'widget.displayfield',
70131     requires: ['Ext.util.Format', 'Ext.XTemplate'],
70132     alternateClassName: ['Ext.form.DisplayField', 'Ext.form.Display'],
70133     fieldSubTpl: [
70134         '<div id="{id}" class="{fieldCls}"></div>',
70135         {
70136             compiled: true,
70137             disableFormats: true
70138         }
70139     ],
70140
70141     
70142     fieldCls: Ext.baseCSSPrefix + 'form-display-field',
70143
70144     
70145     htmlEncode: false,
70146
70147     validateOnChange: false,
70148
70149     initEvents: Ext.emptyFn,
70150
70151     submitValue: false,
70152
70153     isValid: function() {
70154         return true;
70155     },
70156
70157     validate: function() {
70158         return true;
70159     },
70160
70161     getRawValue: function() {
70162         return this.rawValue;
70163     },
70164
70165     setRawValue: function(value) {
70166         var me = this;
70167         value = Ext.value(value, '');
70168         me.rawValue = value;
70169         if (me.rendered) {
70170             me.inputEl.dom.innerHTML = me.htmlEncode ? Ext.util.Format.htmlEncode(value) : value;
70171         }
70172         return value;
70173     },
70174
70175     
70176     getContentTarget: function() {
70177         return this.inputEl;
70178     }
70179
70180     
70181     
70182     
70183     
70184     
70185     
70186 });
70187
70188
70189 Ext.define("Ext.form.field.File", {
70190     extend: 'Ext.form.field.Text',
70191     alias: ['widget.filefield', 'widget.fileuploadfield'],
70192     alternateClassName: ['Ext.form.FileUploadField', 'Ext.ux.form.FileUploadField', 'Ext.form.File'],
70193     uses: ['Ext.button.Button', 'Ext.layout.component.field.File'],
70194
70195     
70196     buttonText: 'Browse...',
70197
70198     
70199     buttonOnly: false,
70200
70201     
70202     buttonMargin: 3,
70203
70204     
70205
70206     
70207
70208     
70209
70210     
70211
70212     
70213     fieldBodyCls: Ext.baseCSSPrefix + 'form-file-wrap',
70214
70215
70216     
70217     readOnly: true,
70218     componentLayout: 'filefield',
70219
70220     
70221     onRender: function() {
70222         var me = this,
70223             inputEl;
70224
70225         me.callParent(arguments);
70226
70227         me.createButton();
70228         me.createFileInput();
70229         
70230         
70231         
70232         if (me.disabled) {
70233             me.disableItems();
70234         }
70235
70236         inputEl = me.inputEl;
70237         inputEl.dom.removeAttribute('name'); 
70238         if (me.buttonOnly) {
70239             inputEl.setDisplayed(false);
70240         }
70241     },
70242
70243     
70244     createButton: function() {
70245         var me = this;
70246         me.button = Ext.widget('button', Ext.apply({
70247             renderTo: me.bodyEl,
70248             text: me.buttonText,
70249             cls: Ext.baseCSSPrefix + 'form-file-btn',
70250             preventDefault: false,
70251             ownerCt: me,
70252             style: me.buttonOnly ? '' : 'margin-left:' + me.buttonMargin + 'px'
70253         }, me.buttonConfig));
70254     },
70255
70256     
70257     createFileInput : function() {
70258         var me = this;
70259         me.fileInputEl = me.button.el.createChild({
70260             name: me.getName(),
70261             cls: Ext.baseCSSPrefix + 'form-file-input',
70262             tag: 'input',
70263             type: 'file',
70264             size: 1
70265         }).on('change', me.onFileChange, me);
70266     },
70267
70268     
70269     onFileChange: function() {
70270         this.lastValue = null; 
70271         Ext.form.field.File.superclass.setValue.call(this, this.fileInputEl.dom.value);
70272     },
70273
70274     
70275     setValue: Ext.emptyFn,
70276
70277     reset : function(){
70278         this.fileInputEl.remove();
70279         this.createFileInput();
70280         this.callParent();
70281     },
70282
70283     onDisable: function(){
70284         this.callParent();
70285         this.disableItems();
70286     },
70287     
70288     disableItems: function(){
70289         var file = this.fileInputEl,
70290             button = this.button;
70291              
70292         if (file) {
70293             file.dom.disabled = true;
70294         }
70295         if (button) {
70296             button.disable();
70297         }    
70298     },
70299
70300     onEnable: function(){
70301         var me = this;
70302         me.callParent();
70303         me.fileInputEl.dom.disabled = false;
70304         me.button.enable();
70305     },
70306
70307     isFileUpload: function() {
70308         return true;
70309     },
70310
70311     extractFileInput: function() {
70312         var fileInput = this.fileInputEl.dom;
70313         this.reset();
70314         return fileInput;
70315     },
70316
70317     onDestroy: function(){
70318         Ext.destroyMembers(this, 'fileInputEl', 'button');
70319         this.callParent();
70320     }
70321
70322
70323 });
70324
70325
70326 Ext.define('Ext.form.field.Hidden', {
70327     extend:'Ext.form.field.Base',
70328     alias: ['widget.hiddenfield', 'widget.hidden'],
70329     alternateClassName: 'Ext.form.Hidden',
70330
70331     
70332     inputType : 'hidden',
70333     hideLabel: true,
70334     
70335     initComponent: function(){
70336         this.formItemCls += '-hidden';
70337         this.callParent();    
70338     },
70339
70340     
70341     initEvents: Ext.emptyFn,
70342     setSize : Ext.emptyFn,
70343     setWidth : Ext.emptyFn,
70344     setHeight : Ext.emptyFn,
70345     setPosition : Ext.emptyFn,
70346     setPagePosition : Ext.emptyFn,
70347     markInvalid : Ext.emptyFn,
70348     clearInvalid : Ext.emptyFn
70349 });
70350
70351
70352 Ext.define('Ext.picker.Color', {
70353     extend: 'Ext.Component',
70354     requires: 'Ext.XTemplate',
70355     alias: 'widget.colorpicker',
70356     alternateClassName: 'Ext.ColorPalette',
70357     
70358     
70359     componentCls : Ext.baseCSSPrefix + 'color-picker',
70360     
70361     
70362     selectedCls: Ext.baseCSSPrefix + 'color-picker-selected',
70363     
70364     
70365     value : null,
70366     
70367     
70368     clickEvent :'click',
70369
70370     
70371     allowReselect : false,
70372
70373     
70374     colors : [
70375         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
70376         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
70377         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
70378         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
70379         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
70380     ],
70381
70382     
70383     
70384     
70385     colorRe: /(?:^|\s)color-(.{6})(?:\s|$)/,
70386     
70387     constructor: function() {
70388         this.renderTpl = Ext.create('Ext.XTemplate', '<tpl for="colors"><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>');
70389         this.callParent(arguments);
70390     },
70391     
70392     
70393     initComponent : function(){
70394         var me = this;
70395         
70396         this.callParent(arguments);
70397         me.addEvents(
70398             
70399             'select'
70400         );
70401
70402         if (me.handler) {
70403             me.on('select', me.handler, me.scope, true);
70404         }
70405     },
70406
70407
70408     
70409     onRender : function(container, position){
70410         var me = this,
70411             clickEvent = me.clickEvent;
70412             
70413         Ext.apply(me.renderData, {
70414             itemCls: me.itemCls,
70415             colors: me.colors    
70416         });
70417         this.callParent(arguments);
70418
70419         me.mon(me.el, clickEvent, me.handleClick, me, {delegate: 'a'});
70420         
70421         if(clickEvent != 'click'){
70422             me.mon(me.el, 'click', Ext.emptyFn, me, {delegate: 'a', stopEvent: true});
70423         }
70424     },
70425
70426     
70427     afterRender : function(){
70428         var me = this,
70429             value;
70430             
70431         this.callParent(arguments);
70432         if (me.value) {
70433             value = me.value;
70434             me.value = null;
70435             me.select(value, true);
70436         }
70437     },
70438
70439     
70440     handleClick : function(event, target){
70441         var me = this,
70442             color;
70443             
70444         event.stopEvent();
70445         if (!me.disabled) {
70446             color = target.className.match(me.colorRe)[1];
70447             me.select(color.toUpperCase());
70448         }
70449     },
70450
70451     
70452     select : function(color, suppressEvent){
70453         
70454         var me = this,
70455             selectedCls = me.selectedCls,
70456             value = me.value,
70457             el;
70458             
70459         color = color.replace('#', '');
70460         if (!me.rendered) {
70461             me.value = color;
70462             return;
70463         }
70464         
70465         
70466         if (color != value || me.allowReselect) {
70467             el = me.el;
70468
70469             if (me.value) {
70470                 el.down('a.color-' + value).removeCls(selectedCls);
70471             }
70472             el.down('a.color-' + color).addCls(selectedCls);
70473             me.value = color;
70474             if (suppressEvent !== true) {
70475                 me.fireEvent('select', me, color);
70476             }
70477         }
70478     },
70479     
70480     
70481     getValue: function(){
70482         return this.value || null;
70483     }
70484 });
70485
70486
70487
70488 Ext.define('Ext.layout.component.field.HtmlEditor', {
70489     extend: 'Ext.layout.component.field.Field',
70490     alias: ['layout.htmleditor'],
70491
70492     type: 'htmleditor',
70493
70494     sizeBodyContents: function(width, height) {
70495         var me = this,
70496             owner = me.owner,
70497             bodyEl = owner.bodyEl,
70498             toolbar = owner.getToolbar(),
70499             textarea = owner.textareaEl,
70500             iframe = owner.iframeEl,
70501             editorHeight;
70502
70503         if (Ext.isNumber(width)) {
70504             width -= bodyEl.getFrameWidth('lr');
70505         }
70506         toolbar.setWidth(width);
70507         textarea.setWidth(width);
70508         iframe.setWidth(width);
70509
70510         
70511         if (Ext.isNumber(height)) {
70512             editorHeight = height - toolbar.getHeight() - bodyEl.getFrameWidth('tb');
70513             textarea.setHeight(editorHeight);
70514             iframe.setHeight(editorHeight);
70515         }
70516     }
70517 });
70518
70519 Ext.define('Ext.form.field.HtmlEditor', {
70520     extend:'Ext.Component',
70521     mixins: {
70522         labelable: 'Ext.form.Labelable',
70523         field: 'Ext.form.field.Field'
70524     },
70525     alias: 'widget.htmleditor',
70526     alternateClassName: 'Ext.form.HtmlEditor',
70527     requires: [
70528         'Ext.tip.QuickTipManager',
70529         'Ext.picker.Color',
70530         'Ext.toolbar.Item',
70531         'Ext.toolbar.Toolbar',
70532         'Ext.util.Format',
70533         'Ext.layout.component.field.HtmlEditor'
70534     ],
70535
70536     fieldSubTpl: [
70537         '<div class="{toolbarWrapCls}"></div>',
70538         '<textarea id="{id}" name="{name}" tabIndex="-1" class="{textareaCls}" ',
70539             'style="{size}" autocomplete="off"></textarea>',
70540         '<iframe name="{iframeName}" frameBorder="0" style="overflow:auto;{size}" src="{iframeSrc}"></iframe>',
70541         {
70542             compiled: true,
70543             disableFormats: true
70544         }
70545     ],
70546
70547     
70548     enableFormat : true,
70549     
70550     enableFontSize : true,
70551     
70552     enableColors : true,
70553     
70554     enableAlignments : true,
70555     
70556     enableLists : true,
70557     
70558     enableSourceEdit : true,
70559     
70560     enableLinks : true,
70561     
70562     enableFont : true,
70563     
70564     createLinkText : 'Please enter the URL for the link:',
70565     
70566     defaultLinkValue : 'http:/'+'/',
70567     
70568     fontFamilies : [
70569         'Arial',
70570         'Courier New',
70571         'Tahoma',
70572         'Times New Roman',
70573         'Verdana'
70574     ],
70575     defaultFont: 'tahoma',
70576     
70577     defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
70578
70579     fieldBodyCls: Ext.baseCSSPrefix + 'html-editor-wrap',
70580
70581     componentLayout: 'htmleditor',
70582
70583     
70584     initialized : false,
70585     activated : false,
70586     sourceEditMode : false,
70587     iframePad:3,
70588     hideMode:'offsets',
70589
70590     maskOnDisable: true,
70591     
70592     
70593     initComponent : function(){
70594         var me = this;
70595
70596         me.addEvents(
70597             
70598             'initialize',
70599             
70600             'activate',
70601              
70602             'beforesync',
70603              
70604             'beforepush',
70605              
70606             'sync',
70607              
70608             'push',
70609              
70610             'editmodechange'
70611         );
70612
70613         me.callParent(arguments);
70614
70615         
70616         me.initLabelable();
70617         me.initField();
70618     },
70619
70620     
70621     createToolbar : function(editor){
70622         var me = this,
70623             items = [],
70624             tipsEnabled = Ext.tip.QuickTipManager && Ext.tip.QuickTipManager.isEnabled(),
70625             baseCSSPrefix = Ext.baseCSSPrefix,
70626             fontSelectItem, toolbar, undef;
70627
70628         function btn(id, toggle, handler){
70629             return {
70630                 itemId : id,
70631                 cls : baseCSSPrefix + 'btn-icon',
70632                 iconCls: baseCSSPrefix + 'edit-'+id,
70633                 enableToggle:toggle !== false,
70634                 scope: editor,
70635                 handler:handler||editor.relayBtnCmd,
70636                 clickEvent:'mousedown',
70637                 tooltip: tipsEnabled ? editor.buttonTips[id] || undef : undef,
70638                 overflowText: editor.buttonTips[id].title || undef,
70639                 tabIndex:-1
70640             };
70641         }
70642
70643
70644         if (me.enableFont && !Ext.isSafari2) {
70645             fontSelectItem = Ext.widget('component', {
70646                 renderTpl: [
70647                     '<select class="{cls}">',
70648                         '<tpl for="fonts">',
70649                             '<option value="{[values.toLowerCase()]}" style="font-family:{.}"<tpl if="values.toLowerCase()==parent.defaultFont"> selected</tpl>>{.}</option>',
70650                         '</tpl>',
70651                     '</select>'
70652                 ],
70653                 renderData: {
70654                     cls: baseCSSPrefix + 'font-select',
70655                     fonts: me.fontFamilies,
70656                     defaultFont: me.defaultFont
70657                 },
70658                 renderSelectors: {
70659                     selectEl: 'select'
70660                 },
70661                 onDisable: function() {
70662                     var selectEl = this.selectEl;
70663                     if (selectEl) {
70664                         selectEl.dom.disabled = true;
70665                     }
70666                     Ext.Component.superclass.onDisable.apply(this, arguments);
70667                 },
70668                 onEnable: function() {
70669                     var selectEl = this.selectEl;
70670                     if (selectEl) {
70671                         selectEl.dom.disabled = false;
70672                     }
70673                     Ext.Component.superclass.onEnable.apply(this, arguments);
70674                 }
70675             });
70676
70677             items.push(
70678                 fontSelectItem,
70679                 '-'
70680             );
70681         }
70682
70683         if (me.enableFormat) {
70684             items.push(
70685                 btn('bold'),
70686                 btn('italic'),
70687                 btn('underline')
70688             );
70689         }
70690
70691         if (me.enableFontSize) {
70692             items.push(
70693                 '-',
70694                 btn('increasefontsize', false, me.adjustFont),
70695                 btn('decreasefontsize', false, me.adjustFont)
70696             );
70697         }
70698
70699         if (me.enableColors) {
70700             items.push(
70701                 '-', {
70702                     itemId: 'forecolor',
70703                     cls: baseCSSPrefix + 'btn-icon',
70704                     iconCls: baseCSSPrefix + 'edit-forecolor',
70705                     overflowText: editor.buttonTips.forecolor.title,
70706                     tooltip: tipsEnabled ? editor.buttonTips.forecolor || undef : undef,
70707                     tabIndex:-1,
70708                     menu : Ext.widget('menu', {
70709                         plain: true,
70710                         items: [{
70711                             xtype: 'colorpicker',
70712                             allowReselect: true,
70713                             focus: Ext.emptyFn,
70714                             value: '000000',
70715                             plain: true,
70716                             clickEvent: 'mousedown',
70717                             handler: function(cp, color) {
70718                                 me.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
70719                                 me.deferFocus();
70720                                 this.up('menu').hide();
70721                             }
70722                         }]
70723                     })
70724                 }, {
70725                     itemId: 'backcolor',
70726                     cls: baseCSSPrefix + 'btn-icon',
70727                     iconCls: baseCSSPrefix + 'edit-backcolor',
70728                     overflowText: editor.buttonTips.backcolor.title,
70729                     tooltip: tipsEnabled ? editor.buttonTips.backcolor || undef : undef,
70730                     tabIndex:-1,
70731                     menu : Ext.widget('menu', {
70732                         plain: true,
70733                         items: [{
70734                             xtype: 'colorpicker',
70735                             focus: Ext.emptyFn,
70736                             value: 'FFFFFF',
70737                             plain: true,
70738                             allowReselect: true,
70739                             clickEvent: 'mousedown',
70740                             handler: function(cp, color) {
70741                                 if (Ext.isGecko) {
70742                                     me.execCmd('useCSS', false);
70743                                     me.execCmd('hilitecolor', color);
70744                                     me.execCmd('useCSS', true);
70745                                     me.deferFocus();
70746                                 } else {
70747                                     me.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
70748                                     me.deferFocus();
70749                                 }
70750                                 this.up('menu').hide();
70751                             }
70752                         }]
70753                     })
70754                 }
70755             );
70756         }
70757
70758         if (me.enableAlignments) {
70759             items.push(
70760                 '-',
70761                 btn('justifyleft'),
70762                 btn('justifycenter'),
70763                 btn('justifyright')
70764             );
70765         }
70766
70767         if (!Ext.isSafari2) {
70768             if (me.enableLinks) {
70769                 items.push(
70770                     '-',
70771                     btn('createlink', false, me.createLink)
70772                 );
70773             }
70774
70775             if (me.enableLists) {
70776                 items.push(
70777                     '-',
70778                     btn('insertorderedlist'),
70779                     btn('insertunorderedlist')
70780                 );
70781             }
70782             if (me.enableSourceEdit) {
70783                 items.push(
70784                     '-',
70785                     btn('sourceedit', true, function(btn){
70786                         me.toggleSourceEdit(!me.sourceEditMode);
70787                     })
70788                 );
70789             }
70790         }
70791
70792         
70793         toolbar = Ext.widget('toolbar', {
70794             renderTo: me.toolbarWrap,
70795             enableOverflow: true,
70796             items: items
70797         });
70798
70799         if (fontSelectItem) {
70800             me.fontSelect = fontSelectItem.selectEl;
70801
70802             me.mon(me.fontSelect, 'change', function(){
70803                 me.relayCmd('fontname', me.fontSelect.dom.value);
70804                 me.deferFocus();
70805             });
70806         }
70807
70808         
70809         me.mon(toolbar.el, 'click', function(e){
70810             e.preventDefault();
70811         });
70812
70813         me.toolbar = toolbar;
70814     },
70815
70816     onDisable: function() {
70817         this.bodyEl.mask();
70818         this.callParent(arguments);
70819     },
70820
70821     onEnable: function() {
70822         this.bodyEl.unmask();
70823         this.callParent(arguments);
70824     },
70825
70826     
70827     setReadOnly: function(readOnly) {
70828         var me = this,
70829             textareaEl = me.textareaEl,
70830             iframeEl = me.iframeEl,
70831             body;
70832
70833         me.readOnly = readOnly;
70834
70835         if (textareaEl) {
70836             textareaEl.dom.readOnly = readOnly;
70837         }
70838
70839         if (me.initialized) {
70840             body = me.getEditorBody();
70841             if (Ext.isIE) {
70842                 
70843                 iframeEl.setDisplayed(false);
70844                 body.contentEditable = !readOnly;
70845                 iframeEl.setDisplayed(true);
70846             } else {
70847                 me.setDesignMode(!readOnly);
70848             }
70849             if (body) {
70850                 body.style.cursor = readOnly ? 'default' : 'text';
70851             }
70852             me.disableItems(readOnly);
70853         }
70854     },
70855
70856     
70857     getDocMarkup: function() {
70858         var me = this,
70859             h = me.iframeEl.getHeight() - me.iframePad * 2;
70860         return Ext.String.format('<html><head><style type="text/css">body{border:0;margin:0;padding:{0}px;height:{1}px;cursor:text}</style></head><body></body></html>', me.iframePad, h);
70861     },
70862
70863     
70864     getEditorBody: function() {
70865         var doc = this.getDoc();
70866         return doc.body || doc.documentElement;
70867     },
70868
70869     
70870     getDoc: function() {
70871         return (!Ext.isIE && this.iframeEl.dom.contentDocument) || this.getWin().document;
70872     },
70873
70874     
70875     getWin: function() {
70876         return Ext.isIE ? this.iframeEl.dom.contentWindow : window.frames[this.iframeEl.dom.name];
70877     },
70878
70879     
70880     onRender: function() {
70881         var me = this,
70882             renderSelectors = me.renderSelectors;
70883
70884         Ext.applyIf(renderSelectors, me.getLabelableSelectors());
70885
70886         Ext.applyIf(renderSelectors, {
70887             toolbarWrap: 'div.' + Ext.baseCSSPrefix + 'html-editor-tb',
70888             iframeEl: 'iframe',
70889             textareaEl: 'textarea'
70890         });
70891
70892         me.callParent(arguments);
70893
70894         me.textareaEl.dom.value = me.value || '';
70895
70896         
70897         me.monitorTask = Ext.TaskManager.start({
70898             run: me.checkDesignMode,
70899             scope: me,
70900             interval:100
70901         });
70902
70903         me.createToolbar(me);
70904         me.disableItems(true);
70905     },
70906
70907     initRenderTpl: function() {
70908         var me = this;
70909         if (!me.hasOwnProperty('renderTpl')) {
70910             me.renderTpl = me.getTpl('labelableRenderTpl');
70911         }
70912         return me.callParent();
70913     },
70914
70915     initRenderData: function() {
70916         return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
70917     },
70918
70919     getSubTplData: function() {
70920         var cssPrefix = Ext.baseCSSPrefix;
70921         return {
70922             toolbarWrapCls: cssPrefix + 'html-editor-tb',
70923             textareaCls: cssPrefix + 'hidden',
70924             iframeName: Ext.id(),
70925             iframeSrc: Ext.SSL_SECURE_URL,
70926             size: 'height:100px;'
70927         };
70928     },
70929
70930     getSubTplMarkup: function() {
70931         return this.getTpl('fieldSubTpl').apply(this.getSubTplData());
70932     },
70933
70934     getBodyNaturalWidth: function() {
70935         return 565;
70936     },
70937
70938     initFrameDoc: function() {
70939         var me = this,
70940             doc, task;
70941
70942         Ext.TaskManager.stop(me.monitorTask);
70943
70944         doc = me.getDoc();
70945         me.win = me.getWin();
70946
70947         doc.open();
70948         doc.write(me.getDocMarkup());
70949         doc.close();
70950
70951         task = { 
70952             run: function() {
70953                 var doc = me.getDoc();
70954                 if (doc.body || doc.readyState === 'complete') {
70955                     Ext.TaskManager.stop(task);
70956                     me.setDesignMode(true);
70957                     Ext.defer(me.initEditor, 10, me);
70958                 }
70959             },
70960             interval : 10,
70961             duration:10000,
70962             scope: me
70963         };
70964         Ext.TaskManager.start(task);
70965     },
70966
70967     checkDesignMode: function() {
70968         var me = this,
70969             doc = me.getDoc();
70970         if (doc && (!doc.editorInitialized || me.getDesignMode() !== 'on')) {
70971             me.initFrameDoc();
70972         }
70973     },
70974
70975     
70976     setDesignMode: function(mode) {
70977         var me = this,
70978             doc = me.getDoc();
70979         if (doc) {
70980             if (me.readOnly) {
70981                 mode = false;
70982             }
70983             doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
70984         }
70985     },
70986
70987     
70988     getDesignMode: function() {
70989         var doc = this.getDoc();
70990         return !doc ? '' : String(doc.designMode).toLowerCase();
70991     },
70992
70993     disableItems: function(disabled) {
70994         this.getToolbar().items.each(function(item){
70995             if(item.getItemId() !== 'sourceedit'){
70996                 item.setDisabled(disabled);
70997             }
70998         });
70999     },
71000
71001     
71002     toggleSourceEdit: function(sourceEditMode) {
71003         var me = this,
71004             iframe = me.iframeEl,
71005             textarea = me.textareaEl,
71006             hiddenCls = Ext.baseCSSPrefix + 'hidden',
71007             btn = me.getToolbar().getComponent('sourceedit');
71008
71009         if (!Ext.isBoolean(sourceEditMode)) {
71010             sourceEditMode = !me.sourceEditMode;
71011         }
71012         me.sourceEditMode = sourceEditMode;
71013
71014         if (btn.pressed !== sourceEditMode) {
71015             btn.toggle(sourceEditMode);
71016         }
71017         if (sourceEditMode) {
71018             me.disableItems(true);
71019             me.syncValue();
71020             iframe.addCls(hiddenCls);
71021             textarea.removeCls(hiddenCls);
71022             textarea.dom.removeAttribute('tabIndex');
71023             textarea.focus();
71024         }
71025         else {
71026             if (me.initialized) {
71027                 me.disableItems(me.readOnly);
71028             }
71029             me.pushValue();
71030             iframe.removeCls(hiddenCls);
71031             textarea.addCls(hiddenCls);
71032             textarea.dom.setAttribute('tabIndex', -1);
71033             me.deferFocus();
71034         }
71035         me.fireEvent('editmodechange', me, sourceEditMode);
71036         me.doComponentLayout();
71037     },
71038
71039     
71040     createLink : function() {
71041         var url = prompt(this.createLinkText, this.defaultLinkValue);
71042         if (url && url !== 'http:/'+'/') {
71043             this.relayCmd('createlink', url);
71044         }
71045     },
71046
71047     clearInvalid: Ext.emptyFn,
71048
71049     
71050     setValue: function(value) {
71051         var me = this,
71052             textarea = me.textareaEl;
71053         me.mixins.field.setValue.call(me, value);
71054         if (value === null || value === undefined) {
71055             value = '';
71056         }
71057         if (textarea) {
71058             textarea.dom.value = value;
71059         }
71060         me.pushValue();
71061         return this;
71062     },
71063
71064     
71065     cleanHtml: function(html) {
71066         html = String(html);
71067         if (Ext.isWebKit) { 
71068             html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
71069         }
71070
71071         
71072         if (html.charCodeAt(0) === this.defaultValue.replace(/\D/g, '')) {
71073             html = html.substring(1);
71074         }
71075         return html;
71076     },
71077
71078     
71079     syncValue : function(){
71080         var me = this,
71081             body, html, bodyStyle, match;
71082         if (me.initialized) {
71083             body = me.getEditorBody();
71084             html = body.innerHTML;
71085             if (Ext.isWebKit) {
71086                 bodyStyle = body.getAttribute('style'); 
71087                 match = bodyStyle.match(/text-align:(.*?);/i);
71088                 if (match && match[1]) {
71089                     html = '<div style="' + match[0] + '">' + html + '</div>';
71090                 }
71091             }
71092             html = me.cleanHtml(html);
71093             if (me.fireEvent('beforesync', me, html) !== false) {
71094                 me.textareaEl.dom.value = html;
71095                 me.fireEvent('sync', me, html);
71096             }
71097         }
71098     },
71099
71100     
71101     getValue : function() {
71102         var me = this,
71103             value;
71104         if (!me.sourceEditMode) {
71105             me.syncValue();
71106         }
71107         value = me.rendered ? me.textareaEl.dom.value : me.value;
71108         me.value = value;
71109         return value;
71110     },
71111
71112     
71113     pushValue: function() {
71114         var me = this,
71115             v;
71116         if(me.initialized){
71117             v = me.textareaEl.dom.value || '';
71118             if (!me.activated && v.length < 1) {
71119                 v = me.defaultValue;
71120             }
71121             if (me.fireEvent('beforepush', me, v) !== false) {
71122                 me.getEditorBody().innerHTML = v;
71123                 if (Ext.isGecko) {
71124                     
71125                     me.setDesignMode(false);  
71126                     me.setDesignMode(true);
71127                 }
71128                 me.fireEvent('push', me, v);
71129             }
71130         }
71131     },
71132
71133     
71134     deferFocus : function(){
71135          this.focus(false, true);
71136     },
71137
71138     getFocusEl: function() {
71139         var me = this,
71140             win = me.win;
71141         return win && !me.sourceEditMode ? win : me.textareaEl;
71142     },
71143
71144     
71145     initEditor : function(){
71146         
71147         try {
71148             var me = this,
71149                 dbody = me.getEditorBody(),
71150                 ss = me.textareaEl.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
71151                 doc,
71152                 fn;
71153
71154             ss['background-attachment'] = 'fixed'; 
71155             dbody.bgProperties = 'fixed'; 
71156
71157             Ext.core.DomHelper.applyStyles(dbody, ss);
71158
71159             doc = me.getDoc();
71160
71161             if (doc) {
71162                 try {
71163                     Ext.EventManager.removeAll(doc);
71164                 } catch(e) {}
71165             }
71166
71167             
71168             fn = Ext.Function.bind(me.onEditorEvent, me);
71169             Ext.EventManager.on(doc, {
71170                 mousedown: fn,
71171                 dblclick: fn,
71172                 click: fn,
71173                 keyup: fn,
71174                 buffer:100
71175             });
71176
71177             
71178             
71179             
71180             
71181             
71182             fn = me.onRelayedEvent;
71183             Ext.EventManager.on(doc, {
71184                 mousedown: fn, 
71185                 mousemove: fn, 
71186                 mouseup: fn,   
71187                 click: fn,     
71188                 dblclick: fn,  
71189                 scope: me
71190             });
71191
71192             if (Ext.isGecko) {
71193                 Ext.EventManager.on(doc, 'keypress', me.applyCommand, me);
71194             }
71195             if (me.fixKeys) {
71196                 Ext.EventManager.on(doc, 'keydown', me.fixKeys, me);
71197             }
71198
71199             
71200             Ext.EventManager.on(window, 'unload', me.beforeDestroy, me);
71201             doc.editorInitialized = true;
71202
71203             me.initialized = true;
71204             me.pushValue();
71205             me.setReadOnly(me.readOnly);
71206             me.fireEvent('initialize', me);
71207         } catch(ex) {
71208             
71209         }
71210     },
71211
71212     
71213     beforeDestroy : function(){
71214         var me = this,
71215             monitorTask = me.monitorTask,
71216             doc, prop;
71217
71218         if (monitorTask) {
71219             Ext.TaskManager.stop(monitorTask);
71220         }
71221         if (me.rendered) {
71222             try {
71223                 doc = me.getDoc();
71224                 if (doc) {
71225                     Ext.EventManager.removeAll(doc);
71226                     for (prop in doc) {
71227                         if (doc.hasOwnProperty(prop)) {
71228                             delete doc[prop];
71229                         }
71230                     }
71231                 }
71232             } catch(e) {
71233                 
71234             }
71235             Ext.destroyMembers('tb', 'toolbarWrap', 'iframeEl', 'textareaEl');
71236         }
71237         me.callParent();
71238     },
71239
71240     
71241     onRelayedEvent: function (event) {
71242         
71243
71244         var iframeEl = this.iframeEl,
71245             iframeXY = iframeEl.getXY(),
71246             eventXY = event.getXY();
71247
71248         
71249         
71250         event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]];
71251
71252         event.injectEvent(iframeEl); 
71253
71254         event.xy = eventXY; 
71255     },
71256
71257     
71258     onFirstFocus : function(){
71259         var me = this,
71260             selection, range;
71261         me.activated = true;
71262         me.disableItems(me.readOnly);
71263         if (Ext.isGecko) { 
71264             me.win.focus();
71265             selection = me.win.getSelection();
71266             if (!selection.focusNode || selection.focusNode.nodeType !== 3) {
71267                 range = selection.getRangeAt(0);
71268                 range.selectNodeContents(me.getEditorBody());
71269                 range.collapse(true);
71270                 me.deferFocus();
71271             }
71272             try {
71273                 me.execCmd('useCSS', true);
71274                 me.execCmd('styleWithCSS', false);
71275             } catch(e) {
71276                 
71277             }
71278         }
71279         me.fireEvent('activate', me);
71280     },
71281
71282     
71283     adjustFont: function(btn) {
71284         var adjust = btn.getItemId() === 'increasefontsize' ? 1 : -1,
71285             size = this.getDoc().queryCommandValue('FontSize') || '2',
71286             isPxSize = Ext.isString(size) && size.indexOf('px') !== -1,
71287             isSafari;
71288         size = parseInt(size, 10);
71289         if (isPxSize) {
71290             
71291             
71292             if (size <= 10) {
71293                 size = 1 + adjust;
71294             }
71295             else if (size <= 13) {
71296                 size = 2 + adjust;
71297             }
71298             else if (size <= 16) {
71299                 size = 3 + adjust;
71300             }
71301             else if (size <= 18) {
71302                 size = 4 + adjust;
71303             }
71304             else if (size <= 24) {
71305                 size = 5 + adjust;
71306             }
71307             else {
71308                 size = 6 + adjust;
71309             }
71310             size = Ext.Number.constrain(size, 1, 6);
71311         } else {
71312             isSafari = Ext.isSafari;
71313             if (isSafari) { 
71314                 adjust *= 2;
71315             }
71316             size = Math.max(1, size + adjust) + (isSafari ? 'px' : 0);
71317         }
71318         this.execCmd('FontSize', size);
71319     },
71320
71321     
71322     onEditorEvent: function(e) {
71323         this.updateToolbar();
71324     },
71325
71326     
71327     updateToolbar: function() {
71328         var me = this,
71329             btns, doc, name, fontSelect;
71330
71331         if (me.readOnly) {
71332             return;
71333         }
71334
71335         if (!me.activated) {
71336             me.onFirstFocus();
71337             return;
71338         }
71339
71340         btns = me.getToolbar().items.map;
71341         doc = me.getDoc();
71342
71343         if (me.enableFont && !Ext.isSafari2) {
71344             name = (doc.queryCommandValue('FontName') || me.defaultFont).toLowerCase();
71345             fontSelect = me.fontSelect.dom;
71346             if (name !== fontSelect.value) {
71347                 fontSelect.value = name;
71348             }
71349         }
71350
71351         function updateButtons() {
71352             Ext.Array.forEach(Ext.Array.toArray(arguments), function(name) {
71353                 btns[name].toggle(doc.queryCommandState(name));
71354             });
71355         }
71356         if(me.enableFormat){
71357             updateButtons('bold', 'italic', 'underline');
71358         }
71359         if(me.enableAlignments){
71360             updateButtons('justifyleft', 'justifycenter', 'justifyright');
71361         }
71362         if(!Ext.isSafari2 && me.enableLists){
71363             updateButtons('insertorderedlist', 'insertunorderedlist');
71364         }
71365
71366         Ext.menu.Manager.hideAll();
71367
71368         me.syncValue();
71369     },
71370
71371     
71372     relayBtnCmd: function(btn) {
71373         this.relayCmd(btn.getItemId());
71374     },
71375
71376     
71377     relayCmd: function(cmd, value) {
71378         Ext.defer(function() {
71379             var me = this;
71380             me.focus();
71381             me.execCmd(cmd, value);
71382             me.updateToolbar();
71383         }, 10, this);
71384     },
71385
71386     
71387     execCmd : function(cmd, value){
71388         var me = this,
71389             doc = me.getDoc(),
71390             undef;
71391         doc.execCommand(cmd, false, value === undef ? null : value);
71392         me.syncValue();
71393     },
71394
71395     
71396     applyCommand : function(e){
71397         if (e.ctrlKey) {
71398             var me = this,
71399                 c = e.getCharCode(), cmd;
71400             if (c > 0) {
71401                 c = String.fromCharCode(c);
71402                 switch (c) {
71403                     case 'b':
71404                         cmd = 'bold';
71405                     break;
71406                     case 'i':
71407                         cmd = 'italic';
71408                     break;
71409                     case 'u':
71410                         cmd = 'underline';
71411                     break;
71412                 }
71413                 if (cmd) {
71414                     me.win.focus();
71415                     me.execCmd(cmd);
71416                     me.deferFocus();
71417                     e.preventDefault();
71418                 }
71419             }
71420         }
71421     },
71422
71423     
71424     insertAtCursor : function(text){
71425         var me = this,
71426             range;
71427
71428         if (me.activated) {
71429             me.win.focus();
71430             if (Ext.isIE) {
71431                 range = me.getDoc().selection.createRange();
71432                 if (range) {
71433                     range.pasteHTML(text);
71434                     me.syncValue();
71435                     me.deferFocus();
71436                 }
71437             }else{
71438                 me.execCmd('InsertHTML', text);
71439                 me.deferFocus();
71440             }
71441         }
71442     },
71443
71444     
71445     fixKeys: function() { 
71446         if (Ext.isIE) {
71447             return function(e){
71448                 var me = this,
71449                     k = e.getKey(),
71450                     doc = me.getDoc(),
71451                     range, target;
71452                 if (k === e.TAB) {
71453                     e.stopEvent();
71454                     range = doc.selection.createRange();
71455                     if(range){
71456                         range.collapse(true);
71457                         range.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
71458                         me.deferFocus();
71459                     }
71460                 }
71461                 else if (k === e.ENTER) {
71462                     range = doc.selection.createRange();
71463                     if (range) {
71464                         target = range.parentElement();
71465                         if(!target || target.tagName.toLowerCase() !== 'li'){
71466                             e.stopEvent();
71467                             range.pasteHTML('<br />');
71468                             range.collapse(false);
71469                             range.select();
71470                         }
71471                     }
71472                 }
71473             };
71474         }
71475
71476         if (Ext.isOpera) {
71477             return function(e){
71478                 var me = this;
71479                 if (e.getKey() === e.TAB) {
71480                     e.stopEvent();
71481                     me.win.focus();
71482                     me.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
71483                     me.deferFocus();
71484                 }
71485             };
71486         }
71487
71488         if (Ext.isWebKit) {
71489             return function(e){
71490                 var me = this,
71491                     k = e.getKey();
71492                 if (k === e.TAB) {
71493                     e.stopEvent();
71494                     me.execCmd('InsertText','\t');
71495                     me.deferFocus();
71496                 }
71497                 else if (k === e.ENTER) {
71498                     e.stopEvent();
71499                     me.execCmd('InsertHtml','<br /><br />');
71500                     me.deferFocus();
71501                 }
71502             };
71503         }
71504
71505         return null; 
71506     }(),
71507
71508     
71509     getToolbar : function(){
71510         return this.toolbar;
71511     },
71512
71513     
71514     buttonTips : {
71515         bold : {
71516             title: 'Bold (Ctrl+B)',
71517             text: 'Make the selected text bold.',
71518             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71519         },
71520         italic : {
71521             title: 'Italic (Ctrl+I)',
71522             text: 'Make the selected text italic.',
71523             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71524         },
71525         underline : {
71526             title: 'Underline (Ctrl+U)',
71527             text: 'Underline the selected text.',
71528             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71529         },
71530         increasefontsize : {
71531             title: 'Grow Text',
71532             text: 'Increase the font size.',
71533             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71534         },
71535         decreasefontsize : {
71536             title: 'Shrink Text',
71537             text: 'Decrease the font size.',
71538             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71539         },
71540         backcolor : {
71541             title: 'Text Highlight Color',
71542             text: 'Change the background color of the selected text.',
71543             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71544         },
71545         forecolor : {
71546             title: 'Font Color',
71547             text: 'Change the color of the selected text.',
71548             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71549         },
71550         justifyleft : {
71551             title: 'Align Text Left',
71552             text: 'Align text to the left.',
71553             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71554         },
71555         justifycenter : {
71556             title: 'Center Text',
71557             text: 'Center text in the editor.',
71558             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71559         },
71560         justifyright : {
71561             title: 'Align Text Right',
71562             text: 'Align text to the right.',
71563             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71564         },
71565         insertunorderedlist : {
71566             title: 'Bullet List',
71567             text: 'Start a bulleted list.',
71568             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71569         },
71570         insertorderedlist : {
71571             title: 'Numbered List',
71572             text: 'Start a numbered list.',
71573             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71574         },
71575         createlink : {
71576             title: 'Hyperlink',
71577             text: 'Make the selected text a hyperlink.',
71578             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71579         },
71580         sourceedit : {
71581             title: 'Source Edit',
71582             text: 'Switch to source editing mode.',
71583             cls: Ext.baseCSSPrefix + 'html-editor-tip'
71584         }
71585     }
71586
71587     
71588     
71589     
71590     
71591     
71592     
71593     
71594     
71595     
71596     
71597     
71598     
71599     
71600     
71601     
71602     
71603     
71604 });
71605
71606
71607 Ext.define('Ext.form.field.Radio', {
71608     extend:'Ext.form.field.Checkbox',
71609     alias: ['widget.radiofield', 'widget.radio'],
71610     alternateClassName: 'Ext.form.Radio',
71611     requires: ['Ext.form.RadioManager'],
71612
71613     isRadio: true,
71614
71615     
71616
71617     
71618     inputType: 'radio',
71619     ariaRole: 'radio',
71620
71621     
71622     getGroupValue: function() {
71623         var selected = this.getManager().getChecked(this.name);
71624         return selected ? selected.inputValue : null;
71625     },
71626
71627     
71628     onBoxClick: function(e) {
71629         var me = this;
71630         if (!me.disabled && !me.readOnly) {
71631             this.setValue(true);
71632         }
71633     },
71634
71635     
71636     setValue: function(v) {
71637         var me = this,
71638             active;
71639
71640         if (Ext.isBoolean(v)) {
71641             me.callParent(arguments);
71642         } else {
71643             active = me.getManager().getWithValue(me.name, v).getAt(0);
71644             if (active) {
71645                 active.setValue(true);
71646             }
71647         }
71648         return me;
71649     },
71650
71651     
71652     getSubmitValue: function() {
71653         return this.checked ? this.inputValue : null;
71654     },
71655
71656     
71657     onChange: function(newVal, oldVal) {
71658         var me = this;
71659         me.callParent(arguments);
71660
71661         if (newVal) {
71662             this.getManager().getByName(me.name).each(function(item){
71663                 if (item !== me) {
71664                     item.setValue(false);
71665                 }
71666             }, me);
71667         }
71668     },
71669
71670     
71671     beforeDestroy: function(){
71672         this.callParent();
71673         this.getManager().removeAtKey(this.id);
71674     },
71675
71676     
71677     getManager: function() {
71678         return Ext.form.RadioManager;
71679     }
71680 });
71681
71682
71683 Ext.define('Ext.picker.Time', {
71684     extend: 'Ext.view.BoundList',
71685     alias: 'widget.timepicker',
71686     requires: ['Ext.data.Store', 'Ext.Date'],
71687
71688     
71689
71690     
71691
71692     
71693     increment: 15,
71694
71695     
71696     format : "g:i A",
71697
71698     
71699     displayField: 'disp',
71700
71701     
71702     initDate: [2008,1,1],
71703
71704     componentCls: Ext.baseCSSPrefix + 'timepicker',
71705
71706     
71707     loadingText: '',
71708
71709     initComponent: function() {
71710         var me = this,
71711             dateUtil = Ext.Date,
71712             clearTime = dateUtil.clearTime,
71713             initDate = me.initDate.join('/');
71714
71715         
71716         me.absMin = clearTime(new Date(initDate));
71717         me.absMax = dateUtil.add(clearTime(new Date(initDate)), 'mi', (24 * 60) - 1);
71718
71719         me.store = me.createStore();
71720         me.updateList();
71721
71722         this.callParent();
71723     },
71724
71725     
71726     setMinValue: function(value) {
71727         this.minValue = value;
71728         this.updateList();
71729     },
71730
71731     
71732     setMaxValue: function(value) {
71733         this.maxValue = value;
71734         this.updateList();
71735     },
71736
71737     
71738     normalizeDate: function(date) {
71739         var initDate = this.initDate;
71740         date.setFullYear(initDate[0], initDate[1] - 1, initDate[2]);
71741         return date;
71742     },
71743
71744     
71745     updateList: function() {
71746         var me = this,
71747             min = me.normalizeDate(me.minValue || me.absMin),
71748             max = me.normalizeDate(me.maxValue || me.absMax);
71749
71750         me.store.filterBy(function(record) {
71751             var date = record.get('date');
71752             return date >= min && date <= max;
71753         });
71754     },
71755
71756     
71757     createStore: function() {
71758         var me = this,
71759             utilDate = Ext.Date,
71760             times = [],
71761             min = me.absMin,
71762             max = me.absMax;
71763
71764         while(min <= max){
71765             times.push({
71766                 disp: utilDate.dateFormat(min, me.format),
71767                 date: min
71768             });
71769             min = utilDate.add(min, 'mi', me.increment);
71770         }
71771
71772         return Ext.create('Ext.data.Store', {
71773             fields: ['disp', 'date'],
71774             data: times
71775         });
71776     }
71777
71778 });
71779
71780
71781 Ext.define('Ext.form.field.Time', {
71782     extend:'Ext.form.field.Picker',
71783     alias: 'widget.timefield',
71784     requires: ['Ext.form.field.Date', 'Ext.picker.Time', 'Ext.view.BoundListKeyNav', 'Ext.Date'],
71785     alternateClassName: ['Ext.form.TimeField', 'Ext.form.Time'],
71786
71787     
71788     triggerCls: Ext.baseCSSPrefix + 'form-time-trigger',
71789
71790     
71791
71792     
71793
71794     
71795     minText : "The time in this field must be equal to or after {0}",
71796
71797     
71798     maxText : "The time in this field must be equal to or before {0}",
71799
71800     
71801     invalidText : "{0} is not a valid time",
71802
71803     
71804     format : "g:i A",
71805
71806     
71807
71808     
71809     altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A",
71810
71811     
71812     increment: 15,
71813
71814     
71815     pickerMaxHeight: 300,
71816
71817     
71818     selectOnTab: true,
71819
71820     
71821     initDate: '1/1/2008',
71822     initDateFormat: 'j/n/Y',
71823
71824
71825     initComponent: function() {
71826         var me = this,
71827             min = me.minValue,
71828             max = me.maxValue;
71829         if (min) {
71830             me.setMinValue(min);
71831         }
71832         if (max) {
71833             me.setMaxValue(max);
71834         }
71835         this.callParent();
71836     },
71837
71838     initValue: function() {
71839         var me = this,
71840             value = me.value;
71841
71842         
71843         if (Ext.isString(value)) {
71844             me.value = me.rawToValue(value);
71845         }
71846
71847         me.callParent();
71848     },
71849
71850     
71851     setMinValue: function(value) {
71852         var me = this,
71853             picker = me.picker;
71854         me.setLimit(value, true);
71855         if (picker) {
71856             picker.setMinValue(me.minValue);
71857         }
71858     },
71859
71860     
71861     setMaxValue: function(value) {
71862         var me = this,
71863             picker = me.picker;
71864         me.setLimit(value, false);
71865         if (picker) {
71866             picker.setMaxValue(me.maxValue);
71867         }
71868     },
71869
71870     
71871     setLimit: function(value, isMin) {
71872         var me = this,
71873             d, val;
71874         if (Ext.isString(value)) {
71875             d = me.parseDate(value);
71876         }
71877         else if (Ext.isDate(value)) {
71878             d = value;
71879         }
71880         if (d) {
71881             val = Ext.Date.clearTime(new Date(me.initDate));
71882             val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
71883             me[isMin ? 'minValue' : 'maxValue'] = val;
71884         }
71885     },
71886
71887     rawToValue: function(rawValue) {
71888         return this.parseDate(rawValue) || rawValue || null;
71889     },
71890
71891     valueToRaw: function(value) {
71892         return this.formatDate(this.parseDate(value));
71893     },
71894
71895     
71896     getErrors: function(value) {
71897         var me = this,
71898             format = Ext.String.format,
71899             errors = me.callParent(arguments),
71900             minValue = me.minValue,
71901             maxValue = me.maxValue,
71902             date;
71903
71904         value = me.formatDate(value || me.processRawValue(me.getRawValue()));
71905
71906         if (value === null || value.length < 1) { 
71907              return errors;
71908         }
71909
71910         date = me.parseDate(value);
71911         if (!date) {
71912             errors.push(format(me.invalidText, value, me.format));
71913             return errors;
71914         }
71915
71916         if (minValue && date < minValue) {
71917             errors.push(format(me.minText, me.formatDate(minValue)));
71918         }
71919
71920         if (maxValue && date > maxValue) {
71921             errors.push(format(me.maxText, me.formatDate(maxValue)));
71922         }
71923
71924         return errors;
71925     },
71926
71927     formatDate: function() {
71928         return Ext.form.field.Date.prototype.formatDate.apply(this, arguments);
71929     },
71930
71931     
71932     parseDate: function(value) {
71933         if (!value || Ext.isDate(value)) {
71934             return value;
71935         }
71936
71937         var me = this,
71938             val = me.safeParse(value, me.format),
71939             altFormats = me.altFormats,
71940             altFormatsArray = me.altFormatsArray,
71941             i = 0,
71942             len;
71943
71944         if (!val && altFormats) {
71945             altFormatsArray = altFormatsArray || altFormats.split('|');
71946             len = altFormatsArray.length;
71947             for (; i < len && !val; ++i) {
71948                 val = me.safeParse(value, altFormatsArray[i]);
71949             }
71950         }
71951         return val;
71952     },
71953
71954     safeParse: function(value, format){
71955         var me = this,
71956             utilDate = Ext.Date,
71957             parsedDate,
71958             result = null;
71959
71960         if (utilDate.formatContainsDateInfo(format)) {
71961             
71962             result = utilDate.parse(value, format);
71963         } else {
71964             
71965             parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
71966             if (parsedDate) {
71967                 result = parsedDate;
71968             }
71969         }
71970         return result;
71971     },
71972
71973     
71974     getSubmitValue: function() {
71975         var me = this,
71976             format = me.submitFormat || me.format,
71977             value = me.getValue();
71978
71979         return value ? Ext.Date.format(value, format) : null;
71980     },
71981
71982     
71983     createPicker: function() {
71984         var me = this,
71985             picker = Ext.create('Ext.picker.Time', {
71986                 selModel: {
71987                     mode: 'SINGLE'
71988                 },
71989                 floating: true,
71990                 hidden: true,
71991                 minValue: me.minValue,
71992                 maxValue: me.maxValue,
71993                 increment: me.increment,
71994                 format: me.format,
71995                 ownerCt: this.ownerCt,
71996                 renderTo: document.body,
71997                 maxHeight: me.pickerMaxHeight,
71998                 focusOnToFront: false
71999             });
72000
72001         me.mon(picker.getSelectionModel(), {
72002             selectionchange: me.onListSelect,
72003             scope: me
72004         });
72005
72006         return picker;
72007     },
72008
72009     
72010     onExpand: function() {
72011         var me = this,
72012             keyNav = me.pickerKeyNav,
72013             selectOnTab = me.selectOnTab,
72014             picker = me.getPicker(),
72015             lastSelected = picker.getSelectionModel().lastSelected,
72016             itemNode;
72017
72018         if (!keyNav) {
72019             keyNav = me.pickerKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
72020                 boundList: picker,
72021                 forceKeyDown: true,
72022                 tab: function(e) {
72023                     if (selectOnTab) {
72024                         this.selectHighlighted(e);
72025                         me.triggerBlur();
72026                     }
72027                     
72028                     return true;
72029                 }
72030             });
72031             
72032             if (selectOnTab) {
72033                 me.ignoreMonitorTab = true;
72034             }
72035         }
72036         Ext.defer(keyNav.enable, 1, keyNav); 
72037
72038         
72039         if (lastSelected) {
72040             itemNode = picker.getNode(lastSelected);
72041             if (itemNode) {
72042                 picker.highlightItem(itemNode);
72043                 picker.el.scrollChildIntoView(itemNode, false);
72044             }
72045         }
72046     },
72047
72048     
72049     onCollapse: function() {
72050         var me = this,
72051             keyNav = me.pickerKeyNav;
72052         if (keyNav) {
72053             keyNav.disable();
72054             me.ignoreMonitorTab = false;
72055         }
72056     },
72057
72058     
72059     onListSelect: function(list, recordArray) {
72060         var me = this,
72061             record = recordArray[0],
72062             val = record ? record.get('date') : null;
72063         me.setValue(val);
72064         me.fireEvent('select', me, val);
72065         me.picker.clearHighlight();
72066         me.collapse();
72067         me.inputEl.focus();
72068     }
72069 });
72070
72071
72072
72073 Ext.define('Ext.grid.CellEditor', {
72074     extend: 'Ext.Editor',
72075     constructor: function(config) {
72076         if (config.field) {
72077             config.field.monitorTab = false;
72078         }
72079         config.autoSize = {
72080             width: 'boundEl'
72081         };
72082         this.callParent(arguments);
72083     },
72084     
72085     
72086     onShow: function() {
72087         var first = this.boundEl.first();
72088         if (first) {
72089             first.hide();
72090         }
72091         this.callParent(arguments);
72092     },
72093     
72094     
72095     onHide: function() {
72096         var first = this.boundEl.first();
72097         if (first) {
72098             first.show();
72099         }
72100         this.callParent(arguments);
72101     },
72102     
72103     
72104     afterRender: function() {
72105         this.callParent(arguments);
72106         var field = this.field;
72107         if (field.isXType('checkboxfield')) {
72108             field.mon(field.inputEl, 'mousedown', this.onCheckBoxMouseDown, this);
72109             field.mon(field.inputEl, 'click', this.onCheckBoxClick, this);
72110         }
72111     },
72112     
72113     
72114     onCheckBoxMouseDown: function() {
72115         this.completeEdit = Ext.emptyFn;
72116     },
72117     
72118     
72119     onCheckBoxClick: function() {
72120         delete this.completeEdit;
72121         this.field.focus(false, 10);
72122     },
72123     
72124     alignment: "tl-tl",
72125     hideEl : false,
72126     cls: Ext.baseCSSPrefix + "small-editor " + Ext.baseCSSPrefix + "grid-editor",
72127     shim: false,
72128     shadow: false
72129 });
72130
72131 Ext.define('Ext.grid.ColumnLayout', {
72132     extend: 'Ext.layout.container.HBox',
72133     alias: 'layout.gridcolumn',
72134     type : 'column',
72135
72136     
72137     clearInnerCtOnLayout: false,
72138
72139     constructor: function() {
72140         var me = this;
72141         me.callParent(arguments);
72142         if (!Ext.isDefined(me.availableSpaceOffset)) {
72143             me.availableSpaceOffset = (Ext.getScrollBarWidth() - 2);
72144         }
72145     },
72146
72147     beforeLayout: function() {
72148         var me = this,
72149             i = 0,
72150             items = me.getLayoutItems(),
72151             len = items.length,
72152             item, returnValue;
72153
72154         returnValue = me.callParent(arguments);
72155
72156         
72157         me.innerCt.setHeight(23);
72158
72159         
72160         if (me.align == 'stretchmax') {
72161             for (; i < len; i++) {
72162                 item = items[i];
72163                 item.el.setStyle({
72164                     height: 'auto'
72165                 });
72166                 item.titleContainer.setStyle({
72167                     height: 'auto',
72168                     paddingTop: '0'
72169                 });
72170                 if (item.componentLayout && item.componentLayout.lastComponentSize) {
72171                     item.componentLayout.lastComponentSize.height = item.el.dom.offsetHeight;
72172                 }
72173             }
72174         }
72175         return returnValue;
72176     },
72177
72178     
72179     calculateChildBoxes: function(visibleItems, targetSize) {
72180         var me = this,
72181             calculations = me.callParent(arguments),
72182             boxes = calculations.boxes,
72183             metaData = calculations.meta,
72184             len = boxes.length, i = 0, box, item;
72185
72186         if (targetSize.width && !me.isColumn) {
72187             
72188             if (me.owner.forceFit) {
72189
72190                 for (; i < len; i++) {
72191                     box = boxes[i];
72192                     item = box.component;
72193
72194                     
72195                     item.minWidth = Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
72196
72197                     
72198                     
72199                     item.flex = box.width;
72200                 }
72201
72202                 
72203                 calculations = me.callParent(arguments);
72204             }
72205             else if (metaData.tooNarrow) {
72206                 targetSize.width = metaData.desiredSize;
72207             }
72208         }
72209
72210         return calculations;
72211     },
72212
72213     afterLayout: function() {
72214         var me = this,
72215             i = 0,
72216             items = me.getLayoutItems(),
72217             len = items.length;
72218
72219         me.callParent(arguments);
72220
72221         
72222         if (me.align == 'stretchmax') {
72223             for (; i < len; i++) {
72224                 items[i].setPadding();
72225             }
72226         }
72227     },
72228
72229     
72230     
72231     updateInnerCtSize: function(tSize, calcs) {
72232         var me    = this,
72233             extra = 0;
72234
72235         
72236         if (!me.isColumn && calcs.meta.tooNarrow) {
72237             if (
72238                 Ext.isWebKit ||
72239                 Ext.isGecko ||
72240                 (Ext.isIEQuirks && (Ext.isIE6 || Ext.isIE7 || Ext.isIE8))
72241             ) {
72242                 extra = 1;
72243             
72244             } else if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
72245                 extra = 2;
72246             }
72247             
72248             
72249             extra++;
72250             tSize.width = calcs.meta.desiredSize + (me.reserveOffset ? me.availableSpaceOffset : 0) + extra;
72251         }
72252         return me.callParent(arguments);
72253     },
72254
72255     doOwnerCtLayouts: function() {
72256         var ownerCt = this.owner.ownerCt;
72257         if (!ownerCt.componentLayout.layoutBusy) {
72258             ownerCt.doComponentLayout();
72259         }
72260     }
72261 });
72262
72263 Ext.define('Ext.grid.LockingView', {
72264     
72265     mixins: {
72266         observable: 'Ext.util.Observable'
72267     },
72268     
72269     eventRelayRe: /^(beforeitem|beforecontainer|item|container|cell)/,
72270     
72271     constructor: function(config){
72272         var me = this,
72273             eventNames = [],
72274             eventRe = me.eventRelayRe,
72275             locked = config.locked.getView(),
72276             normal = config.normal.getView(),
72277             events,
72278             event;
72279         
72280         Ext.apply(me, {
72281             lockedView: locked,
72282             normalView: normal,
72283             lockedGrid: config.locked,
72284             normalGrid: config.normal,
72285             panel: config.panel
72286         });
72287         me.mixins.observable.constructor.call(me, config);
72288         
72289         
72290         events = locked.events;
72291         for (event in events) {
72292             if (events.hasOwnProperty(event) && eventRe.test(event)) {
72293                 eventNames.push(event);
72294             }
72295         }
72296         me.relayEvents(locked, eventNames);
72297         me.relayEvents(normal, eventNames);
72298         
72299         normal.on({
72300             scope: me,
72301             itemmouseleave: me.onItemMouseLeave,
72302             itemmouseenter: me.onItemMouseEnter
72303         });
72304         
72305         locked.on({
72306             scope: me,
72307             itemmouseleave: me.onItemMouseLeave,
72308             itemmouseenter: me.onItemMouseEnter
72309         });
72310     },
72311     
72312     getGridColumns: function() {
72313         var cols = this.lockedGrid.headerCt.getGridColumns();
72314         return cols.concat(this.normalGrid.headerCt.getGridColumns());
72315     },
72316     
72317     onItemMouseEnter: function(view, record){
72318         var me = this,
72319             locked = me.lockedView,
72320             other = me.normalView,
72321             item;
72322             
72323         if (view.trackOver) {
72324             if (view !== locked) {
72325                 other = locked;
72326             }
72327             item = other.getNode(record);
72328             other.highlightItem(item);
72329         }
72330     },
72331     
72332     onItemMouseLeave: function(view, record){
72333         var me = this,
72334             locked = me.lockedView,
72335             other = me.normalView;
72336             
72337         if (view.trackOver) {
72338             if (view !== locked) {
72339                 other = locked;
72340             }
72341             other.clearHighlight();
72342         }
72343     },
72344     
72345     relayFn: function(name, args){
72346         args = args || [];
72347         
72348         var view = this.lockedView;
72349         view[name].apply(view, args || []);    
72350         view = this.normalView;
72351         view[name].apply(view, args || []);   
72352     },
72353     
72354     getSelectionModel: function(){
72355         return this.panel.getSelectionModel();    
72356     },
72357     
72358     getStore: function(){
72359         return this.panel.store;
72360     },
72361     
72362     getNode: function(nodeInfo){
72363         
72364         return this.normalView.getNode(nodeInfo);
72365     },
72366     
72367     getCell: function(record, column){
72368         var view = this.lockedView,
72369             row;
72370         
72371         
72372         if (view.getHeaderAtIndex(column) === -1) {
72373             view = this.normalView;
72374         }
72375         
72376         row = view.getNode(record);
72377         return Ext.fly(row).down(column.getCellSelector());
72378     },
72379     
72380     getRecord: function(node){
72381         var result = this.lockedView.getRecord(node);
72382         if (!node) {
72383             result = this.normalView.getRecord(node);
72384         }
72385         return result;
72386     },
72387     
72388     refreshNode: function(){
72389         this.relayFn('refreshNode', arguments);
72390     },
72391     
72392     refresh: function(){
72393         this.relayFn('refresh', arguments);
72394     },
72395     
72396     bindStore: function(){
72397         this.relayFn('bindStore', arguments);
72398     },
72399     
72400     addRowCls: function(){
72401         this.relayFn('addRowCls', arguments);
72402     },
72403     
72404     removeRowCls: function(){
72405         this.relayFn('removeRowCls', arguments);
72406     }
72407        
72408 });
72409
72410 Ext.define('Ext.grid.Lockable', {
72411     
72412     requires: ['Ext.grid.LockingView'],
72413     
72414     
72415     syncRowHeight: true,
72416     
72417     
72418     
72419     
72420
72421     
72422     
72423     
72424     spacerHidden: true,
72425     
72426     
72427     unlockText: 'Unlock',
72428     lockText: 'Lock',
72429     
72430     determineXTypeToCreate: function() {
72431         var me = this,
72432             typeToCreate;
72433
72434         if (me.subGridXType) {
72435             typeToCreate = me.subGridXType;
72436         } else {
72437             var xtypes     = this.getXTypes().split('/'),
72438                 xtypesLn   = xtypes.length,
72439                 xtype      = xtypes[xtypesLn - 1],
72440                 superxtype = xtypes[xtypesLn - 2];
72441                 
72442             if (superxtype !== 'tablepanel') {
72443                 typeToCreate = superxtype;
72444             } else {
72445                 typeToCreate = xtype;
72446             }
72447         }
72448         
72449         return typeToCreate;
72450     },
72451     
72452     
72453     
72454     injectLockable: function() {
72455         
72456         this.lockable = true;
72457         
72458         
72459         this.hasView = true;
72460
72461         var me = this,
72462             
72463             
72464             
72465             xtype = me.determineXTypeToCreate(),
72466             
72467             selModel = me.getSelectionModel(),
72468             lockedGrid = {
72469                 xtype: xtype,
72470                 
72471                 enableAnimations: false,
72472                 scroll: false,
72473                 scrollerOwner: false,
72474                 selModel: selModel,
72475                 border: false,
72476                 cls: Ext.baseCSSPrefix + 'grid-inner-locked'
72477             },
72478             normalGrid = {
72479                 xtype: xtype,
72480                 enableAnimations: false,
72481                 scrollerOwner: false,
72482                 selModel: selModel,
72483                 border: false
72484             },
72485             i = 0,
72486             columns,
72487             lockedHeaderCt,
72488             normalHeaderCt;
72489         
72490         me.addCls(Ext.baseCSSPrefix + 'grid-locked');
72491         
72492         
72493         
72494         
72495         Ext.copyTo(normalGrid, me, me.normalCfgCopy);
72496         Ext.copyTo(lockedGrid, me, me.lockedCfgCopy);
72497         for (; i < me.normalCfgCopy.length; i++) {
72498             delete me[me.normalCfgCopy[i]];
72499         }
72500         for (i = 0; i < me.lockedCfgCopy.length; i++) {
72501             delete me[me.lockedCfgCopy[i]];
72502         }
72503         
72504         me.lockedHeights = [];
72505         me.normalHeights = [];
72506         
72507         columns = me.processColumns(me.columns);
72508
72509         lockedGrid.width = columns.lockedWidth;
72510         lockedGrid.columns = columns.locked;
72511         normalGrid.columns = columns.normal;
72512         
72513         me.store = Ext.StoreManager.lookup(me.store);
72514         lockedGrid.store = me.store;
72515         normalGrid.store = me.store;
72516         
72517         
72518         normalGrid.flex = 1;
72519         lockedGrid.viewConfig = me.lockedViewConfig || {};
72520         lockedGrid.viewConfig.loadingUseMsg = false;
72521         normalGrid.viewConfig = me.normalViewConfig || {};
72522         
72523         Ext.applyIf(lockedGrid.viewConfig, me.viewConfig);
72524         Ext.applyIf(normalGrid.viewConfig, me.viewConfig);
72525         
72526         me.normalGrid = Ext.ComponentManager.create(normalGrid);
72527         me.lockedGrid = Ext.ComponentManager.create(lockedGrid);
72528         
72529         me.view = Ext.create('Ext.grid.LockingView', {
72530             locked: me.lockedGrid,
72531             normal: me.normalGrid,
72532             panel: me    
72533         });
72534         
72535         if (me.syncRowHeight) {
72536             me.lockedGrid.getView().on({
72537                 refresh: me.onLockedGridAfterRefresh,
72538                 itemupdate: me.onLockedGridAfterUpdate,
72539                 scope: me
72540             });
72541             
72542             me.normalGrid.getView().on({
72543                 refresh: me.onNormalGridAfterRefresh,
72544                 itemupdate: me.onNormalGridAfterUpdate,
72545                 scope: me
72546             });
72547         }
72548         
72549         lockedHeaderCt = me.lockedGrid.headerCt;
72550         normalHeaderCt = me.normalGrid.headerCt;
72551         
72552         lockedHeaderCt.lockedCt = true;
72553         lockedHeaderCt.lockableInjected = true;
72554         normalHeaderCt.lockableInjected = true;
72555         
72556         lockedHeaderCt.on({
72557             columnshow: me.onLockedHeaderShow,
72558             columnhide: me.onLockedHeaderHide,
72559             columnmove: me.onLockedHeaderMove,
72560             sortchange: me.onLockedHeaderSortChange,
72561             columnresize: me.onLockedHeaderResize,
72562             scope: me
72563         });
72564         
72565         normalHeaderCt.on({
72566             columnmove: me.onNormalHeaderMove,
72567             sortchange: me.onNormalHeaderSortChange,
72568             scope: me
72569         });
72570         
72571         me.normalGrid.on({
72572             scrollershow: me.onScrollerShow,
72573             scrollerhide: me.onScrollerHide,
72574             scope: me
72575         });
72576         
72577         me.lockedGrid.on('afterlayout', me.onLockedGridAfterLayout, me, {single: true});
72578         
72579         me.modifyHeaderCt();
72580         me.items = [me.lockedGrid, me.normalGrid];
72581
72582         me.layout = {
72583             type: 'hbox',
72584             align: 'stretch'
72585         };
72586     },
72587     
72588     processColumns: function(columns){
72589         
72590         var i = 0,
72591             len = columns.length,
72592             lockedWidth = 0,
72593             lockedHeaders = [],
72594             normalHeaders = [],
72595             column;
72596             
72597         for (; i < len; ++i) {
72598             column = columns[i];
72599             
72600             
72601             column.processed = true;
72602             if (column.locked) {
72603                 if (column.flex) {
72604                     Ext.Error.raise("Columns which are locked do NOT support a flex width. You must set a width on the " + columns[i].text + "column.");
72605                 }
72606                 lockedWidth += column.width;
72607                 lockedHeaders.push(column);
72608             } else {
72609                 normalHeaders.push(column);
72610             }
72611         }
72612         return {
72613             lockedWidth: lockedWidth,
72614             locked: lockedHeaders,
72615             normal: normalHeaders    
72616         };
72617     },
72618     
72619     
72620     onLockedGridAfterLayout: function() {
72621         var me         = this,
72622             lockedView = me.lockedGrid.getView();
72623         lockedView.on({
72624             refresh: me.createSpacer,
72625             beforerefresh: me.destroySpacer,
72626             scope: me
72627         });
72628     },
72629     
72630     
72631     onLockedHeaderMove: function() {
72632         if (this.syncRowHeight) {
72633             this.onNormalGridAfterRefresh();
72634         }
72635     },
72636     
72637     
72638     onNormalHeaderMove: function() {
72639         if (this.syncRowHeight) {
72640             this.onLockedGridAfterRefresh();
72641         }
72642     },
72643     
72644     
72645     
72646     createSpacer: function() {
72647         var me   = this,
72648             
72649             
72650             w    = Ext.getScrollBarWidth() + (Ext.isIE ? 2 : 0),
72651             view = me.lockedGrid.getView(),
72652             el   = view.el;
72653
72654         me.spacerEl = Ext.core.DomHelper.append(el, {
72655             cls: me.spacerHidden ? (Ext.baseCSSPrefix + 'hidden') : '',
72656             style: 'height: ' + w + 'px;'
72657         }, true);
72658     },
72659     
72660     destroySpacer: function() {
72661         var me = this;
72662         if (me.spacerEl) {
72663             me.spacerEl.destroy();
72664             delete me.spacerEl;
72665         }
72666     },
72667     
72668     
72669     onLockedGridAfterRefresh: function() {
72670         var me     = this,
72671             view   = me.lockedGrid.getView(),
72672             el     = view.el,
72673             rowEls = el.query(view.getItemSelector()),
72674             ln     = rowEls.length,
72675             i = 0;
72676             
72677         
72678         me.lockedHeights = [];
72679         
72680         for (; i < ln; i++) {
72681             me.lockedHeights[i] = rowEls[i].clientHeight;
72682         }
72683         me.syncRowHeights();
72684     },
72685     
72686     
72687     onNormalGridAfterRefresh: function() {
72688         var me     = this,
72689             view   = me.normalGrid.getView(),
72690             el     = view.el,
72691             rowEls = el.query(view.getItemSelector()),
72692             ln     = rowEls.length,
72693             i = 0;
72694             
72695         
72696         me.normalHeights = [];
72697         
72698         for (; i < ln; i++) {
72699             me.normalHeights[i] = rowEls[i].clientHeight;
72700         }
72701         me.syncRowHeights();
72702     },
72703     
72704     
72705     onLockedGridAfterUpdate: function(record, index, node) {
72706         this.lockedHeights[index] = node.clientHeight;
72707         this.syncRowHeights();
72708     },
72709     
72710     
72711     onNormalGridAfterUpdate: function(record, index, node) {
72712         this.normalHeights[index] = node.clientHeight;
72713         this.syncRowHeights();
72714     },
72715     
72716     
72717     
72718     syncRowHeights: function() {
72719         var me = this,
72720             lockedHeights = me.lockedHeights,
72721             normalHeights = me.normalHeights,
72722             calcHeights   = [],
72723             ln = lockedHeights.length,
72724             i  = 0,
72725             lockedView, normalView,
72726             lockedRowEls, normalRowEls,
72727             vertScroller = me.getVerticalScroller(),
72728             scrollTop;
72729
72730         
72731         
72732         if (lockedHeights.length && normalHeights.length) {
72733             lockedView = me.lockedGrid.getView();
72734             normalView = me.normalGrid.getView();
72735             lockedRowEls = lockedView.el.query(lockedView.getItemSelector());
72736             normalRowEls = normalView.el.query(normalView.getItemSelector());
72737
72738             
72739             for (; i < ln; i++) {
72740                 
72741                 if (!isNaN(lockedHeights[i]) && !isNaN(normalHeights[i])) {
72742                     if (lockedHeights[i] > normalHeights[i]) {
72743                         Ext.fly(normalRowEls[i]).setHeight(lockedHeights[i]);
72744                     } else if (lockedHeights[i] < normalHeights[i]) {
72745                         Ext.fly(lockedRowEls[i]).setHeight(normalHeights[i]);
72746                     }
72747                 }
72748             }
72749
72750             
72751             me.normalGrid.invalidateScroller();
72752             
72753             
72754             
72755             if (vertScroller && vertScroller.setViewScrollTop) {
72756                 vertScroller.setViewScrollTop(me.virtualScrollTop);
72757             } else {
72758                 
72759                 
72760                 
72761                 scrollTop = normalView.el.dom.scrollTop;
72762                 normalView.el.dom.scrollTop = scrollTop;
72763                 lockedView.el.dom.scrollTop = scrollTop;
72764             }
72765             
72766             
72767             me.lockedHeights = [];
72768             me.normalHeights = [];
72769         }
72770     },
72771     
72772     
72773     onScrollerShow: function(scroller, direction) {
72774         if (direction === 'horizontal') {
72775             this.spacerHidden = false;
72776             this.spacerEl.removeCls(Ext.baseCSSPrefix + 'hidden');
72777         }
72778     },
72779     
72780     
72781     onScrollerHide: function(scroller, direction) {
72782         if (direction === 'horizontal') {
72783             this.spacerHidden = true;
72784             this.spacerEl.addCls(Ext.baseCSSPrefix + 'hidden');
72785         }
72786     },
72787
72788     
72789     
72790     modifyHeaderCt: function() {
72791         var me = this;
72792         me.lockedGrid.headerCt.getMenuItems = me.getMenuItems(true);
72793         me.normalGrid.headerCt.getMenuItems = me.getMenuItems(false);
72794     },
72795     
72796     onUnlockMenuClick: function() {
72797         this.unlock();
72798     },
72799     
72800     onLockMenuClick: function() {
72801         this.lock();
72802     },
72803     
72804     getMenuItems: function(locked) {
72805         var me            = this,
72806             unlockText    = me.unlockText,
72807             lockText      = me.lockText,
72808             
72809             unlockCls     = 'xg-hmenu-unlock',
72810             lockCls       = 'xg-hmenu-lock',
72811             unlockHandler = Ext.Function.bind(me.onUnlockMenuClick, me),
72812             lockHandler   = Ext.Function.bind(me.onLockMenuClick, me);
72813         
72814         
72815         return function() {
72816             var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
72817             o.push('-',{
72818                 cls: unlockCls,
72819                 text: unlockText,
72820                 handler: unlockHandler,
72821                 disabled: !locked
72822             });
72823             o.push({
72824                 cls: lockCls,
72825                 text: lockText,
72826                 handler: lockHandler,
72827                 disabled: locked
72828             });
72829             return o;
72830         };
72831     },
72832     
72833     
72834     
72835     lock: function(activeHd, toIdx) {
72836         var me         = this,
72837             normalGrid = me.normalGrid,
72838             lockedGrid = me.lockedGrid,
72839             normalHCt  = normalGrid.headerCt,
72840             lockedHCt  = lockedGrid.headerCt;
72841             
72842         activeHd = activeHd || normalHCt.getMenu().activeHeader;
72843         
72844         
72845         
72846         if (activeHd.flex) {
72847             activeHd.width = activeHd.getWidth();
72848             delete activeHd.flex;
72849         }
72850         
72851         normalHCt.remove(activeHd, false);
72852         lockedHCt.suspendLayout = true;
72853         if (Ext.isDefined(toIdx)) {
72854             lockedHCt.insert(toIdx, activeHd);
72855         } else {
72856             lockedHCt.add(activeHd);
72857         }
72858         lockedHCt.suspendLayout = false;
72859         me.syncLockedSection();
72860     },
72861     
72862     syncLockedSection: function() {
72863         var me = this;
72864         me.syncLockedWidth();
72865         me.lockedGrid.getView().refresh();
72866         me.normalGrid.getView().refresh();
72867     },
72868     
72869     
72870     
72871     syncLockedWidth: function() {
72872         var me = this,
72873             width = me.lockedGrid.headerCt.getFullWidth(true);
72874         me.lockedGrid.setWidth(width);
72875     },
72876     
72877     onLockedHeaderResize: function() {
72878         this.syncLockedWidth();
72879     },
72880     
72881     onLockedHeaderHide: function() {
72882         this.syncLockedWidth();
72883     },
72884     
72885     onLockedHeaderShow: function() {
72886         this.syncLockedWidth();
72887     },
72888     
72889     onLockedHeaderSortChange: function(headerCt, header, sortState) {
72890         if (sortState) {
72891             
72892             
72893             this.normalGrid.headerCt.clearOtherSortStates(null, true);
72894         }
72895     },
72896     
72897     onNormalHeaderSortChange: function(headerCt, header, sortState) {
72898         if (sortState) {
72899             
72900             
72901             this.lockedGrid.headerCt.clearOtherSortStates(null, true);
72902         }
72903     },
72904     
72905     
72906     
72907     unlock: function(activeHd, toIdx) {
72908         var me         = this,
72909             normalGrid = me.normalGrid,
72910             lockedGrid = me.lockedGrid,
72911             normalHCt  = normalGrid.headerCt,
72912             lockedHCt  = lockedGrid.headerCt;
72913
72914         if (!Ext.isDefined(toIdx)) {
72915             toIdx = 0;
72916         }
72917         activeHd = activeHd || lockedHCt.getMenu().activeHeader;
72918         
72919         lockedHCt.remove(activeHd, false);
72920         me.syncLockedWidth();
72921         me.lockedGrid.getView().refresh();
72922         normalHCt.insert(toIdx, activeHd);
72923         me.normalGrid.getView().refresh();
72924     },
72925     
72926     
72927     reconfigureLockable: function(store, columns) {
72928         var me = this,
72929             lockedGrid = me.lockedGrid,
72930             normalGrid = me.normalGrid;
72931         
72932         if (columns) {
72933             lockedGrid.headerCt.removeAll();
72934             normalGrid.headerCt.removeAll();
72935             
72936             columns = me.processColumns(columns);
72937             lockedGrid.setWidth(columns.lockedWidth);
72938             lockedGrid.headerCt.add(columns.locked);
72939             normalGrid.headerCt.add(columns.normal);
72940         }
72941         
72942         if (store) {
72943             store = Ext.data.StoreManager.lookup(store);
72944             me.store = store;
72945             lockedGrid.bindStore(store);
72946             normalGrid.bindStore(store);
72947         } else {
72948             lockedGrid.getView().refresh();
72949             normalGrid.getView().refresh();
72950         }
72951     }
72952 });
72953
72954
72955 Ext.define('Ext.grid.Scroller', {
72956     extend: 'Ext.Component',
72957     alias: 'widget.gridscroller',
72958     weight: 110,
72959     cls: Ext.baseCSSPrefix + 'scroller',
72960     focusable: false,
72961     
72962     renderTpl: ['<div class="' + Ext.baseCSSPrefix + 'stretcher"></div>'],
72963     
72964     initComponent: function() {
72965         var me       = this,
72966             dock     = me.dock,
72967             cls      = Ext.baseCSSPrefix + 'scroller-vertical',
72968             sizeProp = 'width',
72969             
72970             
72971             
72972             
72973             
72974             scrollbarWidth = Ext.getScrollBarWidth() + (Ext.isIE ? 1 : -1);
72975
72976         me.offsets = {bottom: 0};
72977
72978         if (dock === 'top' || dock === 'bottom') {
72979             cls = Ext.baseCSSPrefix + 'scroller-horizontal';
72980             sizeProp = 'height';
72981         }
72982         me[sizeProp] = scrollbarWidth;
72983         
72984         me.cls += (' ' + cls);
72985         
72986         Ext.applyIf(me.renderSelectors, {
72987             stretchEl: '.' + Ext.baseCSSPrefix + 'stretcher'
72988         });
72989         me.callParent();
72990     },
72991     
72992     
72993     afterRender: function() {
72994         var me = this;
72995         me.callParent();
72996         me.ownerCt.on('afterlayout', me.onOwnerAfterLayout, me);
72997         me.mon(me.el, 'scroll', me.onElScroll, me);
72998         Ext.cache[me.el.id].skipGarbageCollection = true;
72999     },
73000     
73001     getSizeCalculation: function() {
73002         var owner  = this.getPanel(),
73003             dock   = this.dock,
73004             elDom  = this.el.dom,
73005             width  = 1,
73006             height = 1,
73007             view, tbl;
73008             
73009         if (dock === 'top' || dock === 'bottom') {
73010             
73011             
73012             var items  = owner.query('tableview'),
73013                 center = items[1] || items[0];
73014             
73015             if (!center) {
73016                 return false;
73017             }
73018             
73019             
73020             
73021             width = center.headerCt.getFullWidth();
73022             
73023             if (Ext.isIEQuirks) {
73024                 width--;
73025             }
73026             
73027             width--;
73028         } else {            
73029             view = owner.down('tableview:not([lockableInjected])');
73030             if (!view) {
73031                 return false;
73032             }
73033             tbl = view.el;
73034             if (!tbl) {
73035                 return false;
73036             }
73037             
73038             
73039             
73040             height = tbl.dom.scrollHeight;
73041         }
73042         if (isNaN(width)) {
73043             width = 1;
73044         }
73045         if (isNaN(height)) {
73046             height = 1;
73047         }
73048         return {
73049             width: width,
73050             height: height
73051         };
73052     },
73053     
73054     invalidate: function(firstPass) {
73055         if (!this.stretchEl || !this.ownerCt) {
73056             return;
73057         }
73058         var size  = this.getSizeCalculation(),
73059             elDom = this.el.dom;
73060         if (size) {
73061             this.stretchEl.setSize(size);
73062         
73063             
73064             
73065             elDom.scrollTop = elDom.scrollTop;
73066         }
73067     },
73068
73069     onOwnerAfterLayout: function(owner, layout) {
73070         this.invalidate();
73071     },
73072
73073     
73074     setScrollTop: function(scrollTop) {
73075         if (this.el) {
73076             var elDom = this.el.dom;
73077             return elDom.scrollTop = Ext.Number.constrain(scrollTop, 0, elDom.scrollHeight - elDom.clientHeight);
73078         }
73079     },
73080
73081     
73082     setScrollLeft: function(scrollLeft) {
73083         if (this.el) {
73084             var elDom = this.el.dom;
73085             return elDom.scrollLeft = Ext.Number.constrain(scrollLeft, 0, elDom.scrollWidth - elDom.clientWidth);
73086         }
73087     },
73088
73089     
73090     scrollByDeltaY: function(delta) {
73091         if (this.el) {
73092             var elDom = this.el.dom;
73093             return this.setScrollTop(elDom.scrollTop + delta);
73094         }
73095     },
73096
73097     
73098     scrollByDeltaX: function(delta) {
73099         if (this.el) {
73100             var elDom = this.el.dom;
73101             return this.setScrollLeft(elDom.scrollLeft + delta);
73102         }
73103     },
73104     
73105     
73106     
73107     scrollToTop : function(){
73108         this.setScrollTop(0);
73109     },
73110     
73111     
73112     onElScroll: function(event, target) {
73113         this.fireEvent('bodyscroll', event, target);
73114     },
73115
73116     getPanel: function() {
73117         var me = this;
73118         if (!me.panel) {
73119             me.panel = this.up('[scrollerOwner]');
73120         }
73121         return me.panel;
73122     }
73123 });
73124
73125
73126
73127 Ext.define('Ext.grid.PagingScroller', {
73128     extend: 'Ext.grid.Scroller',
73129     alias: 'widget.paginggridscroller',
73130     
73131     
73132     
73133     
73134     
73135     
73136     
73137     percentageFromEdge: 0.35,
73138     
73139     
73140     scrollToLoadBuffer: 200,
73141     
73142     activePrefetch: true,
73143     
73144     chunkSize: 50,
73145     snapIncrement: 25,
73146     
73147     syncScroll: true,
73148     
73149     initComponent: function() {
73150         var me = this,
73151             ds = me.store;
73152
73153         ds.on('guaranteedrange', this.onGuaranteedRange, this);
73154         this.callParent(arguments);
73155     },
73156     
73157     
73158     onGuaranteedRange: function(range, start, end) {
73159         var me = this,
73160             ds = me.store,
73161             rs;
73162         
73163         if (range.length && me.visibleStart < range[0].index) {
73164             return;
73165         }
73166         
73167         ds.loadRecords(range);
73168
73169         if (!me.firstLoad) {
73170             if (me.rendered) {
73171                 me.invalidate();
73172             } else {
73173                 me.on('afterrender', this.invalidate, this, {single: true});
73174             }
73175             me.firstLoad = true;
73176         } else {
73177             
73178             me.syncTo();
73179         }
73180     },
73181     
73182     syncTo: function() {
73183         var me            = this,
73184             pnl           = me.getPanel(),
73185             store         = pnl.store,
73186             scrollerElDom = this.el.dom,
73187             rowOffset     = me.visibleStart - store.guaranteedStart,
73188             scrollBy      = rowOffset * me.rowHeight,
73189             scrollHeight  = scrollerElDom.scrollHeight,
73190             clientHeight  = scrollerElDom.clientHeight,
73191             scrollTop     = scrollerElDom.scrollTop,
73192             useMaximum;
73193         
73194         
73195         
73196         if (Ext.isIE9 && Ext.isStrict) {
73197             clientHeight = scrollerElDom.offsetHeight + 2;
73198         }
73199
73200         
73201         
73202         useMaximum = (scrollHeight - clientHeight - scrollTop <= 0);
73203         this.setViewScrollTop(scrollBy, useMaximum);
73204     },
73205     
73206     getPageData : function(){
73207         var panel = this.getPanel(),
73208             store = panel.store,
73209             totalCount = store.getTotalCount();
73210             
73211         return {
73212             total : totalCount,
73213             currentPage : store.currentPage,
73214             pageCount: Math.ceil(totalCount / store.pageSize),
73215             fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
73216             toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
73217         };
73218     },
73219     
73220     onElScroll: function(e, t) {
73221         var me = this,
73222             panel = me.getPanel(),
73223             store = panel.store,
73224             pageSize = store.pageSize,
73225             guaranteedStart = store.guaranteedStart,
73226             guaranteedEnd = store.guaranteedEnd,
73227             totalCount = store.getTotalCount(),
73228             numFromEdge = Math.ceil(me.percentageFromEdge * store.pageSize),
73229             position = t.scrollTop,
73230             visibleStart = Math.floor(position / me.rowHeight),
73231             view = panel.down('tableview'),
73232             viewEl = view.el,
73233             visibleHeight = viewEl.getHeight(),
73234             visibleAhead = Math.ceil(visibleHeight / me.rowHeight),
73235             visibleEnd = visibleStart + visibleAhead,
73236             prevPage = Math.floor(visibleStart / store.pageSize),
73237             nextPage = Math.floor(visibleEnd / store.pageSize) + 2,
73238             lastPage = Math.ceil(totalCount / store.pageSize),
73239             
73240             requestStart = Math.floor(visibleStart / me.snapIncrement) * me.snapIncrement,
73241             requestEnd = requestStart + pageSize - 1,
73242             activePrefetch = me.activePrefetch;
73243
73244         me.visibleStart = visibleStart;
73245         me.visibleEnd = visibleEnd;
73246         
73247         
73248         me.syncScroll = true;
73249         if (totalCount >= pageSize) {
73250             
73251             if (requestEnd > totalCount - 1) {
73252                 this.cancelLoad();
73253                 if (store.rangeSatisfied(totalCount - pageSize, totalCount - 1)) {
73254                     me.syncScroll = true;
73255                 }
73256                 store.guaranteeRange(totalCount - pageSize, totalCount - 1);
73257             
73258             } else if (visibleStart < guaranteedStart || visibleEnd > guaranteedEnd) {
73259                 if (store.rangeSatisfied(requestStart, requestEnd)) {
73260                     this.cancelLoad();
73261                     store.guaranteeRange(requestStart, requestEnd);
73262                 } else {
73263                     store.mask();
73264                     me.attemptLoad(requestStart, requestEnd);
73265                 }
73266                 
73267                 me.syncScroll = false;
73268             } else if (activePrefetch && visibleStart < (guaranteedStart + numFromEdge) && prevPage > 0) {
73269                 me.syncScroll = true;
73270                 store.prefetchPage(prevPage);
73271             } else if (activePrefetch && visibleEnd > (guaranteedEnd - numFromEdge) && nextPage < lastPage) {
73272                 me.syncScroll = true;
73273                 store.prefetchPage(nextPage);
73274             }
73275         }
73276     
73277     
73278         if (me.syncScroll) {
73279             me.syncTo();
73280         }
73281     },
73282     
73283     getSizeCalculation: function() {
73284         
73285         
73286         var owner = this.ownerCt,
73287             view   = owner.getView(),
73288             store  = this.store,
73289             dock   = this.dock,
73290             elDom  = this.el.dom,
73291             width  = 1,
73292             height = 1;
73293         
73294         if (!this.rowHeight) {
73295             this.rowHeight = view.el.down(view.getItemSelector()).getHeight(false, true);
73296         }
73297
73298         height = store.getTotalCount() * this.rowHeight;
73299
73300         if (isNaN(width)) {
73301             width = 1;
73302         }
73303         if (isNaN(height)) {
73304             height = 1;
73305         }
73306         return {
73307             width: width,
73308             height: height
73309         };
73310     },
73311     
73312     attemptLoad: function(start, end) {
73313         var me = this;
73314         if (!me.loadTask) {
73315             me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
73316         }
73317         me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]);
73318     },
73319     
73320     cancelLoad: function() {
73321         if (this.loadTask) {
73322             this.loadTask.cancel();
73323         }
73324     },
73325     
73326     doAttemptLoad:  function(start, end) {
73327         var store = this.getPanel().store;
73328         store.guaranteeRange(start, end);
73329     },
73330     
73331     setViewScrollTop: function(scrollTop, useMax) {
73332         var owner = this.getPanel(),
73333             items = owner.query('tableview'),
73334             i = 0,
73335             len = items.length,
73336             center,
73337             centerEl,
73338             calcScrollTop,
73339             maxScrollTop,
73340             scrollerElDom = this.el.dom;
73341             
73342         owner.virtualScrollTop = scrollTop;
73343             
73344         center = items[1] || items[0];
73345         centerEl = center.el.dom;
73346         
73347         maxScrollTop = ((owner.store.pageSize * this.rowHeight) - centerEl.clientHeight);
73348         calcScrollTop = (scrollTop % ((owner.store.pageSize * this.rowHeight) + 1));
73349         if (useMax) {
73350             calcScrollTop = maxScrollTop;
73351         }
73352         if (calcScrollTop > maxScrollTop) {
73353             
73354             return;
73355             
73356         }
73357         for (; i < len; i++) {
73358             items[i].el.dom.scrollTop = calcScrollTop;
73359         }
73360     }
73361 });
73362
73363
73364
73365 Ext.define('Ext.panel.Table', {
73366     extend: 'Ext.panel.Panel',
73367
73368     alias: 'widget.tablepanel',
73369
73370     uses: [
73371         'Ext.selection.RowModel',
73372         'Ext.grid.Scroller',
73373         'Ext.grid.header.Container',
73374         'Ext.grid.Lockable'
73375     ],
73376
73377     cls: Ext.baseCSSPrefix + 'grid',
73378     extraBodyCls: Ext.baseCSSPrefix + 'grid-body',
73379
73380     layout: 'fit',
73381     
73382     hasView: false,
73383
73384     
73385     viewType: null,
73386     selType: 'rowmodel',
73387
73388     
73389     scrollDelta: 40,
73390
73391     
73392     scroll: true,
73393
73394     
73395
73396     
73397
73398     
73399
73400     
73401     sortableColumns: true,
73402
73403     verticalScrollDock: 'right',
73404     verticalScrollerType: 'gridscroller',
73405
73406     horizontalScrollerPresentCls: Ext.baseCSSPrefix + 'horizontal-scroller-present',
73407     verticalScrollerPresentCls: Ext.baseCSSPrefix + 'vertical-scroller-present',
73408
73409     
73410     
73411     scrollerOwner: true,
73412
73413     invalidateScrollerOnRefresh: true,
73414     
73415     enableColumnMove: true,
73416     enableColumnResize: true,
73417
73418
73419     initComponent: function() {
73420         if (!this.viewType) {
73421             Ext.Error.raise("You must specify a viewType config.");
73422         }
73423         if (!this.store) {
73424             Ext.Error.raise("You must specify a store config");
73425         }
73426         if (this.headers) {
73427             Ext.Error.raise("The headers config is not supported. Please specify columns instead.");
73428         }
73429
73430         var me          = this,
73431             scroll      = me.scroll,
73432             vertical    = false,
73433             horizontal  = false,
73434             headerCtCfg = me.columns || me.colModel,
73435             i           = 0,
73436             view,
73437             border = me.border;
73438
73439         
73440         me.determineScrollbars = Ext.Function.createBuffered(me.determineScrollbars, 30);
73441         me.injectView = Ext.Function.createBuffered(me.injectView, 30);
73442
73443         if (me.hideHeaders) {
73444             border = false;
73445         }
73446
73447         
73448         
73449         if (headerCtCfg instanceof Ext.grid.header.Container) {
73450             me.headerCt = headerCtCfg;
73451             me.headerCt.border = border;
73452             me.columns = me.headerCt.items.items;
73453         } else {
73454             if (Ext.isArray(headerCtCfg)) {
73455                 headerCtCfg = {
73456                     items: headerCtCfg,
73457                     border: border
73458                 };
73459             }
73460             Ext.apply(headerCtCfg, {
73461                 forceFit: me.forceFit,
73462                 sortable: me.sortableColumns,
73463                 enableColumnMove: me.enableColumnMove,
73464                 enableColumnResize: me.enableColumnResize,
73465                 border:  border
73466             });
73467             me.columns = headerCtCfg.items;
73468
73469              
73470              
73471              if (Ext.ComponentQuery.query('{locked !== undefined}{processed != true}', me.columns).length) {
73472                  me.self.mixin('lockable', Ext.grid.Lockable);
73473                  me.injectLockable();
73474              }
73475         }
73476
73477         me.store = Ext.data.StoreManager.lookup(me.store);
73478         me.addEvents(
73479             
73480             'scrollerhide',
73481             
73482             'scrollershow'
73483         );
73484
73485         me.bodyCls = me.bodyCls || '';
73486         me.bodyCls += (' ' + me.extraBodyCls);
73487
73488         
73489         delete me.autoScroll;
73490
73491         
73492         
73493         if (!me.hasView) {
73494
73495             
73496             
73497             if (!me.headerCt) {
73498                 me.headerCt = Ext.create('Ext.grid.header.Container', headerCtCfg);
73499             }
73500
73501             
73502             me.columns = me.headerCt.items.items;
73503
73504             if (me.hideHeaders) {
73505                 me.headerCt.height = 0;
73506                 me.headerCt.border = false;
73507                 me.headerCt.addCls(Ext.baseCSSPrefix + 'grid-header-ct-hidden');
73508                 me.addCls(Ext.baseCSSPrefix + 'grid-header-hidden');
73509                 
73510                 
73511                 if (Ext.isIEQuirks) {
73512                     me.headerCt.style = {
73513                         display: 'none'
73514                     };
73515                 }
73516             }
73517
73518             
73519             if (scroll === true || scroll === 'both') {
73520                 vertical = horizontal = true;
73521             } else if (scroll === 'horizontal') {
73522                 horizontal = true;
73523             } else if (scroll === 'vertical') {
73524                 vertical = true;
73525             
73526             } else {
73527                 me.headerCt.availableSpaceOffset = 0;
73528             }
73529
73530             if (vertical) {
73531                 me.verticalScroller = me.verticalScroller || {};
73532                 Ext.applyIf(me.verticalScroller, {
73533                     dock: me.verticalScrollDock,
73534                     xtype: me.verticalScrollerType,
73535                     store: me.store
73536                 });
73537                 me.verticalScroller = Ext.ComponentManager.create(me.verticalScroller);
73538                 me.mon(me.verticalScroller, {
73539                     bodyscroll: me.onVerticalScroll,
73540                     scope: me
73541                 });
73542             }
73543
73544             if (horizontal) {
73545                 me.horizontalScroller = Ext.ComponentManager.create({
73546                     xtype: 'gridscroller',
73547                     section: me,
73548                     dock: 'bottom',
73549                     store: me.store
73550                 });
73551                 me.mon(me.horizontalScroller, {
73552                     bodyscroll: me.onHorizontalScroll,
73553                     scope: me
73554                 });
73555             }
73556
73557             me.headerCt.on('columnresize', me.onHeaderResize, me);
73558             me.relayEvents(me.headerCt, ['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange']);
73559             me.features = me.features || [];
73560             me.dockedItems = me.dockedItems || [];
73561             me.dockedItems.unshift(me.headerCt);
73562             me.viewConfig = me.viewConfig || {};
73563             me.viewConfig.invalidateScrollerOnRefresh = me.invalidateScrollerOnRefresh;
73564
73565             
73566             
73567             view = me.getView();
73568
73569             if (view) {
73570                 me.mon(view.store, {
73571                     load: me.onStoreLoad,
73572                     scope: me
73573                 });
73574                 me.mon(view, {
73575                     refresh: {
73576                         fn: this.onViewRefresh,
73577                         scope: me,
73578                         buffer: 50
73579                     },
73580                     itemupdate: me.onViewItemUpdate,
73581                     scope: me
73582                 });
73583                 this.relayEvents(view, [
73584                     
73585                     'beforeitemmousedown',
73586                     
73587                     'beforeitemmouseup',
73588                     
73589                     'beforeitemmouseenter',
73590                     
73591                     'beforeitemmouseleave',
73592                     
73593                     'beforeitemclick',
73594                     
73595                     'beforeitemdblclick',
73596                     
73597                     'beforeitemcontextmenu',
73598                     
73599                     'itemmousedown',
73600                     
73601                     'itemmouseup',
73602                     
73603                     'itemmouseenter',
73604                     
73605                     'itemmouseleave',
73606                     
73607                     'itemclick',
73608                     
73609                     'itemdblclick',
73610                     
73611                     'itemcontextmenu',
73612                     
73613                     'beforecontainermousedown',
73614                     
73615                     'beforecontainermouseup',
73616                     
73617                     'beforecontainermouseover',
73618                     
73619                     'beforecontainermouseout',
73620                     
73621                     'beforecontainerclick',
73622                     
73623                     'beforecontainerdblclick',
73624                     
73625                     'beforecontainercontextmenu',
73626                     
73627                     'containermouseup',
73628                     
73629                     'containermouseover',
73630                     
73631                     'containermouseout',
73632                     
73633                     'containerclick',
73634                     
73635                     'containerdblclick',
73636                     
73637                     'containercontextmenu',
73638
73639                     
73640                     'selectionchange',
73641                     
73642                     'beforeselect'
73643                 ]);
73644             }
73645         }
73646         me.callParent(arguments);
73647     },
73648
73649     
73650     initStateEvents: function(){
73651         var events = this.stateEvents;
73652         
73653         Ext.each(['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange'], function(event){
73654             if (Ext.Array.indexOf(events, event)) {
73655                 events.push(event);
73656             }
73657         });
73658         this.callParent();
73659     },
73660
73661     getState: function(){
73662         var state = {
73663             columns: []
73664         },
73665         sorter = this.store.sorters.first();
73666
73667         this.headerCt.items.each(function(header){
73668             state.columns.push({
73669                 id: header.headerId,
73670                 width: header.flex ? undefined : header.width,
73671                 hidden: header.hidden,
73672                 sortable: header.sortable
73673             });
73674         });
73675
73676         if (sorter) {
73677             state.sort = {
73678                 property: sorter.property,
73679                 direction: sorter.direction
73680             };
73681         }
73682         return state;
73683     },
73684
73685     applyState: function(state) {
73686         var headers = state.columns,
73687             length = headers ? headers.length : 0,
73688             headerCt = this.headerCt,
73689             items = headerCt.items,
73690             sorter = state.sort,
73691             store = this.store,
73692             i = 0,
73693             index,
73694             headerState,
73695             header;
73696
73697         for (; i < length; ++i) {
73698             headerState = headers[i];
73699             header = headerCt.down('gridcolumn[headerId=' + headerState.id + ']');
73700             index = items.indexOf(header);
73701             if (i !== index) {
73702                 headerCt.moveHeader(index, i);
73703             }
73704             header.sortable = headerState.sortable;
73705             if (Ext.isDefined(headerState.width)) {
73706                 delete header.flex;
73707                 if (header.rendered) {
73708                     header.setWidth(headerState.width);
73709                 } else {
73710                     header.minWidth = header.width = headerState.width;
73711                 }
73712             }
73713             header.hidden = headerState.hidden;
73714         }
73715
73716         if (sorter) {
73717             if (store.remoteSort) {
73718                 store.sorters.add(Ext.create('Ext.util.Sorter', {
73719                     property: sorter.property,
73720                     direction: sorter.direction
73721                 }));
73722             }
73723             else {
73724                 store.sort(sorter.property, sorter.direction);
73725             }
73726         }
73727     },
73728
73729     
73730     getStore: function(){
73731         return this.store;
73732     },
73733
73734     
73735     getView: function() {
73736         var me = this,
73737             sm;
73738
73739         if (!me.view) {
73740             sm = me.getSelectionModel();
73741             me.view = me.createComponent(Ext.apply({}, me.viewConfig, {
73742                 xtype: me.viewType,
73743                 store: me.store,
73744                 headerCt: me.headerCt,
73745                 selModel: sm,
73746                 features: me.features,
73747                 panel: me
73748             }));
73749             me.mon(me.view, {
73750                 uievent: me.processEvent,
73751                 scope: me
73752             });
73753             sm.view = me.view;
73754             me.headerCt.view = me.view;
73755             me.relayEvents(me.view, ['cellclick', 'celldblclick']);
73756         }
73757         return me.view;
73758     },
73759
73760     
73761     setAutoScroll: Ext.emptyFn,
73762
73763     
73764     
73765     
73766     elScroll: function(direction, distance, animate) {
73767         var me = this,
73768             scroller;
73769
73770         if (direction === "up" || direction === "left") {
73771             distance = -distance;
73772         }
73773
73774         if (direction === "down" || direction === "up") {
73775             scroller = me.getVerticalScroller();
73776             scroller.scrollByDeltaY(distance);
73777         } else {
73778             scroller = me.getHorizontalScroller();
73779             scroller.scrollByDeltaX(distance);
73780         }
73781     },
73782     
73783     afterLayout: function() {
73784         this.callParent(arguments);
73785         this.injectView();
73786     },
73787     
73788
73789     
73790     injectView: function() {
73791         if (!this.hasView && !this.collapsed) {
73792             var me   = this,
73793                 view = me.getView();
73794
73795             me.hasView = true;
73796             me.add(view);
73797
73798             
73799             view.el.scroll = Ext.Function.bind(me.elScroll, me);
73800             
73801             
73802             me.mon(view.el, {
73803                 mousewheel: me.onMouseWheel,
73804                 scope: me
73805             });
73806         }
73807     },
73808
73809     afterExpand: function() {
73810         this.callParent(arguments);
73811         if (!this.hasView) {
73812             this.injectView();
73813         }
73814     },
73815
73816     
73817     processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
73818         var me = this,
73819             header;
73820
73821         if (cellIndex !== -1) {
73822             header = me.headerCt.getGridColumns()[cellIndex];
73823             return header.processEvent.apply(header, arguments);
73824         }
73825     },
73826
73827     
73828     determineScrollbars: function() {
73829         var me = this,
73830             viewElDom,
73831             centerScrollWidth,
73832             centerClientWidth,
73833             scrollHeight,
73834             clientHeight;
73835
73836         if (!me.collapsed && me.view && me.view.el) {
73837             viewElDom = me.view.el.dom;
73838             
73839             centerScrollWidth = me.headerCt.getFullWidth();
73840             
73841             centerClientWidth = viewElDom.offsetWidth;
73842             if (me.verticalScroller && me.verticalScroller.el) {
73843                 scrollHeight = me.verticalScroller.getSizeCalculation().height;
73844             } else {
73845                 scrollHeight = viewElDom.scrollHeight;
73846             }
73847
73848             clientHeight = viewElDom.clientHeight;
73849
73850             if (!me.collapsed && scrollHeight > clientHeight) {
73851                 me.showVerticalScroller();
73852             } else {
73853                 me.hideVerticalScroller();
73854             }
73855
73856             if (!me.collapsed && centerScrollWidth > (centerClientWidth + Ext.getScrollBarWidth() - 2)) {
73857                 me.showHorizontalScroller();
73858             } else {
73859                 me.hideHorizontalScroller();
73860             }
73861         }
73862     },
73863
73864     onHeaderResize: function() {
73865         if (this.view && this.view.rendered) {
73866             this.determineScrollbars();
73867             this.invalidateScroller();
73868         }
73869     },
73870
73871     
73872     hideHorizontalScroller: function() {
73873         var me = this;
73874
73875         if (me.horizontalScroller && me.horizontalScroller.ownerCt === me) {
73876             me.verticalScroller.offsets.bottom = 0;
73877             me.removeDocked(me.horizontalScroller, false);
73878             me.removeCls(me.horizontalScrollerPresentCls);
73879             me.fireEvent('scrollerhide', me.horizontalScroller, 'horizontal');
73880         }
73881
73882     },
73883
73884     
73885     showHorizontalScroller: function() {
73886         var me = this;
73887
73888         if (me.verticalScroller) {
73889             me.verticalScroller.offsets.bottom = Ext.getScrollBarWidth() - 2;
73890         }
73891         if (me.horizontalScroller && me.horizontalScroller.ownerCt !== me) {
73892             me.addDocked(me.horizontalScroller);
73893             me.addCls(me.horizontalScrollerPresentCls);
73894             me.fireEvent('scrollershow', me.horizontalScroller, 'horizontal');
73895         }
73896     },
73897
73898     
73899     hideVerticalScroller: function() {
73900         var me = this,
73901             headerCt = me.headerCt;
73902
73903         
73904         if (headerCt && headerCt.layout.reserveOffset) {
73905             headerCt.layout.reserveOffset = false;
73906             headerCt.doLayout();
73907         }
73908         if (me.verticalScroller && me.verticalScroller.ownerCt === me) {
73909             me.removeDocked(me.verticalScroller, false);
73910             me.removeCls(me.verticalScrollerPresentCls);
73911             me.fireEvent('scrollerhide', me.verticalScroller, 'vertical');
73912         }
73913     },
73914
73915     
73916     showVerticalScroller: function() {
73917         var me = this,
73918             headerCt = me.headerCt;
73919
73920         
73921         if (headerCt && !headerCt.layout.reserveOffset) {
73922             headerCt.layout.reserveOffset = true;
73923             headerCt.doLayout();
73924         }
73925         if (me.verticalScroller && me.verticalScroller.ownerCt !== me) {
73926             me.addDocked(me.verticalScroller);
73927             me.addCls(me.verticalScrollerPresentCls);
73928             me.fireEvent('scrollershow', me.verticalScroller, 'vertical');
73929         }
73930     },
73931
73932     
73933     invalidateScroller: function() {
73934         var me = this,
73935             vScroll = me.verticalScroller,
73936             hScroll = me.horizontalScroller;
73937
73938         if (vScroll) {
73939             vScroll.invalidate();
73940         }
73941         if (hScroll) {
73942             hScroll.invalidate();
73943         }
73944     },
73945
73946     
73947     onHeaderMove: function(headerCt, header, fromIdx, toIdx) {
73948         this.view.refresh();
73949     },
73950
73951     
73952     onHeaderHide: function(headerCt, header) {
73953         this.invalidateScroller();
73954     },
73955
73956     onHeaderShow: function(headerCt, header) {
73957         this.invalidateScroller();
73958     },
73959
73960     getVerticalScroller: function() {
73961         return this.getScrollerOwner().down('gridscroller[dock=' + this.verticalScrollDock + ']');
73962     },
73963
73964     getHorizontalScroller: function() {
73965         return this.getScrollerOwner().down('gridscroller[dock=bottom]');
73966     },
73967
73968     onMouseWheel: function(e) {
73969         var me = this,
73970             browserEvent = e.browserEvent,
73971             vertScroller = me.getVerticalScroller(),
73972             horizScroller = me.getHorizontalScroller(),
73973             scrollDelta = me.scrollDelta,
73974             deltaY, deltaX,
73975             vertScrollerEl, horizScrollerEl,
73976             origScrollLeft, origScrollTop,
73977             newScrollLeft, newScrollTop;
73978
73979         
73980         
73981         if (horizScroller) {
73982             horizScrollerEl = horizScroller.el;
73983             if (horizScrollerEl) {
73984                 origScrollLeft = horizScrollerEl.dom.scrollLeft;
73985             }
73986         }
73987         if (vertScroller) {
73988             vertScrollerEl = vertScroller.el;
73989             if (vertScrollerEl) {
73990                 origScrollTop = vertScrollerEl.dom.scrollTop;
73991             }
73992         }
73993
73994         
73995         if (browserEvent.wheelDeltaX || browserEvent.wheelDeltaY) {
73996             deltaX = -browserEvent.wheelDeltaX / 120 * scrollDelta / 3;
73997             deltaY = -browserEvent.wheelDeltaY / 120 * scrollDelta / 3;
73998             if (horizScroller) {
73999                 newScrollLeft = horizScroller.scrollByDeltaX(deltaX);
74000             }
74001             if (vertScroller) {
74002                 newScrollTop = vertScroller.scrollByDeltaY(deltaY);
74003             }
74004         } else {
74005             
74006             if (browserEvent.axis && browserEvent.axis === 1) {
74007                 if (horizScroller) {
74008                     deltaX = -(scrollDelta * e.getWheelDelta()) / 3;
74009                     newScrollLeft = horizScroller.scrollByDeltaX(deltaX);
74010                 }
74011             } else {
74012                 if (vertScroller) {
74013
74014                     deltaY = -(scrollDelta * e.getWheelDelta() / 3);
74015                     newScrollTop = vertScroller.scrollByDeltaY(deltaY);
74016                 }
74017             }
74018         }
74019
74020         
74021         
74022         if ((deltaX !== 0 && newScrollLeft !== origScrollLeft) ||
74023             (deltaY !== 0 && newScrollTop !== origScrollTop)) {
74024             e.stopEvent();
74025         }
74026     },
74027
74028     
74029     onViewRefresh: function() {
74030         if (Ext.isIE) {
74031             this.syncCellHeight();
74032         }
74033         this.determineScrollbars();
74034         if (this.invalidateScrollerOnRefresh) {
74035             this.invalidateScroller();
74036         }
74037     },
74038
74039     onViewItemUpdate: function(record, index, tr) {
74040         if (Ext.isIE) {
74041             this.syncCellHeight([tr]);
74042         }
74043     },
74044
74045     
74046     
74047     
74048     syncCellHeight: function(trs) {
74049         var me    = this,
74050             i     = 0,
74051             tds,
74052             j, tdsLn,
74053             tr, td,
74054             trsLn,
74055             rowHeights = [],
74056             cellHeights,
74057             cellClsSelector = ('.' + Ext.baseCSSPrefix + 'grid-cell');
74058
74059         trs   = trs || me.view.getNodes();
74060         
74061         trsLn = trs.length;
74062         
74063         for (; i < trsLn; i++) {
74064             tr = trs[i];
74065             tds = Ext.fly(tr).query(cellClsSelector);
74066             tdsLn = tds.length;
74067             cellHeights = [];
74068             for (j = 0; j < tdsLn; j++) {
74069                 td = tds[j];
74070                 cellHeights.push(td.clientHeight);
74071             }
74072             rowHeights.push(Ext.Array.max(cellHeights));
74073         }
74074
74075         
74076         for (i = 0; i < trsLn; i++) {
74077             tr = trs[i];
74078             tdsLn = tr.childNodes.length;
74079             for (j = 0; j < tdsLn; j++) {
74080                 td = Ext.fly(tr.childNodes[j]);
74081                 if (rowHeights[i]) {
74082                     if (td.is(cellClsSelector)) {
74083                         td.setHeight(rowHeights[i]);
74084                     } else {
74085                         td.down(cellClsSelector).setHeight(rowHeights[i]);
74086                     }
74087                 }
74088                 
74089             }
74090         }
74091     },
74092
74093     
74094     setScrollTop: function(top) {
74095         var me               = this,
74096             rootCmp          = me.getScrollerOwner(),
74097             verticalScroller = me.getVerticalScroller();
74098
74099         rootCmp.virtualScrollTop = top;
74100         if (verticalScroller) {
74101             verticalScroller.setScrollTop(top);
74102         }
74103
74104     },
74105
74106     getScrollerOwner: function() {
74107         var rootCmp = this;
74108         if (!this.scrollerOwner) {
74109             rootCmp = this.up('[scrollerOwner]');
74110         }
74111         return rootCmp;
74112     },
74113
74114     
74115     scrollByDeltaY: function(deltaY) {
74116         var rootCmp = this.getScrollerOwner(),
74117             scrollerRight;
74118         scrollerRight = rootCmp.down('gridscroller[dock=' + this.verticalScrollDock + ']');
74119         if (scrollerRight) {
74120             scrollerRight.scrollByDeltaY(deltaY);
74121         }
74122     },
74123
74124
74125     
74126     scrollByDeltaX: function(deltaX) {
74127         this.horizontalScroller.scrollByDeltaX(deltaX);
74128     },
74129
74130     
74131     getLhsMarker: function() {
74132         var me = this;
74133
74134         if (!me.lhsMarker) {
74135             me.lhsMarker = Ext.core.DomHelper.append(me.el, {
74136                 cls: Ext.baseCSSPrefix + 'grid-resize-marker'
74137             }, true);
74138         }
74139         return me.lhsMarker;
74140     },
74141
74142     
74143     getRhsMarker: function() {
74144         var me = this;
74145
74146         if (!me.rhsMarker) {
74147             me.rhsMarker = Ext.core.DomHelper.append(me.el, {
74148                 cls: Ext.baseCSSPrefix + 'grid-resize-marker'
74149             }, true);
74150         }
74151         return me.rhsMarker;
74152     },
74153
74154     
74155     getSelectionModel: function(){
74156         if (!this.selModel) {
74157             this.selModel = {};
74158         }
74159
74160         var mode = 'SINGLE',
74161             type;
74162         if (this.simpleSelect) {
74163             mode = 'SIMPLE';
74164         } else if (this.multiSelect) {
74165             mode = 'MULTI';
74166         }
74167
74168         Ext.applyIf(this.selModel, {
74169             allowDeselect: this.allowDeselect,
74170             mode: mode
74171         });
74172
74173         if (!this.selModel.events) {
74174             type = this.selModel.selType || this.selType;
74175             this.selModel = Ext.create('selection.' + type, this.selModel);
74176         }
74177
74178         if (!this.selModel.hasRelaySetup) {
74179             this.relayEvents(this.selModel, ['selectionchange', 'select', 'deselect']);
74180             this.selModel.hasRelaySetup = true;
74181         }
74182
74183         
74184         
74185         if (this.disableSelection) {
74186             this.selModel.locked = true;
74187         }
74188         return this.selModel;
74189     },
74190
74191     onVerticalScroll: function(event, target) {
74192         var owner = this.getScrollerOwner(),
74193             items = owner.query('tableview'),
74194             i = 0,
74195             len = items.length;
74196
74197         for (; i < len; i++) {
74198             items[i].el.dom.scrollTop = target.scrollTop;
74199         }
74200     },
74201
74202     onHorizontalScroll: function(event, target) {
74203         var owner = this.getScrollerOwner(),
74204             items = owner.query('tableview'),
74205             i = 0,
74206             len = items.length,
74207             center,
74208             centerEl,
74209             centerScrollWidth,
74210             centerClientWidth,
74211             width;
74212
74213         center = items[1] || items[0];
74214         centerEl = center.el.dom;
74215         centerScrollWidth = centerEl.scrollWidth;
74216         centerClientWidth = centerEl.offsetWidth;
74217         width = this.horizontalScroller.getWidth();
74218
74219         centerEl.scrollLeft = target.scrollLeft;
74220         this.headerCt.el.dom.scrollLeft = target.scrollLeft;
74221     },
74222
74223     
74224     onStoreLoad: Ext.emptyFn,
74225
74226     getEditorParent: function() {
74227         return this.body;
74228     },
74229
74230     bindStore: function(store) {
74231         var me = this;
74232         me.store = store;
74233         me.getView().bindStore(store);
74234     },
74235
74236     reconfigure: function(store, columns) {
74237         var me = this;
74238
74239         if (me.lockable) {
74240             me.reconfigureLockable(store, columns);
74241             return;
74242         }
74243
74244         if (columns) {
74245             me.headerCt.removeAll();
74246             me.headerCt.add(columns);
74247         }
74248         if (store) {
74249             store = Ext.StoreManager.lookup(store);
74250             me.bindStore(store);
74251         } else {
74252             me.getView().refresh();
74253         }
74254     },
74255
74256     afterComponentLayout: function() {
74257         this.callParent(arguments);
74258         this.determineScrollbars();
74259         this.invalidateScroller();
74260     }
74261 });
74262
74263 Ext.define('Ext.view.Table', {
74264     extend: 'Ext.view.View',
74265     alias: 'widget.tableview',
74266     uses: [
74267         'Ext.view.TableChunker',
74268         'Ext.util.DelayedTask',
74269         'Ext.util.MixedCollection'
74270     ],
74271
74272     cls: Ext.baseCSSPrefix + 'grid-view',
74273
74274     
74275     itemSelector: '.' + Ext.baseCSSPrefix + 'grid-row',
74276     
74277     cellSelector: '.' + Ext.baseCSSPrefix + 'grid-cell',
74278
74279     selectedItemCls: Ext.baseCSSPrefix + 'grid-row-selected',
74280     selectedCellCls: Ext.baseCSSPrefix + 'grid-cell-selected',
74281     focusedItemCls: Ext.baseCSSPrefix + 'grid-row-focused',
74282     overItemCls: Ext.baseCSSPrefix + 'grid-row-over',
74283     altRowCls:   Ext.baseCSSPrefix + 'grid-row-alt',
74284     rowClsRe: /(?:^|\s*)grid-row-(first|last|alt)(?:\s+|$)/g,
74285     cellRe: new RegExp('x-grid-cell-([^\\s]+) ', ''),
74286
74287     
74288     trackOver: true,
74289
74290     
74291     getRowClass: null,
74292
74293     initComponent: function() {
74294         this.scrollState = {};
74295         this.selModel.view = this;
74296         this.headerCt.view = this;
74297         this.initFeatures();
74298         this.setNewTemplate();
74299         this.callParent();
74300         this.mon(this.store, {
74301             load: this.onStoreLoad,
74302             scope: this
74303         });
74304
74305         
74306         
74307         
74308         
74309         
74310         
74311         
74312         
74313         
74314     },
74315
74316     
74317     onStoreLoad: function(){
74318         if (this.invalidateScrollerOnRefresh) {
74319             if (Ext.isGecko) {
74320                 if (!this.scrollToTopTask) {
74321                     this.scrollToTopTask = Ext.create('Ext.util.DelayedTask', this.scrollToTop, this);
74322                 }
74323                 this.scrollToTopTask.delay(1);
74324             } else {
74325                 this.scrollToTop();
74326             }
74327         }
74328     },
74329
74330     
74331     scrollToTop: Ext.emptyFn,
74332     
74333     
74334     getGridColumns: function() {
74335         return this.headerCt.getGridColumns();    
74336     },
74337     
74338     
74339     getHeaderAtIndex: function(index) {
74340         return this.headerCt.getHeaderAtIndex(index);
74341     },
74342     
74343     
74344     getCell: function(record, column) {
74345         var row = this.getNode(record);
74346         return Ext.fly(row).down(column.getCellSelector());
74347     },
74348
74349     
74350     getFeature: function(id) {
74351         var features = this.featuresMC;
74352         if (features) {
74353             return features.get(id);
74354         }
74355     },
74356
74357     
74358     initFeatures: function() {
74359         this.features = this.features || [];
74360         var features = this.features,
74361             ln       = features.length,
74362             i        = 0;
74363
74364         this.featuresMC = Ext.create('Ext.util.MixedCollection');
74365         for (; i < ln; i++) {
74366             
74367             if (!features[i].isFeature) {
74368                 features[i] = Ext.create('feature.'+features[i].ftype, features[i]);
74369             }
74370             
74371             features[i].view = this;
74372             this.featuresMC.add(features[i]);
74373         }
74374     },
74375
74376     
74377     attachEventsForFeatures: function() {
74378         var features = this.features,
74379             ln       = features.length,
74380             i        = 0;
74381
74382         for (; i < ln; i++) {
74383             if (features[i].isFeature) {
74384                 features[i].attachEvents();
74385             }
74386         }
74387     },
74388
74389     afterRender: function() {
74390         this.callParent();
74391         this.mon(this.el, {
74392             scroll: this.fireBodyScroll,
74393             scope: this
74394         });
74395         this.attachEventsForFeatures();
74396     },
74397
74398     fireBodyScroll: function(e, t) {
74399         this.fireEvent('bodyscroll', e, t);
74400     },
74401
74402     
74403     
74404     prepareData: function(data, idx, record) {
74405         var orig     = this.headerCt.prepareData(data, idx, record, this),
74406             features = this.features,
74407             ln       = features.length,
74408             i        = 0,
74409             node, feature;
74410
74411         for (; i < ln; i++) {
74412             feature = features[i];
74413             if (feature.isFeature) {
74414                 Ext.apply(orig, feature.getAdditionalData(data, idx, record, orig, this));
74415             }
74416         }
74417
74418         return orig;
74419     },
74420
74421     
74422     collectData: function(records, startIndex) {
74423         var preppedRecords = this.callParent(arguments),
74424             headerCt  = this.headerCt,
74425             fullWidth = headerCt.getFullWidth(),
74426             features  = this.features,
74427             ln = features.length,
74428             o = {
74429                 rows: preppedRecords,
74430                 fullWidth: fullWidth
74431             },
74432             i  = 0,
74433             feature,
74434             j = 0,
74435             jln,
74436             rowParams;
74437
74438         jln = preppedRecords.length;
74439         
74440         
74441         if (this.getRowClass) {
74442             for (; j < jln; j++) {
74443                 rowParams = {};
74444                 preppedRecords[j]['rowCls'] = this.getRowClass(records[j], j, rowParams, this.store);
74445                 if (rowParams.alt) {
74446                     Ext.Error.raise("The getRowClass alt property is no longer supported.");
74447                 }
74448                 if (rowParams.tstyle) {
74449                     Ext.Error.raise("The getRowClass tstyle property is no longer supported.");
74450                 }
74451                 if (rowParams.cells) {
74452                     Ext.Error.raise("The getRowClass cells property is no longer supported.");
74453                 }
74454                 if (rowParams.body) {
74455                     Ext.Error.raise("The getRowClass body property is no longer supported. Use the getAdditionalData method of the rowbody feature.");
74456                 }
74457                 if (rowParams.bodyStyle) {
74458                     Ext.Error.raise("The getRowClass bodyStyle property is no longer supported.");
74459                 }
74460                 if (rowParams.cols) {
74461                     Ext.Error.raise("The getRowClass cols property is no longer supported.");
74462                 }
74463             }
74464         }
74465         
74466         
74467         for (; i < ln; i++) {
74468             feature = features[i];
74469             if (feature.isFeature && feature.collectData && !feature.disabled) {
74470                 o = feature.collectData(records, preppedRecords, startIndex, fullWidth, o);
74471                 break;
74472             }
74473         }
74474         return o;
74475     },
74476
74477     
74478     
74479     onHeaderResize: function(header, w, suppressFocus) {
74480         var el = this.el;
74481         if (el) {
74482             this.saveScrollState();
74483             
74484             
74485             
74486             el.select('.' + Ext.baseCSSPrefix + 'grid-col-resizer-'+header.id).setWidth(w);
74487             el.select('.' + Ext.baseCSSPrefix + 'grid-table-resizer').setWidth(this.headerCt.getFullWidth());
74488             this.restoreScrollState();
74489             this.setNewTemplate();
74490             if (!suppressFocus) {
74491                 this.el.focus();
74492             }
74493         }
74494     },
74495
74496     
74497     onHeaderShow: function(headerCt, header, suppressFocus) {
74498         
74499         if (header.oldWidth) {
74500             this.onHeaderResize(header, header.oldWidth, suppressFocus);
74501             delete header.oldWidth;
74502         
74503         
74504         
74505         } else if (header.width && !header.flex) {
74506             this.onHeaderResize(header, header.width, suppressFocus);
74507         }
74508         this.setNewTemplate();
74509     },
74510
74511     
74512     onHeaderHide: function(headerCt, header, suppressFocus) {
74513         this.onHeaderResize(header, 0, suppressFocus);
74514     },
74515
74516     
74517     setNewTemplate: function() {
74518         var columns = this.headerCt.getColumnsForTpl(true);
74519         this.tpl = this.getTableChunker().getTableTpl({
74520             columns: columns,
74521             features: this.features
74522         });
74523     },
74524
74525     
74526     getTableChunker: function() {
74527         return this.chunker || Ext.view.TableChunker;
74528     },
74529
74530     
74531     addRowCls: function(rowInfo, cls) {
74532         var row = this.getNode(rowInfo);
74533         if (row) {
74534             Ext.fly(row).addCls(cls);
74535         }
74536     },
74537
74538     
74539     removeRowCls: function(rowInfo, cls) {
74540         var row = this.getNode(rowInfo);
74541         if (row) {
74542             Ext.fly(row).removeCls(cls);
74543         }
74544     },
74545
74546     
74547     onRowSelect : function(rowIdx) {
74548         this.addRowCls(rowIdx, this.selectedItemCls);
74549     },
74550
74551     
74552     onRowDeselect : function(rowIdx) {
74553         this.removeRowCls(rowIdx, this.selectedItemCls);
74554         this.removeRowCls(rowIdx, this.focusedItemCls);
74555     },
74556     
74557     onCellSelect: function(position) {
74558         var cell = this.getCellByPosition(position);
74559         if (cell) {
74560             cell.addCls(this.selectedCellCls);
74561         }
74562     },
74563     
74564     onCellDeselect: function(position) {
74565         var cell = this.getCellByPosition(position);
74566         if (cell) {
74567             cell.removeCls(this.selectedCellCls);
74568         }
74569         
74570     },
74571     
74572     onCellFocus: function(position) {
74573         
74574         this.focusCell(position);
74575     },
74576     
74577     getCellByPosition: function(position) {
74578         var row    = position.row,
74579             column = position.column,
74580             store  = this.store,
74581             node   = this.getNode(row),
74582             header = this.headerCt.getHeaderAtIndex(column),
74583             cellSelector,
74584             cell = false;
74585             
74586         if (header) {
74587             cellSelector = header.getCellSelector();
74588             cell = Ext.fly(node).down(cellSelector);
74589         }
74590         return cell;
74591     },
74592
74593     
74594     
74595     onRowFocus: function(rowIdx, highlight, supressFocus) {
74596         var row = this.getNode(rowIdx);
74597
74598         if (highlight) {
74599             this.addRowCls(rowIdx, this.focusedItemCls);
74600             if (!supressFocus) {
74601                 this.focusRow(rowIdx);
74602             }
74603             
74604         } else {
74605             this.removeRowCls(rowIdx, this.focusedItemCls);
74606         }
74607     },
74608
74609     
74610     focusRow: function(rowIdx) {
74611         var row        = this.getNode(rowIdx),
74612             el         = this.el,
74613             adjustment = 0,
74614             panel      = this.ownerCt,
74615             rowRegion,
74616             elRegion,
74617             record;
74618             
74619         if (row && this.el) {
74620             elRegion  = el.getRegion();
74621             rowRegion = Ext.fly(row).getRegion();
74622             
74623             if (rowRegion.top < elRegion.top) {
74624                 adjustment = rowRegion.top - elRegion.top;
74625             
74626             } else if (rowRegion.bottom > elRegion.bottom) {
74627                 adjustment = rowRegion.bottom - elRegion.bottom;
74628             }
74629             record = this.getRecord(row);
74630             rowIdx = this.store.indexOf(record);
74631
74632             if (adjustment) {
74633                 
74634                 panel.scrollByDeltaY(adjustment);
74635             }
74636             this.fireEvent('rowfocus', record, row, rowIdx);
74637         }
74638     },
74639
74640     focusCell: function(position) {
74641         var cell        = this.getCellByPosition(position),
74642             el          = this.el,
74643             adjustmentY = 0,
74644             adjustmentX = 0,
74645             elRegion    = el.getRegion(),
74646             panel       = this.ownerCt,
74647             cellRegion,
74648             record;
74649
74650         if (cell) {
74651             cellRegion = cell.getRegion();
74652             
74653             if (cellRegion.top < elRegion.top) {
74654                 adjustmentY = cellRegion.top - elRegion.top;
74655             
74656             } else if (cellRegion.bottom > elRegion.bottom) {
74657                 adjustmentY = cellRegion.bottom - elRegion.bottom;
74658             }
74659
74660             
74661             if (cellRegion.left < elRegion.left) {
74662                 adjustmentX = cellRegion.left - elRegion.left;
74663             
74664             } else if (cellRegion.right > elRegion.right) {
74665                 adjustmentX = cellRegion.right - elRegion.right;
74666             }
74667
74668             if (adjustmentY) {
74669                 
74670                 panel.scrollByDeltaY(adjustmentY);
74671             }
74672             if (adjustmentX) {
74673                 panel.scrollByDeltaX(adjustmentX);
74674             }
74675             el.focus();
74676             this.fireEvent('cellfocus', record, cell, position);
74677         }
74678     },
74679
74680     
74681     scrollByDelta: function(delta, dir) {
74682         dir = dir || 'scrollTop';
74683         var elDom = this.el.dom;
74684         elDom[dir] = (elDom[dir] += delta);
74685     },
74686
74687     onUpdate: function(ds, index) {
74688         this.callParent(arguments);
74689     },
74690
74691     
74692     saveScrollState: function() {
74693         var dom = this.el.dom,
74694             state = this.scrollState;
74695
74696         state.left = dom.scrollLeft;
74697         state.top = dom.scrollTop;
74698     },
74699
74700     
74701     restoreScrollState: function() {
74702         var dom = this.el.dom,
74703             state = this.scrollState,
74704             headerEl = this.headerCt.el.dom;
74705
74706         headerEl.scrollLeft = dom.scrollLeft = state.left;
74707         dom.scrollTop = state.top;
74708     },
74709
74710     
74711     refresh: function(firstPass) {
74712         var me = this,
74713             table;
74714
74715         
74716         me.setNewTemplate();
74717         
74718         
74719         
74720         
74721         if (me.rendered) {
74722             table = me.el.child('table');
74723             if (table) {
74724                 table.removeAllListeners();
74725             }
74726         }
74727         
74728         me.callParent(arguments);
74729
74730         
74731         if (me.rendered) {
74732             
74733             table = me.el.child('table');
74734             if (table) {
74735                 table.unselectable();
74736             }
74737             
74738             if (!firstPass) {
74739                 
74740                 me.el.focus();
74741             }
74742         }
74743     },
74744
74745     processItemEvent: function(type, record, row, rowIndex, e) {
74746         var me = this,
74747             cell = e.getTarget(me.cellSelector, row),
74748             cellIndex = cell ? cell.cellIndex : -1,
74749             map = me.statics().EventMap,
74750             selModel = me.getSelectionModel(),
74751             result;
74752
74753         if (type == 'keydown' && !cell && selModel.getCurrentPosition) {
74754             
74755             cell = me.getCellByPosition(selModel.getCurrentPosition());
74756             if (cell) {
74757                 cell = cell.dom;
74758                 cellIndex = cell.cellIndex;
74759             }
74760         }
74761
74762         result = me.fireEvent('uievent', type, me, cell, rowIndex, cellIndex, e);
74763
74764         if (result === false || me.callParent(arguments) === false) {
74765             return false;
74766         }
74767
74768         
74769         if (type == 'mouseover' || type == 'mouseout') {
74770             return true;
74771         }
74772
74773         return !(
74774             
74775             (me['onBeforeCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
74776             (me.fireEvent('beforecell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false) ||
74777             (me['onCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
74778             (me.fireEvent('cell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false)
74779         );
74780     },
74781
74782     processSpecialEvent: function(e) {
74783         var me = this,
74784             map = this.statics().EventMap,
74785             features = this.features,
74786             ln = features.length,
74787             type = e.type,
74788             i, feature, prefix, featureTarget,
74789             beforeArgs, args,
74790             panel = me.ownerCt;
74791
74792         this.callParent(arguments);
74793
74794         if (type == 'mouseover' || type == 'mouseout') {
74795             return;
74796         }
74797
74798         for (i = 0; i < ln; i++) {
74799             feature = features[i];
74800             if (feature.hasFeatureEvent) {
74801                 featureTarget = e.getTarget(feature.eventSelector, me.getTargetEl());
74802                 if (featureTarget) {
74803                     prefix = feature.eventPrefix;
74804                     
74805                     
74806                     beforeArgs = feature.getFireEventArgs('before' + prefix + type, me, featureTarget);
74807                     args = feature.getFireEventArgs(prefix + type, me, featureTarget);
74808                     
74809                     if (
74810                         
74811                         (me.fireEvent.apply(me, beforeArgs) === false) ||
74812                         
74813                         (panel.fireEvent.apply(panel, beforeArgs) === false) ||
74814                         
74815                         (me.fireEvent.apply(me, args) === false) ||
74816                         
74817                         (panel.fireEvent.apply(panel, args) === false)
74818                     ) {
74819                         return false;
74820                     }
74821                 }
74822             }
74823         }
74824         return true;
74825     },
74826
74827     onCellMouseDown: Ext.emptyFn,
74828     onCellMouseUp: Ext.emptyFn,
74829     onCellClick: Ext.emptyFn,
74830     onCellDblClick: Ext.emptyFn,
74831     onCellContextMenu: Ext.emptyFn,
74832     onCellKeyDown: Ext.emptyFn,
74833     onBeforeCellMouseDown: Ext.emptyFn,
74834     onBeforeCellMouseUp: Ext.emptyFn,
74835     onBeforeCellClick: Ext.emptyFn,
74836     onBeforeCellDblClick: Ext.emptyFn,
74837     onBeforeCellContextMenu: Ext.emptyFn,
74838     onBeforeCellKeyDown: Ext.emptyFn,
74839
74840     
74841     expandToFit: function(header) {
74842         var maxWidth = this.getMaxContentWidth(header);
74843         delete header.flex;
74844         header.setWidth(maxWidth);
74845     },
74846
74847     
74848     getMaxContentWidth: function(header) {
74849         var cellSelector = header.getCellInnerSelector(),
74850             cells        = this.el.query(cellSelector),
74851             i = 0,
74852             ln = cells.length,
74853             maxWidth = header.el.dom.scrollWidth,
74854             scrollWidth;
74855
74856         for (; i < ln; i++) {
74857             scrollWidth = cells[i].scrollWidth;
74858             if (scrollWidth > maxWidth) {
74859                 maxWidth = scrollWidth;
74860             }
74861         }
74862         return maxWidth;
74863     },
74864
74865     getPositionByEvent: function(e) {
74866         var cellNode = e.getTarget(this.cellSelector),
74867             rowNode  = e.getTarget(this.itemSelector),
74868             record   = this.getRecord(rowNode),
74869             header   = this.getHeaderByCell(cellNode);
74870
74871         return this.getPosition(record, header);
74872     },
74873
74874     getHeaderByCell: function(cell) {
74875         if (cell) {
74876             var m = cell.className.match(this.cellRe);
74877             if (m && m[1]) {
74878                 return Ext.getCmp(m[1]);
74879             }
74880         }
74881         return false;
74882     },
74883
74884     
74885     walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
74886         var row      = pos.row,
74887             column   = pos.column,
74888             rowCount = this.store.getCount(),
74889             firstCol = this.getFirstVisibleColumnIndex(),
74890             lastCol  = this.getLastVisibleColumnIndex(),
74891             newPos   = {row: row, column: column},
74892             activeHeader = this.headerCt.getHeaderAtIndex(column);
74893
74894         
74895         if (!activeHeader || activeHeader.hidden) {
74896             return false;
74897         }
74898
74899         e = e || {};
74900         direction = direction.toLowerCase();
74901         switch (direction) {
74902             case 'right':
74903                 
74904                 if (column === lastCol) {
74905                     
74906                     if (preventWrap || row === rowCount - 1) {
74907                         return false;
74908                     }
74909                     if (!e.ctrlKey) {
74910                         
74911                         newPos.row = row + 1;
74912                         newPos.column = firstCol;
74913                     }
74914                 
74915                 } else {
74916                     if (!e.ctrlKey) {
74917                         newPos.column = column + this.getRightGap(activeHeader);
74918                     } else {
74919                         newPos.column = lastCol;
74920                     }
74921                 }
74922                 break;
74923
74924             case 'left':
74925                 
74926                 if (column === firstCol) {
74927                     
74928                     if (preventWrap || row === 0) {
74929                         return false;
74930                     }
74931                     if (!e.ctrlKey) {
74932                         
74933                         newPos.row = row - 1;
74934                         newPos.column = lastCol;
74935                     }
74936                 
74937                 } else {
74938                     if (!e.ctrlKey) {
74939                         newPos.column = column + this.getLeftGap(activeHeader);
74940                     } else {
74941                         newPos.column = firstCol;
74942                     }
74943                 }
74944                 break;
74945
74946             case 'up':
74947                 
74948                 if (row === 0) {
74949                     return false;
74950                 
74951                 } else {
74952                     if (!e.ctrlKey) {
74953                         newPos.row = row - 1;
74954                     } else {
74955                         newPos.row = 0;
74956                     }
74957                 }
74958                 break;
74959
74960             case 'down':
74961                 
74962                 if (row === rowCount - 1) {
74963                     return false;
74964                 
74965                 } else {
74966                     if (!e.ctrlKey) {
74967                         newPos.row = row + 1;
74968                     } else {
74969                         newPos.row = rowCount - 1;
74970                     }
74971                 }
74972                 break;
74973         }
74974
74975         if (verifierFn && verifierFn.call(scope || window, newPos) !== true) {
74976             return false;
74977         } else {
74978             return newPos;
74979         }
74980     },
74981     getFirstVisibleColumnIndex: function() {
74982         var headerCt   = this.getHeaderCt(),
74983             allColumns = headerCt.getGridColumns(),
74984             visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
74985             firstHeader = visHeaders[0];
74986
74987         return headerCt.getHeaderIndex(firstHeader);
74988     },
74989
74990     getLastVisibleColumnIndex: function() {
74991         var headerCt   = this.getHeaderCt(),
74992             allColumns = headerCt.getGridColumns(),
74993             visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
74994             lastHeader = visHeaders[visHeaders.length - 1];
74995
74996         return headerCt.getHeaderIndex(lastHeader);
74997     },
74998
74999     getHeaderCt: function() {
75000         return this.headerCt;
75001     },
75002
75003     getPosition: function(record, header) {
75004         var me = this,
75005             store = me.store,
75006             gridCols = me.headerCt.getGridColumns();
75007
75008         return {
75009             row: store.indexOf(record),
75010             column: Ext.Array.indexOf(gridCols, header)
75011         };
75012     },
75013
75014     
75015     getRightGap: function(activeHeader) {
75016         var headerCt        = this.getHeaderCt(),
75017             headers         = headerCt.getGridColumns(),
75018             activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
75019             i               = activeHeaderIdx + 1,
75020             nextIdx;
75021
75022         for (; i <= headers.length; i++) {
75023             if (!headers[i].hidden) {
75024                 nextIdx = i;
75025                 break;
75026             }
75027         }
75028
75029         return nextIdx - activeHeaderIdx;
75030     },
75031
75032     beforeDestroy: function() {
75033         if (this.rendered) {
75034             table = this.el.child('table');
75035             if (table) {
75036                 table.removeAllListeners();
75037             }
75038         }
75039         this.callParent(arguments);
75040     },
75041
75042     
75043     getLeftGap: function(activeHeader) {
75044         var headerCt        = this.getHeaderCt(),
75045             headers         = headerCt.getGridColumns(),
75046             activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
75047             i               = activeHeaderIdx - 1,
75048             prevIdx;
75049
75050         for (; i >= 0; i--) {
75051             if (!headers[i].hidden) {
75052                 prevIdx = i;
75053                 break;
75054             }
75055         }
75056
75057         return prevIdx - activeHeaderIdx;
75058     }
75059 });
75060
75061 Ext.define('Ext.grid.View', {
75062     extend: 'Ext.view.Table',
75063     alias: 'widget.gridview',
75064
75065     
75066     stripeRows: true,
75067     
75068     invalidateScrollerOnRefresh: true,
75069     
75070     
75071     scrollToTop : function(){
75072         if (this.rendered) {
75073             var section = this.ownerCt,
75074                 verticalScroller = section.verticalScroller;
75075                 
75076             if (verticalScroller) {
75077                 verticalScroller.scrollToTop();
75078             }
75079         }
75080     },
75081
75082     
75083     onAdd: function(ds, records, index) {
75084         this.callParent(arguments);
75085         this.doStripeRows(index);
75086     },
75087     
75088     
75089     onRemove: function(ds, records, index) {
75090         this.callParent(arguments);
75091         this.doStripeRows(index);
75092     },
75093     
75094     
75095     doStripeRows: function(startRow) {
75096         
75097         if (this.stripeRows) {
75098             var rows   = this.getNodes(startRow),
75099                 rowsLn = rows.length,
75100                 i      = 0,
75101                 row;
75102                 
75103             for (; i < rowsLn; i++) {
75104                 row = rows[i];
75105                 
75106                 row.className = row.className.replace(this.rowClsRe, ' ');
75107                 
75108                 if (i % 2 === 1) {
75109                     row.className += (' ' + this.altRowCls);
75110                 }
75111             }
75112         }
75113     },
75114     
75115     refresh: function(firstPass) {
75116         this.callParent(arguments);
75117         this.doStripeRows(0);
75118         
75119         var g = this.up('gridpanel');
75120         if (g && this.invalidateScrollerOnRefresh) {
75121             g.invalidateScroller();
75122         }
75123     }
75124 });
75125
75126
75127 Ext.define('Ext.grid.Panel', {
75128     extend: 'Ext.panel.Table',
75129     requires: ['Ext.grid.View'],
75130     alias: ['widget.gridpanel', 'widget.grid'],
75131     alternateClassName: ['Ext.list.ListView', 'Ext.ListView', 'Ext.grid.GridPanel'],
75132     viewType: 'gridview',
75133     
75134     lockable: false,
75135     
75136     
75137     
75138     normalCfgCopy: ['invalidateScrollerOnRefresh', 'verticalScroller', 'verticalScrollDock', 'verticalScrollerType', 'scroll'],
75139     lockedCfgCopy: ['invalidateScrollerOnRefresh'],
75140     
75141     
75142     
75143     initComponent: function() {
75144         var me = this;
75145
75146         if (me.columnLines) {
75147             me.setColumnLines(me.columnLines);
75148         }
75149         
75150         me.callParent();
75151     },
75152     
75153     setColumnLines: function(show) {
75154         var me = this,
75155             method = (show) ? 'addClsWithUI' : 'removeClsWithUI';
75156         
75157         me[method]('with-col-lines')
75158     }
75159 });
75160
75161
75162
75163
75164
75165
75166
75167
75168
75169 Ext.define('Ext.grid.RowEditor', {
75170     extend: 'Ext.form.Panel',
75171     requires: [
75172         'Ext.tip.ToolTip',
75173         'Ext.util.HashMap',
75174         'Ext.util.KeyNav'
75175     ],
75176
75177     saveBtnText  : 'Update',
75178     cancelBtnText: 'Cancel',
75179     errorsText: 'Errors',
75180     dirtyText: 'You need to commit or cancel your changes',
75181
75182     lastScrollLeft: 0,
75183     lastScrollTop: 0,
75184
75185     border: false,
75186
75187     initComponent: function() {
75188         var me = this,
75189             form;
75190
75191         me.cls = Ext.baseCSSPrefix + 'grid-row-editor';
75192
75193         me.layout = {
75194             type: 'hbox',
75195             align: 'middle'
75196         };
75197
75198         
75199         
75200         me.columns = Ext.create('Ext.util.HashMap');
75201         me.columns.getKey = function(columnHeader) {
75202             var f;
75203             if (columnHeader.getEditor) {
75204                 f = columnHeader.getEditor();
75205                 if (f) {
75206                     return f.id;
75207                 }
75208             }
75209             return columnHeader.id;
75210         };
75211         me.mon(me.columns, {
75212             add: me.onFieldAdd,
75213             remove: me.onFieldRemove,
75214             replace: me.onFieldReplace,
75215             scope: me
75216         });
75217
75218         me.callParent(arguments);
75219
75220         if (me.fields) {
75221             me.setField(me.fields);
75222             delete me.fields;
75223         }
75224
75225         form = me.getForm();
75226         form.trackResetOnLoad = true;
75227     },
75228
75229     onFieldChange: function() {
75230         var me = this,
75231             form = me.getForm(),
75232             valid = form.isValid();
75233         if (me.errorSummary && me.isVisible()) {
75234             me[valid ? 'hideToolTip' : 'showToolTip']();
75235         }
75236         if (me.floatingButtons) {
75237             me.floatingButtons.child('#update').setDisabled(!valid);
75238         }
75239         me.isValid = valid;
75240     },
75241
75242     afterRender: function() {
75243         var me = this,
75244             plugin = me.editingPlugin;
75245
75246         me.callParent(arguments);
75247         me.mon(me.renderTo, 'scroll', me.onCtScroll, me, { buffer: 100 });
75248
75249         
75250         me.mon(me.el, {
75251             click: Ext.emptyFn,
75252             stopPropagation: true
75253         });
75254
75255         me.el.swallowEvent([
75256             'keypress',
75257             'keydown'
75258         ]);
75259
75260         me.keyNav = Ext.create('Ext.util.KeyNav', me.el, {
75261             enter: plugin.completeEdit,
75262             esc: plugin.onEscKey,
75263             scope: plugin
75264         });
75265
75266         me.mon(plugin.view, {
75267             beforerefresh: me.onBeforeViewRefresh,
75268             refresh: me.onViewRefresh,
75269             scope: me
75270         });
75271     },
75272
75273     onBeforeViewRefresh: function(view) {
75274         var me = this,
75275             viewDom = view.el.dom;
75276
75277         if (me.el.dom.parentNode === viewDom) {
75278             viewDom.removeChild(me.el.dom);
75279         }
75280     },
75281
75282     onViewRefresh: function(view) {
75283         var me = this,
75284             viewDom = view.el.dom,
75285             context = me.context,
75286             idx;
75287
75288         viewDom.appendChild(me.el.dom);
75289
75290         
75291         if (context && (idx = context.store.indexOf(context.record)) >= 0) {
75292             context.row = view.getNode(idx);
75293             me.reposition();
75294             if (me.tooltip && me.tooltip.isVisible()) {
75295                 me.tooltip.setTarget(context.row);
75296             }
75297         } else {
75298             me.editingPlugin.cancelEdit();
75299         }
75300     },
75301
75302     onCtScroll: function(e, target) {
75303         var me = this,
75304             scrollTop  = target.scrollTop,
75305             scrollLeft = target.scrollLeft;
75306
75307         if (scrollTop !== me.lastScrollTop) {
75308             me.lastScrollTop = scrollTop;
75309             if ((me.tooltip && me.tooltip.isVisible()) || me.hiddenTip) {
75310                 me.repositionTip();
75311             }
75312         }
75313         if (scrollLeft !== me.lastScrollLeft) {
75314             me.lastScrollLeft = scrollLeft;
75315             me.reposition();
75316         }
75317     },
75318
75319     onColumnAdd: function(column) {
75320         this.setField(column);
75321     },
75322
75323     onColumnRemove: function(column) {
75324         this.columns.remove(column);
75325     },
75326
75327     onColumnResize: function(column, width) {
75328         column.getEditor().setWidth(width - 2);
75329         if (this.isVisible()) {
75330             this.reposition();
75331         }
75332     },
75333
75334     onColumnHide: function(column) {
75335         column.getEditor().hide();
75336         if (this.isVisible()) {
75337             this.reposition();
75338         }
75339     },
75340
75341     onColumnShow: function(column) {
75342         var field = column.getEditor();
75343         field.setWidth(column.getWidth() - 2).show();
75344         if (this.isVisible()) {
75345             this.reposition();
75346         }
75347     },
75348
75349     onColumnMove: function(column, fromIdx, toIdx) {
75350         var field = column.getEditor();
75351         if (this.items.indexOf(field) != toIdx) {
75352             this.move(fromIdx, toIdx);
75353         }
75354     },
75355
75356     onFieldAdd: function(hm, fieldId, column) {
75357         var me = this,
75358             colIdx = me.editingPlugin.grid.headerCt.getHeaderIndex(column),
75359             field = column.getEditor({ xtype: 'displayfield' });
75360
75361         me.insert(colIdx, field);
75362     },
75363
75364     onFieldRemove: function(hm, fieldId, column) {
75365         var me = this,
75366             field = column.getEditor(),
75367             fieldDom = field.el.dom;
75368         me.remove(field, false);
75369         fieldDom.parentNode.removeChild(fieldDom);
75370     },
75371
75372     onFieldReplace: function(hm, fieldId, column, oldColumn) {
75373         var me = this;
75374         me.onFieldRemove(hm, fieldId, oldColumn);
75375     },
75376
75377     clearFields: function() {
75378         var me = this,
75379             hm = me.columns;
75380         hm.each(function(fieldId) {
75381             hm.removeAtKey(fieldId);
75382         });
75383     },
75384
75385     getFloatingButtons: function() {
75386         var me = this,
75387             cssPrefix = Ext.baseCSSPrefix,
75388             btnsCss = cssPrefix + 'grid-row-editor-buttons',
75389             plugin = me.editingPlugin,
75390             btns;
75391
75392         if (!me.floatingButtons) {
75393             btns = me.floatingButtons = Ext.create('Ext.Container', {
75394                 renderTpl: [
75395                     '<div class="{baseCls}-ml"></div>',
75396                     '<div class="{baseCls}-mr"></div>',
75397                     '<div class="{baseCls}-bl"></div>',
75398                     '<div class="{baseCls}-br"></div>',
75399                     '<div class="{baseCls}-bc"></div>'
75400                 ],
75401
75402                 renderTo: me.el,
75403                 baseCls: btnsCss,
75404                 layout: {
75405                     type: 'hbox',
75406                     align: 'middle'
75407                 },
75408                 defaults: {
75409                     margins: '0 1 0 1'
75410                 },
75411                 items: [{
75412                     itemId: 'update',
75413                     flex: 1,
75414                     xtype: 'button',
75415                     handler: plugin.completeEdit,
75416                     scope: plugin,
75417                     text: me.saveBtnText,
75418                     disabled: !me.isValid
75419                 }, {
75420                     flex: 1,
75421                     xtype: 'button',
75422                     handler: plugin.cancelEdit,
75423                     scope: plugin,
75424                     text: me.cancelBtnText
75425                 }]
75426             });
75427
75428             
75429             me.mon(btns.el, {
75430                 
75431                 
75432                 mousedown: Ext.emptyFn,
75433                 click: Ext.emptyFn,
75434                 stopEvent: true
75435             });
75436         }
75437         return me.floatingButtons;
75438     },
75439
75440     reposition: function(animateConfig) {
75441         var me = this,
75442             context = me.context,
75443             row = context && Ext.get(context.row),
75444             btns = me.getFloatingButtons(),
75445             btnEl = btns.el,
75446             grid = me.editingPlugin.grid,
75447             viewEl = grid.view.el,
75448             scroller = grid.verticalScroller,
75449
75450             
75451             
75452             mainBodyWidth = grid.headerCt.getFullWidth(),
75453             scrollerWidth = grid.getWidth(),
75454
75455             
75456             
75457             width = Math.min(mainBodyWidth, scrollerWidth),
75458             scrollLeft = grid.view.el.dom.scrollLeft,
75459             btnWidth = btns.getWidth(),
75460             left = (width - btnWidth) / 2 + scrollLeft,
75461             y, rowH, newHeight,
75462
75463             invalidateScroller = function() {
75464                 if (scroller) {
75465                     scroller.invalidate();
75466                     btnEl.scrollIntoView(viewEl, false);
75467                 }
75468                 if (animateConfig && animateConfig.callback) {
75469                     animateConfig.callback.call(animateConfig.scope || me);
75470                 }
75471             };
75472
75473         
75474         if (row && Ext.isElement(row.dom)) {
75475             
75476             
75477             row.scrollIntoView(viewEl, false);
75478
75479             
75480             
75481             
75482             y = row.getXY()[1] - 5;
75483             rowH = row.getHeight();
75484             newHeight = rowH + 10;
75485
75486             
75487             
75488             
75489             
75490             if (Ext.isIE) {
75491                 newHeight += 2;
75492             }
75493
75494             
75495             if (me.getHeight() != newHeight) {
75496                 me.setHeight(newHeight);
75497                 me.el.setLeft(0);
75498             }
75499
75500             if (animateConfig) {
75501                 var animObj = {
75502                     to: {
75503                         y: y
75504                     },
75505                     duration: animateConfig.duration || 125,
75506                     listeners: {
75507                         afteranimate: function() {
75508                             invalidateScroller();
75509                             y = row.getXY()[1] - 5;
75510                             me.el.setY(y);
75511                         }
75512                     }
75513                 };
75514                 me.animate(animObj);
75515             } else {
75516                 me.el.setY(y);
75517                 invalidateScroller();
75518             }
75519         }
75520         if (me.getWidth() != mainBodyWidth) {
75521             me.setWidth(mainBodyWidth);
75522         }
75523         btnEl.setLeft(left);
75524     },
75525
75526     getEditor: function(fieldInfo) {
75527         var me = this;
75528
75529         if (Ext.isNumber(fieldInfo)) {
75530             
75531             
75532             
75533             return me.query('>[isFormField]')[fieldInfo];
75534         } else if (fieldInfo instanceof Ext.grid.column.Column) {
75535             return fieldInfo.getEditor();
75536         }
75537     },
75538
75539     removeField: function(field) {
75540         var me = this;
75541
75542         
75543         field = me.getEditor(field);
75544         me.mun(field, 'validitychange', me.onValidityChange, me);
75545
75546         
75547         
75548         me.columns.removeKey(field.id);
75549     },
75550
75551     setField: function(column) {
75552         var me = this,
75553             field;
75554
75555         if (Ext.isArray(column)) {
75556             Ext.Array.forEach(column, me.setField, me);
75557             return;
75558         }
75559
75560         
75561         field = column.getEditor(null, { xtype: 'displayfield' });
75562         field.margins = '0 0 0 2';
75563         field.setWidth(column.getWidth() - 2);
75564         me.mon(field, 'change', me.onFieldChange, me);
75565
75566         
75567         
75568         me.columns.add(field.id, column);
75569     },
75570
75571     loadRecord: function(record) {
75572         var me = this,
75573             form = me.getForm();
75574         form.loadRecord(record);
75575         if (form.isValid()) {
75576             me.hideToolTip();
75577         } else {
75578             me.showToolTip();
75579         }
75580
75581         
75582         Ext.Array.forEach(me.query('>displayfield'), function(field) {
75583             me.renderColumnData(field, record);
75584         }, me);
75585     },
75586
75587     renderColumnData: function(field, record) {
75588         var me = this,
75589             grid = me.editingPlugin.grid,
75590             headerCt = grid.headerCt,
75591             view = grid.view,
75592             store = view.store,
75593             column = me.columns.get(field.id),
75594             value = field.getRawValue();
75595
75596         
75597         if (column.renderer) {
75598             var metaData = { tdCls: '', style: '' },
75599                 rowIdx = store.indexOf(record),
75600                 colIdx = headerCt.getHeaderIndex(column);
75601
75602             value = column.renderer.call(
75603                 column.scope || headerCt.ownerCt,
75604                 value,
75605                 metaData,
75606                 record,
75607                 rowIdx,
75608                 colIdx,
75609                 store,
75610                 view
75611             );
75612         }
75613
75614         field.setRawValue(value);
75615         field.resetOriginalValue();
75616     },
75617
75618     beforeEdit: function() {
75619         var me = this;
75620
75621         if (me.isVisible() && !me.autoCancel && me.isDirty()) {
75622             me.showToolTip();
75623             return false;
75624         }
75625     },
75626
75627     
75628     startEdit: function(record, columnHeader) {
75629         var me = this,
75630             grid = me.editingPlugin.grid,
75631             view = grid.getView(),
75632             store = grid.store,
75633             context = me.context = Ext.apply(me.editingPlugin.context, {
75634                 view: grid.getView(),
75635                 store: store
75636             });
75637
75638         
75639         context.grid.getSelectionModel().select(record);
75640
75641         
75642         me.loadRecord(record);
75643
75644         if (!me.isVisible()) {
75645             me.show();
75646             me.focusContextCell();
75647         } else {
75648             me.reposition({
75649                 callback: this.focusContextCell
75650             });
75651         }
75652     },
75653
75654     
75655     focusContextCell: function() {
75656         var field = this.getEditor(this.context.colIdx);
75657         if (field && field.focus) {
75658             field.focus();
75659         }
75660     },
75661
75662     cancelEdit: function() {
75663         var me = this,
75664             form = me.getForm();
75665
75666         me.hide();
75667         form.clearInvalid();
75668         form.reset();
75669     },
75670
75671     completeEdit: function() {
75672         var me = this,
75673             form = me.getForm();
75674
75675         if (!form.isValid()) {
75676             return;
75677         }
75678
75679         form.updateRecord(me.context.record);
75680         me.hide();
75681         return true;
75682     },
75683
75684     onShow: function() {
75685         var me = this;
75686         me.callParent(arguments);
75687         me.reposition();
75688     },
75689
75690     onHide: function() {
75691         var me = this;
75692         me.callParent(arguments);
75693         me.hideToolTip();
75694         me.invalidateScroller();
75695         if (me.context) {
75696             me.context.view.focus();
75697             me.context = null;
75698         }
75699     },
75700
75701     isDirty: function() {
75702         var me = this,
75703             form = me.getForm();
75704         return form.isDirty();
75705     },
75706
75707     getToolTip: function() {
75708         var me = this,
75709             tip;
75710
75711         if (!me.tooltip) {
75712             tip = me.tooltip = Ext.createWidget('tooltip', {
75713                 cls: Ext.baseCSSPrefix + 'grid-row-editor-errors',
75714                 title: me.errorsText,
75715                 autoHide: false,
75716                 closable: true,
75717                 closeAction: 'disable',
75718                 anchor: 'left'
75719             });
75720         }
75721         return me.tooltip;
75722     },
75723
75724     hideToolTip: function() {
75725         var me = this,
75726             tip = me.getToolTip();
75727         if (tip.rendered) {
75728             tip.disable();
75729         }
75730         me.hiddenTip = false;
75731     },
75732
75733     showToolTip: function() {
75734         var me = this,
75735             tip = me.getToolTip(),
75736             context = me.context,
75737             row = Ext.get(context.row),
75738             viewEl = context.grid.view.el;
75739
75740         tip.setTarget(row);
75741         tip.showAt([-10000, -10000]);
75742         tip.body.update(me.getErrors());
75743         tip.mouseOffset = [viewEl.getWidth() - row.getWidth() + me.lastScrollLeft + 15, 0];
75744         me.repositionTip();
75745         tip.doLayout();
75746         tip.enable();
75747     },
75748
75749     repositionTip: function() {
75750         var me = this,
75751             tip = me.getToolTip(),
75752             context = me.context,
75753             row = Ext.get(context.row),
75754             viewEl = context.grid.view.el,
75755             viewHeight = viewEl.getHeight(),
75756             viewTop = me.lastScrollTop,
75757             viewBottom = viewTop + viewHeight,
75758             rowHeight = row.getHeight(),
75759             rowTop = row.dom.offsetTop,
75760             rowBottom = rowTop + rowHeight;
75761
75762         if (rowBottom > viewTop && rowTop < viewBottom) {
75763             tip.show();
75764             me.hiddenTip = false;
75765         } else {
75766             tip.hide();
75767             me.hiddenTip = true;
75768         }
75769     },
75770
75771     getErrors: function() {
75772         var me = this,
75773             dirtyText = !me.autoCancel && me.isDirty() ? me.dirtyText + '<br />' : '',
75774             errors = [];
75775
75776         Ext.Array.forEach(me.query('>[isFormField]'), function(field) {
75777             errors = errors.concat(
75778                 Ext.Array.map(field.getErrors(), function(e) {
75779                     return '<li>' + e + '</li>';
75780                 })
75781             );
75782         }, me);
75783
75784         return dirtyText + '<ul>' + errors.join('') + '</ul>';
75785     },
75786
75787     invalidateScroller: function() {
75788         var me = this,
75789             context = me.context,
75790             scroller = context.grid.verticalScroller;
75791
75792         if (scroller) {
75793             scroller.invalidate();
75794         }
75795     }
75796 });
75797
75798 Ext.define('Ext.grid.header.Container', {
75799     extend: 'Ext.container.Container',
75800     uses: [
75801         'Ext.grid.ColumnLayout',
75802         'Ext.grid.column.Column',
75803         'Ext.menu.Menu',
75804         'Ext.menu.CheckItem',
75805         'Ext.menu.Separator',
75806         'Ext.grid.plugin.HeaderResizer',
75807         'Ext.grid.plugin.HeaderReorderer'
75808     ],
75809     border: true,
75810
75811     alias: 'widget.headercontainer',
75812
75813     baseCls: Ext.baseCSSPrefix + 'grid-header-ct',
75814     dock: 'top',
75815
75816     
75817     weight: 100,
75818     defaultType: 'gridcolumn',
75819     
75820     defaultWidth: 100,
75821
75822
75823     sortAscText: 'Sort Ascending',
75824     sortDescText: 'Sort Descending',
75825     sortClearText: 'Clear Sort',
75826     columnsText: 'Columns',
75827
75828     lastHeaderCls: Ext.baseCSSPrefix + 'column-header-last',
75829     firstHeaderCls: Ext.baseCSSPrefix + 'column-header-first',
75830     headerOpenCls: Ext.baseCSSPrefix + 'column-header-open',
75831
75832     
75833     triStateSort: false,
75834
75835     ddLock: false,
75836
75837     dragging: false,
75838
75839     
75840
75841     
75842     sortable: true,
75843     
75844     initComponent: function() {
75845         var me = this;
75846         
75847         me.headerCounter = 0;
75848         me.plugins = me.plugins || [];
75849
75850         
75851         
75852
75853         
75854         
75855         if (!me.isHeader) {
75856             me.resizer   = Ext.create('Ext.grid.plugin.HeaderResizer');
75857             me.reorderer = Ext.create('Ext.grid.plugin.HeaderReorderer');
75858             if (!me.enableColumnResize) {
75859                 me.resizer.disable();
75860             } 
75861             if (!me.enableColumnMove) {
75862                 me.reorderer.disable();
75863             }
75864             me.plugins.push(me.reorderer, me.resizer);
75865         }
75866
75867         
75868         if (me.isHeader && !me.items) {
75869             me.layout = 'auto';
75870         }
75871         
75872         else {
75873             me.layout = {
75874                 type: 'gridcolumn',
75875                 availableSpaceOffset: me.availableSpaceOffset,
75876                 align: 'stretchmax',
75877                 resetStretch: true
75878             };
75879         }
75880         me.defaults = me.defaults || {};
75881         Ext.applyIf(me.defaults, {
75882             width: me.defaultWidth,
75883             triStateSort: me.triStateSort,
75884             sortable: me.sortable
75885         });
75886         me.callParent();
75887         me.addEvents(
75888             
75889             'columnresize',
75890
75891             
75892             'headerclick',
75893
75894             
75895             'headertriggerclick',
75896
75897             
75898             'columnmove',
75899             
75900             'columnhide',
75901             
75902             'columnshow',
75903             
75904             'sortchange',
75905             
75906             'menucreate'
75907         );
75908     },
75909
75910     onDestroy: function() {
75911         Ext.destroy(this.resizer, this.reorderer);
75912         this.callParent();
75913     },
75914
75915     
75916     
75917     
75918     onAdd: function(c) {
75919         var me = this;
75920         if (!c.headerId) {
75921             c.headerId = 'h' + (++me.headerCounter);
75922         }
75923         me.callParent(arguments);
75924         me.purgeCache();
75925     },
75926
75927     
75928     
75929     
75930     onRemove: function(c) {
75931         var me = this;
75932         me.callParent(arguments);
75933         me.purgeCache();
75934     },
75935
75936     afterRender: function() {
75937         this.callParent();
75938         var store   = this.up('[store]').store,
75939             sorters = store.sorters,
75940             first   = sorters.first(),
75941             hd;
75942
75943         if (first) {
75944             hd = this.down('gridcolumn[dataIndex=' + first.property  +']');
75945             if (hd) {
75946                 hd.setSortState(first.direction, false, true);
75947             }
75948         }
75949     },
75950
75951     afterLayout: function() {
75952         if (!this.isHeader) {
75953             var me = this,
75954                 topHeaders = me.query('>gridcolumn:not([hidden])'),
75955                 viewEl;
75956
75957             me.callParent(arguments);
75958
75959             if (topHeaders.length) {
75960                 topHeaders[0].el.radioCls(me.firstHeaderCls);
75961                 topHeaders[topHeaders.length - 1].el.radioCls(me.lastHeaderCls);
75962             }
75963         }
75964     },
75965
75966     onHeaderShow: function(header) {
75967         
75968         var me = this,
75969             gridSection = me.ownerCt,
75970             menu = me.getMenu(),
75971             topItems, topItemsVisible,
75972             colCheckItem,
75973             itemToEnable,
75974             len, i;
75975
75976         if (menu) {
75977
75978             colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
75979             if (colCheckItem) {
75980                 colCheckItem.setChecked(true, true);
75981             }
75982
75983             
75984             topItems = menu.query('#columnItem>menucheckitem[checked]');
75985             topItemsVisible = topItems.length;
75986             if ((me.getVisibleGridColumns().length > 1) && me.disabledMenuItems && me.disabledMenuItems.length) {
75987                 if (topItemsVisible == 1) {
75988                     Ext.Array.remove(me.disabledMenuItems, topItems[0]);
75989                 }
75990                 for (i = 0, len = me.disabledMenuItems.length; i < len; i++) {
75991                     itemToEnable = me.disabledMenuItems[i];
75992                     if (!itemToEnable.isDestroyed) {
75993                         itemToEnable[itemToEnable.menu ? 'enableCheckChange' : 'enable']();
75994                     }
75995                 }
75996                 if (topItemsVisible == 1) {
75997                     me.disabledMenuItems = topItems;
75998                 } else {
75999                     me.disabledMenuItems = [];
76000                 }
76001             }
76002         }
76003
76004         
76005         
76006         if (!header.isGroupHeader) {
76007             if (me.view) {
76008                 me.view.onHeaderShow(me, header, true);
76009             }
76010             if (gridSection) {
76011                 gridSection.onHeaderShow(me, header);
76012             }
76013         }
76014         me.fireEvent('columnshow', me, header);
76015
76016         
76017         me.doLayout();
76018     },
76019
76020     onHeaderHide: function(header, suppressLayout) {
76021         
76022         var me = this,
76023             gridSection = me.ownerCt,
76024             menu = me.getMenu(),
76025             colCheckItem;
76026
76027         if (menu) {
76028
76029             
76030             colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
76031             if (colCheckItem) {
76032                 colCheckItem.setChecked(false, true);
76033             }
76034             me.setDisabledItems();
76035         }
76036
76037         
76038         if (!header.isGroupHeader) {
76039             if (me.view) {
76040                 me.view.onHeaderHide(me, header, true);
76041             }
76042             if (gridSection) {
76043                 gridSection.onHeaderHide(me, header);
76044             }
76045
76046             
76047             if (!suppressLayout) {
76048                 me.doLayout();
76049             }
76050         }
76051         me.fireEvent('columnhide', me, header);
76052     },
76053
76054     setDisabledItems: function(){
76055         var me = this,
76056             menu = me.getMenu(),
76057             i = 0,
76058             len,
76059             itemsToDisable,
76060             itemToDisable;
76061
76062         
76063         itemsToDisable = menu.query('#columnItem>menucheckitem[checked]');
76064         if ((itemsToDisable.length === 1)) {
76065             if (!me.disabledMenuItems) {
76066                 me.disabledMenuItems = [];
76067             }
76068
76069             
76070             if ((me.getVisibleGridColumns().length === 1) && itemsToDisable[0].menu) {
76071                 itemsToDisable = itemsToDisable.concat(itemsToDisable[0].menu.query('menucheckitem[checked]'));
76072             }
76073
76074             len = itemsToDisable.length;
76075             
76076             for (i = 0; i < len; i++) {
76077                 itemToDisable = itemsToDisable[i];
76078                 if (!Ext.Array.contains(me.disabledMenuItems, itemToDisable)) {
76079                     itemToDisable[itemToDisable.menu ? 'disableCheckChange' : 'disable']();
76080                     me.disabledMenuItems.push(itemToDisable);
76081                 }
76082             }
76083         }
76084     },
76085
76086     
76087     tempLock: function() {
76088         this.ddLock = true;
76089         Ext.Function.defer(function() {
76090             this.ddLock = false;
76091         }, 200, this);
76092     },
76093
76094     onHeaderResize: function(header, w, suppressFocus) {
76095         this.tempLock();
76096         if (this.view && this.view.rendered) {
76097             this.view.onHeaderResize(header, w, suppressFocus);
76098         }
76099         this.fireEvent('columnresize', this, header, w);
76100     },
76101
76102     onHeaderClick: function(header, e, t) {
76103         this.fireEvent("headerclick", this, header, e, t);
76104     },
76105
76106     onHeaderTriggerClick: function(header, e, t) {
76107         
76108         if (this.fireEvent("headertriggerclick", this, header, e, t) !== false) {
76109             this.showMenuBy(t, header);
76110         }
76111     },
76112
76113     showMenuBy: function(t, header) {
76114         var menu = this.getMenu(),
76115             ascItem  = menu.down('#ascItem'),
76116             descItem = menu.down('#descItem'),
76117             sortableMth;
76118
76119         menu.activeHeader = menu.ownerCt = header;
76120         menu.setFloatParent(header);
76121         
76122         header.titleContainer.addCls(this.headerOpenCls);
76123
76124         
76125         sortableMth = header.sortable ? 'enable' : 'disable';
76126         if (ascItem) {
76127             ascItem[sortableMth]();
76128         }
76129         if (descItem) {
76130             descItem[sortableMth]();
76131         }
76132         menu.showBy(t);
76133     },
76134
76135     
76136     onMenuDeactivate: function() {
76137         var menu = this.getMenu();
76138         
76139         menu.activeHeader.titleContainer.removeCls(this.headerOpenCls);
76140     },
76141
76142     moveHeader: function(fromIdx, toIdx) {
76143
76144         
76145         this.tempLock();
76146         this.onHeaderMoved(this.move(fromIdx, toIdx), fromIdx, toIdx);
76147     },
76148
76149     purgeCache: function() {
76150         var me = this;
76151         
76152         delete me.gridDataColumns;
76153
76154         
76155         if (me.menu) {
76156             me.menu.destroy();
76157             delete me.menu;
76158         }
76159     },
76160
76161     onHeaderMoved: function(header, fromIdx, toIdx) {
76162         var me = this,
76163             gridSection = me.ownerCt;
76164
76165         if (gridSection) {
76166             gridSection.onHeaderMove(me, header, fromIdx, toIdx);
76167         }
76168         me.fireEvent("columnmove", me, header, fromIdx, toIdx);
76169     },
76170
76171     
76172     getMenu: function() {
76173         var me = this;
76174
76175         if (!me.menu) {
76176             me.menu = Ext.create('Ext.menu.Menu', {
76177                 items: me.getMenuItems(),
76178                 listeners: {
76179                     deactivate: me.onMenuDeactivate,
76180                     scope: me
76181                 }
76182             });
76183             me.setDisabledItems();
76184             me.fireEvent('menucreate', me, me.menu);
76185         }
76186         return me.menu;
76187     },
76188
76189     
76190     getMenuItems: function() {
76191         var me = this,
76192             menuItems = [{
76193                 itemId: 'columnItem',
76194                 text: me.columnsText,
76195                 cls: Ext.baseCSSPrefix + 'cols-icon',
76196                 menu: me.getColumnMenu(me)
76197             }];
76198
76199         if (me.sortable) {
76200             menuItems.unshift({
76201                 itemId: 'ascItem',
76202                 text: me.sortAscText,
76203                 cls: 'xg-hmenu-sort-asc',
76204                 handler: me.onSortAscClick,
76205                 scope: me
76206             },{
76207                 itemId: 'descItem',
76208                 text: me.sortDescText,
76209                 cls: 'xg-hmenu-sort-desc',
76210                 handler: me.onSortDescClick,
76211                 scope: me
76212             },'-');
76213         }
76214         return menuItems;
76215     },
76216
76217     
76218     onSortAscClick: function() {
76219         var menu = this.getMenu(),
76220             activeHeader = menu.activeHeader;
76221
76222         activeHeader.setSortState('ASC');
76223     },
76224
76225     
76226     onSortDescClick: function() {
76227         var menu = this.getMenu(),
76228             activeHeader = menu.activeHeader;
76229
76230         activeHeader.setSortState('DESC');
76231     },
76232
76233     
76234     getColumnMenu: function(headerContainer) {
76235         var menuItems = [],
76236             i = 0,
76237             item,
76238             items = headerContainer.query('>gridcolumn[hideable]'),
76239             itemsLn = items.length,
76240             menuItem;
76241
76242         for (; i < itemsLn; i++) {
76243             item = items[i];
76244             menuItem = Ext.create('Ext.menu.CheckItem', {
76245                 text: item.text,
76246                 checked: !item.hidden,
76247                 hideOnClick: false,
76248                 headerId: item.id,
76249                 menu: item.isGroupHeader ? this.getColumnMenu(item) : undefined,
76250                 checkHandler: this.onColumnCheckChange,
76251                 scope: this
76252             });
76253             if (itemsLn === 1) {
76254                 menuItem.disabled = true;
76255             }
76256             menuItems.push(menuItem);
76257
76258             
76259             
76260             item.on({
76261                 destroy: Ext.Function.bind(menuItem.destroy, menuItem)
76262             });
76263         }
76264         return menuItems;
76265     },
76266
76267     onColumnCheckChange: function(checkItem, checked) {
76268         var header = Ext.getCmp(checkItem.headerId);
76269         header[checked ? 'show' : 'hide']();
76270     },
76271
76272     
76273     getColumnsForTpl: function(flushCache) {
76274         var cols    = [],
76275             headers   = this.getGridColumns(flushCache),
76276             headersLn = headers.length,
76277             i = 0,
76278             header;
76279
76280         for (; i < headersLn; i++) {
76281             header = headers[i];
76282             cols.push({
76283                 dataIndex: header.dataIndex,
76284                 align: header.align,
76285                 width: header.hidden ? 0 : header.getDesiredWidth(),
76286                 id: header.id,
76287                 cls: header.tdCls,
76288                 columnId: header.getItemId()
76289             });
76290         }
76291         return cols;
76292     },
76293
76294     
76295     getColumnCount: function() {
76296         return this.getGridColumns().length;
76297     },
76298
76299     
76300     getFullWidth: function(flushCache) {
76301         var fullWidth = 0,
76302             headers     = this.getVisibleGridColumns(flushCache),
76303             headersLn   = headers.length,
76304             i         = 0;
76305
76306         for (; i < headersLn; i++) {
76307             if (!isNaN(headers[i].width)) {
76308                 
76309                 if (headers[i].getDesiredWidth) {
76310                     fullWidth += headers[i].getDesiredWidth();
76311                 
76312                 } else {
76313                     fullWidth += headers[i].getWidth();
76314                 }
76315             }
76316         }
76317         return fullWidth;
76318     },
76319
76320     
76321     clearOtherSortStates: function(activeHeader) {
76322         var headers   = this.getGridColumns(),
76323             headersLn = headers.length,
76324             i         = 0,
76325             oldSortState;
76326
76327         for (; i < headersLn; i++) {
76328             if (headers[i] !== activeHeader) {
76329                 oldSortState = headers[i].sortState;
76330                 
76331                 headers[i].setSortState(null, true);
76332                 
76333                 
76334                 
76335             }
76336         }
76337     },
76338
76339     
76340     getVisibleGridColumns: function(refreshCache) {
76341         return Ext.ComponentQuery.query(':not([hidden])', this.getGridColumns(refreshCache));
76342     },
76343
76344     
76345     getGridColumns: function(refreshCache) {
76346         var me = this,
76347             result = refreshCache ? null : me.gridDataColumns;
76348
76349         
76350         if (!result) {
76351             me.gridDataColumns = result = [];
76352             me.cascade(function(c) {
76353                 if ((c !== me) && !c.isGroupHeader) {
76354                     result.push(c);
76355                 }
76356             });
76357         }
76358
76359         return result;
76360     },
76361
76362     
76363     getHeaderIndex: function(header) {
76364         var columns = this.getGridColumns();
76365         return Ext.Array.indexOf(columns, header);
76366     },
76367
76368     
76369     getHeaderAtIndex: function(index) {
76370         var columns = this.getGridColumns();
76371         return columns[index];
76372     },
76373
76374     
76375     prepareData: function(data, rowIdx, record, view) {
76376         var obj       = {},
76377             headers   = this.getGridColumns(),
76378             headersLn = headers.length,
76379             colIdx    = 0,
76380             header, value,
76381             metaData,
76382             g = this.up('tablepanel'),
76383             store = g.store;
76384
76385         for (; colIdx < headersLn; colIdx++) {
76386             metaData = {
76387                 tdCls: '',
76388                 style: ''
76389             };
76390             header = headers[colIdx];
76391             value = data[header.dataIndex];
76392
76393             
76394             
76395             if (Ext.isString(header.renderer)) {
76396                 header.renderer = Ext.util.Format[header.renderer];
76397             }
76398
76399             if (Ext.isFunction(header.renderer)) {
76400                 value = header.renderer.call(
76401                     header.scope || this.ownerCt,
76402                     value,
76403                     
76404                     
76405                     metaData,
76406                     record,
76407                     rowIdx,
76408                     colIdx,
76409                     store,
76410                     view
76411                 );
76412             }
76413
76414             if (metaData.css) {
76415                 
76416                 obj.cssWarning = true;
76417                 metaData.tdCls = metaData.css;
76418                 delete metaData.css;
76419             }
76420             obj[header.id+'-modified'] = record.isModified(header.dataIndex) ? Ext.baseCSSPrefix + 'grid-dirty-cell' : Ext.baseCSSPrefix + 'grid-clean-cell';
76421             obj[header.id+'-tdCls'] = metaData.tdCls;
76422             obj[header.id+'-tdAttr'] = metaData.tdAttr;
76423             obj[header.id+'-style'] = metaData.style;
76424             if (value === undefined || value === null || value === '') {
76425                 value = '&#160;';
76426             }
76427             obj[header.id] = value;
76428         }
76429         return obj;
76430     },
76431
76432     expandToFit: function(header) {
76433         if (this.view) {
76434             this.view.expandToFit(header);
76435         }
76436     }
76437 });
76438
76439
76440 Ext.define('Ext.grid.column.Column', {
76441     extend: 'Ext.grid.header.Container',
76442     alias: 'widget.gridcolumn',
76443     requires: ['Ext.util.KeyNav'],
76444     alternateClassName: 'Ext.grid.Column',
76445
76446     baseCls: Ext.baseCSSPrefix + 'column-header ' + Ext.baseCSSPrefix + 'unselectable',
76447
76448     
76449     hoverCls: Ext.baseCSSPrefix + 'column-header-over',
76450
76451     handleWidth: 5,
76452
76453     sortState: null,
76454
76455     possibleSortStates: ['ASC', 'DESC'],
76456
76457     renderTpl:
76458         '<div class="' + Ext.baseCSSPrefix + 'column-header-inner">' +
76459             '<span class="' + Ext.baseCSSPrefix + 'column-header-text">' +
76460                 '{text}' +
76461             '</span>' +
76462             '<tpl if="!values.menuDisabled"><div class="' + Ext.baseCSSPrefix + 'column-header-trigger"></div></tpl>' +
76463         '</div>',
76464
76465     
76466
76467     
76468     dataIndex: null,
76469
76470     
76471     text: '&#160',
76472
76473     
76474     sortable: true,
76475     
76476     
76477      
76478     
76479     hideable: true,
76480
76481     
76482     menuDisabled: false,
76483
76484     
76485     renderer: false,
76486
76487     
76488     align: 'left',
76489
76490     
76491     draggable: true,
76492
76493     
76494     
76495     initDraggable: Ext.emptyFn,
76496
76497     
76498
76499     
76500
76501     
76502
76503     
76504     isHeader: true,
76505
76506     initComponent: function() {
76507         var me = this,
76508             i,
76509             len;
76510         
76511         if (Ext.isDefined(me.header)) {
76512             me.text = me.header;
76513             delete me.header;
76514         }
76515
76516         
76517         
76518         
76519         if (me.flex) {
76520             me.minWidth = me.minWidth || Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
76521         }
76522         
76523         
76524         else {
76525             me.minWidth = me.width;
76526         }
76527
76528         if (!me.triStateSort) {
76529             me.possibleSortStates.length = 2;
76530         }
76531
76532         
76533         if (Ext.isDefined(me.columns)) {
76534             me.isGroupHeader = true;
76535
76536             if (me.dataIndex) {
76537                 Ext.Error.raise('Ext.grid.column.Column: Group header may not accept a dataIndex');
76538             }
76539             if ((me.width && me.width !== Ext.grid.header.Container.prototype.defaultWidth) || me.flex) {
76540                 Ext.Error.raise('Ext.grid.column.Column: Group header does not support setting explicit widths or flexs. The group header width is calculated by the sum of its children.');
76541             }
76542
76543             
76544             me.items = me.columns;
76545             delete me.columns;
76546             delete me.flex;
76547             me.width = 0;
76548
76549             
76550             for (i = 0, len = me.items.length; i < len; i++) {
76551                 me.width += me.items[i].width || Ext.grid.header.Container.prototype.defaultWidth;
76552                 if (me.items[i].flex) {
76553                     Ext.Error.raise('Ext.grid.column.Column: items of a grouped header do not support flexed values. Each item must explicitly define its width.');
76554                 }
76555             }
76556             me.minWidth = me.width;
76557
76558             me.cls = (me.cls||'') + ' ' + Ext.baseCSSPrefix + 'group-header';
76559             me.sortable = false;
76560             me.fixed = true;
76561             me.align = 'center';
76562         }
76563
76564         Ext.applyIf(me.renderSelectors, {
76565             titleContainer: '.' + Ext.baseCSSPrefix + 'column-header-inner',
76566             triggerEl: '.' + Ext.baseCSSPrefix + 'column-header-trigger',
76567             textEl: '.' + Ext.baseCSSPrefix + 'column-header-text'
76568         });
76569
76570         
76571         me.callParent(arguments);
76572     },
76573
76574     onAdd: function(childHeader) {
76575         childHeader.isSubHeader = true;
76576         childHeader.addCls(Ext.baseCSSPrefix + 'group-sub-header');
76577     },
76578
76579     onRemove: function(childHeader) {
76580         childHeader.isSubHeader = false;
76581         childHeader.removeCls(Ext.baseCSSPrefix + 'group-sub-header');
76582     },
76583
76584     initRenderData: function() {
76585         var me = this;
76586         
76587         Ext.applyIf(me.renderData, {
76588             text: me.text,
76589             menuDisabled: me.menuDisabled
76590         });
76591         return me.callParent(arguments);
76592     },
76593
76594     
76595     setText: function(text) {
76596         this.text = text;
76597         if (this.rendered) {
76598             this.textEl.update(text);
76599         } 
76600     },
76601
76602     
76603     
76604     getOwnerHeaderCt: function() {
76605         return this.up(':not([isHeader])');
76606     },
76607
76608     
76609     getIndex: function() {
76610         return this.isGroupColumn ? false : this.getOwnerHeaderCt().getHeaderIndex(this);
76611     },
76612
76613     afterRender: function() {
76614         var me = this,
76615             el = me.el;
76616
76617         me.callParent(arguments);
76618
76619         el.addCls(Ext.baseCSSPrefix + 'column-header-align-' + me.align).addClsOnOver(me.overCls);
76620
76621         me.mon(el, {
76622             click:     me.onElClick,
76623             dblclick:  me.onElDblClick,
76624             scope:     me
76625         });
76626         
76627         
76628         
76629         if (!Ext.isIE8 || !Ext.isStrict) {
76630             me.mon(me.getFocusEl(), {
76631                 focus: me.onTitleMouseOver,
76632                 blur: me.onTitleMouseOut,
76633                 scope: me
76634             });
76635         }
76636
76637         me.mon(me.titleContainer, {
76638             mouseenter:  me.onTitleMouseOver,
76639             mouseleave:  me.onTitleMouseOut,
76640             scope:      me
76641         });
76642
76643         me.keyNav = Ext.create('Ext.util.KeyNav', el, {
76644             enter: me.onEnterKey,
76645             down: me.onDownKey,
76646             scope: me
76647         });
76648     },
76649
76650     setSize: function(width, height) {
76651         var me = this,
76652             headerCt = me.ownerCt,
76653             ownerHeaderCt = me.getOwnerHeaderCt(),
76654             siblings,
76655             len, i,
76656             oldWidth = me.getWidth(),
76657             newWidth = 0;
76658
76659         if (width !== oldWidth) {
76660
76661             
76662             if (headerCt.isGroupHeader) {
76663
76664                 siblings = headerCt.items.items;
76665                 len = siblings.length;
76666
76667                 
76668                 if (siblings[len - 1].rendered) {
76669
76670                     for (i = 0; i < len; i++) {
76671                         newWidth += (siblings[i] === me) ? width : siblings[i].getWidth();
76672                     }
76673                     headerCt.minWidth = newWidth;
76674                     headerCt.setWidth(newWidth);
76675                 }
76676             }
76677             me.callParent(arguments);
76678         }
76679     },
76680
76681     afterComponentLayout: function(width, height) {
76682         var me = this,
76683             ownerHeaderCt = this.getOwnerHeaderCt();
76684
76685         me.callParent(arguments);
76686
76687         
76688         
76689         
76690         if (width && !me.isGroupHeader && ownerHeaderCt) {
76691             ownerHeaderCt.onHeaderResize(me, width, true);
76692         }
76693     },
76694
76695     
76696     
76697     setPadding: function() {
76698         var me = this,
76699             headerHeight,
76700             lineHeight = parseInt(me.textEl.getStyle('line-height'), 10);
76701
76702         
76703         if (!me.isGroupHeader) {
76704             headerHeight = me.el.getViewSize().height;
76705             if (me.titleContainer.getHeight() < headerHeight) {
76706                 me.titleContainer.dom.style.height = headerHeight + 'px';
76707             }
76708         }
76709         headerHeight = me.titleContainer.getViewSize().height;
76710
76711         
76712         if (lineHeight) {
76713             me.titleContainer.setStyle({
76714                 paddingTop: Math.max(((headerHeight - lineHeight) / 2), 0) + 'px'
76715             });
76716         }
76717
76718         
76719         if (Ext.isIE && me.triggerEl) {
76720             me.triggerEl.setHeight(headerHeight);
76721         }
76722     },
76723
76724     onDestroy: function() {
76725         var me = this;
76726         Ext.destroy(me.keyNav);
76727         delete me.keyNav;
76728         me.callParent(arguments);
76729     },
76730
76731     onTitleMouseOver: function() {
76732         this.titleContainer.addCls(this.hoverCls);
76733     },
76734
76735     onTitleMouseOut: function() {
76736         this.titleContainer.removeCls(this.hoverCls);
76737     },
76738
76739     onDownKey: function(e) {
76740         if (this.triggerEl) {
76741             this.onElClick(e, this.triggerEl.dom || this.el.dom);
76742         }
76743     },
76744
76745     onEnterKey: function(e) {
76746         this.onElClick(e, this.el.dom);
76747     },
76748
76749     
76750     onElDblClick: function(e, t) {
76751         var me = this,
76752             ownerCt = me.ownerCt;
76753         if (ownerCt && Ext.Array.indexOf(ownerCt.items, me) !== 0 && me.isOnLeftEdge(e) ) {
76754             ownerCt.expandToFit(me.previousSibling('gridcolumn'));
76755         }
76756     },
76757
76758     onElClick: function(e, t) {
76759
76760         
76761         var me = this,
76762             ownerHeaderCt = me.getOwnerHeaderCt();
76763
76764         if (ownerHeaderCt && !ownerHeaderCt.ddLock) {
76765             
76766             
76767             if (me.triggerEl && (e.target === me.triggerEl.dom || t === me.triggerEl.dom || e.within(me.triggerEl))) {
76768                 ownerHeaderCt.onHeaderTriggerClick(me, e, t);
76769             
76770             } else if (e.getKey() || (!me.isOnLeftEdge(e) && !me.isOnRightEdge(e))) {
76771                 me.toggleSortState();
76772                 ownerHeaderCt.onHeaderClick(me, e, t);
76773             }
76774         }
76775     },
76776
76777     
76778     processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
76779         return this.fireEvent.apply(this, arguments);
76780     },
76781
76782     toggleSortState: function() {
76783         var me = this,
76784             idx,
76785             nextIdx;
76786             
76787         if (me.sortable) {
76788             idx = Ext.Array.indexOf(me.possibleSortStates, me.sortState);
76789
76790             nextIdx = (idx + 1) % me.possibleSortStates.length;
76791             me.setSortState(me.possibleSortStates[nextIdx]);
76792         }
76793     },
76794
76795     doSort: function(state) {
76796         var ds = this.up('tablepanel').store;
76797         ds.sort({
76798             property: this.getSortParam(),
76799             direction: state
76800         });
76801     },
76802
76803     
76804     getSortParam: function() {
76805         return this.dataIndex;
76806     },
76807
76808     
76809     
76810     setSortState: function(state, skipClear, initial) {
76811         var me = this,
76812             colSortClsPrefix = Ext.baseCSSPrefix + 'column-header-sort-',
76813             ascCls = colSortClsPrefix + 'ASC',
76814             descCls = colSortClsPrefix + 'DESC',
76815             nullCls = colSortClsPrefix + 'null',
76816             ownerHeaderCt = me.getOwnerHeaderCt(),
76817             oldSortState = me.sortState;
76818
76819         if (oldSortState !== state && me.getSortParam()) {
76820             me.addCls(colSortClsPrefix + state);
76821             
76822             if (state && !initial) {
76823                 me.doSort(state);
76824             }
76825             switch (state) {
76826                 case 'DESC':
76827                     me.removeCls([ascCls, nullCls]);
76828                     break;
76829                 case 'ASC':
76830                     me.removeCls([descCls, nullCls]);
76831                     break;
76832                 case null:
76833                     me.removeCls([ascCls, descCls]);
76834                     break;
76835             }
76836             if (ownerHeaderCt && !me.triStateSort && !skipClear) {
76837                 ownerHeaderCt.clearOtherSortStates(me);
76838             }
76839             me.sortState = state;
76840             ownerHeaderCt.fireEvent('sortchange', ownerHeaderCt, me, state);
76841         }
76842     },
76843
76844     hide: function() {
76845         var me = this,
76846             items,
76847             len, i,
76848             lb,
76849             newWidth = 0,
76850             ownerHeaderCt = me.getOwnerHeaderCt();
76851
76852         
76853         me.oldWidth = me.getWidth();
76854
76855         
76856         if (me.isGroupHeader) {
76857             items = me.items.items;
76858             me.callParent(arguments);
76859             ownerHeaderCt.onHeaderHide(me);
76860             for (i = 0, len = items.length; i < len; i++) {
76861                 items[i].hidden = true;
76862                 ownerHeaderCt.onHeaderHide(items[i], true);
76863             }
76864             return;
76865         }
76866
76867         
76868         lb = me.ownerCt.componentLayout.layoutBusy;
76869         me.ownerCt.componentLayout.layoutBusy = true;
76870         me.callParent(arguments);
76871         me.ownerCt.componentLayout.layoutBusy = lb;
76872
76873         
76874         ownerHeaderCt.onHeaderHide(me);
76875
76876         if (me.ownerCt.isGroupHeader) {
76877             
76878             items = me.ownerCt.query('>:not([hidden])');
76879             if (!items.length) {
76880                 me.ownerCt.hide();
76881             }
76882             
76883             else {
76884                 for (i = 0, len = items.length; i < len; i++) {
76885                     newWidth += items[i].getWidth();
76886                 }
76887                 me.ownerCt.minWidth = newWidth;
76888                 me.ownerCt.setWidth(newWidth);
76889             }
76890         }
76891     },
76892
76893     show: function() {
76894         var me = this,
76895             ownerCt = me.getOwnerHeaderCt(),
76896             lb,
76897             items,
76898             len, i,
76899             newWidth = 0;
76900
76901         
76902         lb = me.ownerCt.componentLayout.layoutBusy;
76903         me.ownerCt.componentLayout.layoutBusy = true;
76904         me.callParent(arguments);
76905         me.ownerCt.componentLayout.layoutBusy = lb;
76906
76907         
76908         if (me.isSubHeader) {
76909             if (!me.ownerCt.isVisible()) {
76910                 me.ownerCt.show();
76911             }
76912         }
76913
76914         
76915         if (me.isGroupHeader && !me.query(':not([hidden])').length) {
76916             items = me.query('>*');
76917             for (i = 0, len = items.length; i < len; i++) {
76918                 items[i].show();
76919             }
76920         }
76921
76922         
76923         if (me.ownerCt.isGroupHeader) {
76924             items = me.ownerCt.query('>:not([hidden])');
76925             for (i = 0, len = items.length; i < len; i++) {
76926                 newWidth += items[i].getWidth();
76927             }
76928             me.ownerCt.minWidth = newWidth;
76929             me.ownerCt.setWidth(newWidth);
76930         }
76931
76932         
76933         if (ownerCt) {
76934             ownerCt.onHeaderShow(me);
76935         }
76936     },
76937
76938     getDesiredWidth: function() {
76939         var me = this;
76940         if (me.rendered && me.componentLayout && me.componentLayout.lastComponentSize) {
76941             
76942             
76943             
76944             
76945             
76946             
76947             return me.componentLayout.lastComponentSize.width;
76948         
76949         
76950         
76951         }
76952         else if (me.flex) {
76953             
76954             return me.width;
76955         }
76956         else {
76957             return me.width;
76958         }
76959     },
76960
76961     getCellSelector: function() {
76962         return '.' + Ext.baseCSSPrefix + 'grid-cell-' + this.getItemId();
76963     },
76964
76965     getCellInnerSelector: function() {
76966         return this.getCellSelector() + ' .' + Ext.baseCSSPrefix + 'grid-cell-inner';
76967     },
76968
76969     isOnLeftEdge: function(e) {
76970         return (e.getXY()[0] - this.el.getLeft() <= this.handleWidth);
76971     },
76972
76973     isOnRightEdge: function(e) {
76974         return (this.el.getRight() - e.getXY()[0] <= this.handleWidth);
76975     }
76976     
76977     
76978     
76979     
76980     
76981     
76982     
76983 });
76984
76985 Ext.define('Ext.grid.RowNumberer', {
76986     extend: 'Ext.grid.column.Column',
76987     alias: 'widget.rownumberer',
76988     
76989     text: "&#160",
76990
76991     
76992     width: 23,
76993
76994     
76995     sortable: false,
76996
76997     align: 'right',
76998
76999     constructor : function(config){
77000         this.callParent(arguments);
77001         if (this.rowspan) {
77002             this.renderer = Ext.Function.bind(this.renderer, this);
77003         }
77004     },
77005
77006     
77007     fixed: true,
77008     hideable: false,
77009     menuDisabled: true,
77010     dataIndex: '',
77011     cls: Ext.baseCSSPrefix + 'row-numberer',
77012     rowspan: undefined,
77013
77014     
77015     renderer: function(value, metaData, record, rowIdx, colIdx, store) {
77016         if (this.rowspan){
77017             metaData.cellAttr = 'rowspan="'+this.rowspan+'"';
77018         }
77019
77020         metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
77021         return store.indexOfTotal(record) + 1;
77022     }
77023 });
77024
77025
77026 Ext.define('Ext.view.DropZone', {
77027     extend: 'Ext.dd.DropZone',
77028
77029     indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
77030     indicatorCls: 'x-grid-drop-indicator',
77031
77032     constructor: function(config) {
77033         var me = this;
77034         Ext.apply(me, config);
77035
77036         
77037         
77038         
77039         
77040         
77041         if (!me.ddGroup) {
77042             me.ddGroup = 'view-dd-zone-' + me.view.id;
77043         }
77044
77045         
77046         
77047         
77048         me.callParent([me.view.el]);
77049     },
77050
77051
77052
77053     fireViewEvent: function() {
77054         this.lock();
77055         var result = this.view.fireEvent.apply(this.view, arguments);
77056         this.unlock();
77057         return result;
77058     },
77059
77060     getTargetFromEvent : function(e) {
77061         var node = e.getTarget(this.view.getItemSelector()),
77062             mouseY, nodeList, testNode, i, len, box;
77063
77064
77065
77066         if (!node) {
77067             mouseY = e.getPageY();
77068             for (i = 0, nodeList = this.view.getNodes(), len = nodeList.length; i < len; i++) {
77069                 testNode = nodeList[i];
77070                 box = Ext.fly(testNode).getBox();
77071                 if (mouseY <= box.bottom) {
77072                     return testNode;
77073                 }
77074             }
77075         }
77076         return node;
77077     },
77078
77079     getIndicator: function() {
77080         var me = this;
77081
77082         if (!me.indicator) {
77083             me.indicator = Ext.createWidget('component', {
77084                 html: me.indicatorHtml,
77085                 cls: me.indicatorCls,
77086                 ownerCt: me.view,
77087                 floating: true,
77088                 shadow: false
77089             });
77090         }
77091         return me.indicator;
77092     },
77093
77094     getPosition: function(e, node) {
77095         var y      = e.getXY()[1],
77096             region = Ext.fly(node).getRegion(),
77097             pos;
77098
77099         if ((region.bottom - y) >= (region.bottom - region.top) / 2) {
77100             pos = "before";
77101         } else {
77102             pos = "after";
77103         }
77104         return pos;
77105     },
77106
77107     
77108     containsRecordAtOffset: function(records, record, offset) {
77109         if (!record) {
77110             return false;
77111         }
77112         var view = this.view,
77113             recordIndex = view.indexOf(record),
77114             nodeBefore = view.getNode(recordIndex + offset),
77115             recordBefore = nodeBefore ? view.getRecord(nodeBefore) : null;
77116
77117         return recordBefore && Ext.Array.contains(records, recordBefore);
77118     },
77119
77120     positionIndicator: function(node, data, e) {
77121         var me = this,
77122             view = me.view,
77123             pos = me.getPosition(e, node),
77124             overRecord = view.getRecord(node),
77125             draggingRecords = data.records,
77126             indicator, indicatorY;
77127
77128         if (!Ext.Array.contains(draggingRecords, overRecord) && (
77129             pos == 'before' && !me.containsRecordAtOffset(draggingRecords, overRecord, -1) ||
77130             pos == 'after' && !me.containsRecordAtOffset(draggingRecords, overRecord, 1)
77131         )) {
77132             me.valid = true;
77133
77134             if (me.overRecord != overRecord || me.currentPosition != pos) {
77135
77136                 indicatorY = Ext.fly(node).getY() - view.el.getY() - 1;
77137                 if (pos == 'after') {
77138                     indicatorY += Ext.fly(node).getHeight();
77139                 }
77140                 me.getIndicator().setWidth(Ext.fly(view.el).getWidth()).showAt(0, indicatorY);
77141
77142                 
77143                 me.overRecord = overRecord;
77144                 me.currentPosition = pos;
77145             }
77146         } else {
77147             me.invalidateDrop();
77148         }
77149     },
77150
77151     invalidateDrop: function() {
77152         if (this.valid) {
77153             this.valid = false;
77154             this.getIndicator().hide();
77155         }
77156     },
77157
77158     
77159     onNodeOver: function(node, dragZone, e, data) {
77160         if (!Ext.Array.contains(data.records, this.view.getRecord(node))) {
77161             this.positionIndicator(node, data, e);
77162         }
77163         return this.valid ? this.dropAllowed : this.dropNotAllowed;
77164     },
77165
77166     
77167     
77168     notifyOut: function(node, dragZone, e, data) {
77169         this.callParent(arguments);
77170         delete this.overRecord;
77171         delete this.currentPosition;
77172         if (this.indicator) {
77173             this.indicator.hide();
77174         }
77175     },
77176
77177     
77178     onContainerOver : function(dd, e, data) {
77179         var v = this.view,
77180             c = v.store.getCount();
77181
77182         
77183         if (c) {
77184             this.positionIndicator(v.getNode(c - 1), data, e);
77185         }
77186
77187         
77188         else {
77189             delete this.overRecord;
77190             delete this.currentPosition;
77191             this.getIndicator().setWidth(Ext.fly(v.el).getWidth()).showAt(0, 0);
77192             this.valid = true;
77193         }
77194         return this.dropAllowed;
77195     },
77196
77197     onContainerDrop : function(dd, e, data) {
77198         return this.onNodeDrop(dd, null, e, data);
77199     },
77200
77201     onNodeDrop: function(node, dragZone, e, data) {
77202         var me = this,
77203             dropped = false,
77204
77205             
77206             
77207             
77208             
77209             processDrop = function () {
77210                 me.invalidateDrop();
77211                 me.handleNodeDrop(data, me.overRecord, me.currentPosition);
77212                 dropped = true;
77213                 me.fireViewEvent('drop', node, data, me.overRecord, me.currentPosition);
77214             },
77215             performOperation;
77216
77217         if (me.valid) {
77218             performOperation = me.fireViewEvent('beforedrop', node, data, me.overRecord, me.currentPosition, processDrop);
77219             if (performOperation === 0) {
77220                 return;
77221             } else if (performOperation !== false) {
77222                 
77223                 if (!dropped) {
77224                     processDrop();
77225                 }
77226             } else {
77227                 return false;
77228             }
77229         } else {
77230             return false;
77231         }
77232     }
77233 });
77234
77235 Ext.define('Ext.grid.ViewDropZone', {
77236     extend: 'Ext.view.DropZone',
77237
77238     indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
77239     indicatorCls: 'x-grid-drop-indicator',
77240
77241     handleNodeDrop : function(data, record, position) {
77242         var view = this.view,
77243             store = view.getStore(),
77244             index, records, i, len;
77245
77246         
77247         if (data.copy) {
77248             records = data.records;
77249             data.records = [];
77250             for (i = 0, len = records.length; i < len; i++) {
77251                 data.records.push(records[i].copy(records[i].getId()));
77252             }
77253         } else {
77254             
77255             data.view.store.remove(data.records, data.view === view);
77256         }
77257
77258         index = store.indexOf(record);
77259         if (position == 'after') {
77260             index++;
77261         }
77262         store.insert(index, data.records);
77263         view.getSelectionModel().select(data.records);
77264     }
77265 });
77266
77267 Ext.define('Ext.grid.column.Action', {
77268     extend: 'Ext.grid.column.Column',
77269     alias: ['widget.actioncolumn'],
77270     alternateClassName: 'Ext.grid.ActionColumn',
77271
77272     
77273     
77274     
77275     
77276     
77277     
77278     
77279     
77280     header: '&#160;',
77281
77282     actionIdRe: /x-action-col-(\d+)/,
77283
77284     
77285     altText: '',
77286     
77287     sortable: false,
77288
77289     constructor: function(config) {
77290         var me = this,
77291             cfg = Ext.apply({}, config),
77292             items = cfg.items || [me],
77293             l = items.length,
77294             i,
77295             item;
77296
77297         
77298         delete cfg.items;
77299         this.callParent([cfg]);
77300
77301         
77302         me.items = items;
77303
77304
77305
77306         me.renderer = function(v, meta) {
77307
77308             v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments)||'' : '';
77309
77310             meta.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell';
77311             for (i = 0; i < l; i++) {
77312                 item = items[i];
77313                 v += '<img alt="' + me.altText + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
77314                     '" class="' + Ext.baseCSSPrefix + 'action-col-icon ' + Ext.baseCSSPrefix + 'action-col-' + String(i) + ' ' +  (item.iconCls || '') + 
77315                     ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope||me.scope||me, arguments) : (me.iconCls || '')) + '"' +
77316                     ((item.tooltip) ? ' data-qtip="' + item.tooltip + '"' : '') + ' />';
77317             }
77318             return v;
77319         };
77320     },
77321
77322     destroy: function() {
77323         delete this.items;
77324         delete this.renderer;
77325         return this.callParent(arguments);
77326     },
77327
77328     
77329     processEvent : function(type, view, cell, recordIndex, cellIndex, e){
77330         var m = e.getTarget().className.match(this.actionIdRe),
77331             item, fn;
77332         if (m && (item = this.items[parseInt(m[1], 10)])) {
77333             if (type == 'click') {
77334                 fn = item.handler;
77335                 if (fn || this.handler) {
77336                     fn.call(item.scope||this.scope||this, view, recordIndex, cellIndex, item, e);
77337                 }
77338             } else if ((type == 'mousedown') && (item.stopSelection !== false)) {
77339                 return false;
77340             }
77341         }
77342         return this.callParent(arguments);
77343     },
77344
77345     cascade: function(fn, scope) {
77346         fn.call(scope||this, this);
77347     },
77348
77349     
77350     getRefItems: function() {
77351         return [];
77352     }
77353 });
77354
77355 Ext.define('Ext.grid.column.Boolean', {
77356     extend: 'Ext.grid.column.Column',
77357     alias: ['widget.booleancolumn'],
77358     alternateClassName: 'Ext.grid.BooleanColumn',
77359
77360     
77361     trueText: 'true',
77362
77363     
77364     falseText: 'false',
77365
77366     
77367     undefinedText: '&#160;',
77368
77369     constructor: function(cfg){
77370         this.callParent(arguments);
77371         var trueText      = this.trueText,
77372             falseText     = this.falseText,
77373             undefinedText = this.undefinedText;
77374
77375         this.renderer = function(value){
77376             if(value === undefined){
77377                 return undefinedText;
77378             }
77379             if(!value || value === 'false'){
77380                 return falseText;
77381             }
77382             return trueText;
77383         };
77384     }
77385 });
77386
77387 Ext.define('Ext.grid.column.Date', {
77388     extend: 'Ext.grid.column.Column',
77389     alias: ['widget.datecolumn'],
77390     requires: ['Ext.Date'],
77391     alternateClassName: 'Ext.grid.DateColumn',
77392
77393     
77394     format : Ext.Date.defaultFormat,
77395
77396     constructor: function(cfg){
77397         this.callParent(arguments);
77398         this.renderer = Ext.util.Format.dateRenderer(this.format);
77399     }
77400 });
77401
77402 Ext.define('Ext.grid.column.Number', {
77403     extend: 'Ext.grid.column.Column',
77404     alias: ['widget.numbercolumn'],
77405     requires: ['Ext.util.Format'],
77406     alternateClassName: 'Ext.grid.NumberColumn',
77407
77408     
77409     format : '0,000.00',
77410     constructor: function(cfg) {
77411         this.callParent(arguments);
77412         this.renderer = Ext.util.Format.numberRenderer(this.format);
77413     }
77414 });
77415
77416 Ext.define('Ext.grid.column.Template', {
77417     extend: 'Ext.grid.column.Column',
77418     alias: ['widget.templatecolumn'],
77419     requires: ['Ext.XTemplate'],
77420     alternateClassName: 'Ext.grid.TemplateColumn',
77421
77422     
77423     constructor: function(cfg){
77424         var me = this,
77425             tpl;
77426             
77427         me.callParent(arguments);
77428         tpl = me.tpl = (!Ext.isPrimitive(me.tpl) && me.tpl.compile) ? me.tpl : Ext.create('Ext.XTemplate', me.tpl);
77429
77430         me.renderer = function(value, p, record) {
77431             var data = Ext.apply({}, record.data, record.getAssociatedData());
77432             return tpl.apply(data);
77433         };
77434     }
77435 });
77436
77437
77438 Ext.define('Ext.grid.feature.Feature', {
77439     extend: 'Ext.util.Observable',
77440     alias: 'feature.feature',
77441     
77442     isFeature: true,
77443     disabled: false,
77444     
77445     
77446     hasFeatureEvent: true,
77447     
77448     
77449     eventPrefix: null,
77450     
77451     
77452     eventSelector: null,
77453     
77454     
77455     view: null,
77456     
77457     
77458     grid: null,
77459     
77460     
77461     collectData: false,
77462         
77463     getFeatureTpl: function() {
77464         return '';
77465     },
77466     
77467     
77468     getFireEventArgs: function(eventName, view, featureTarget) {
77469         return [eventName, view, featureTarget];
77470     },
77471     
77472     
77473     attachEvents: function() {
77474         
77475     },
77476     
77477     getFragmentTpl: function() {
77478         return;
77479     },
77480     
77481     
77482     mutateMetaRowTpl: function(metaRowTplArray) {
77483         
77484     },
77485     
77486     
77487     getMetaRowTplFragments: function() {
77488         return {};
77489     },
77490
77491     getTableFragments: function() {
77492         return {};
77493     },
77494     
77495     
77496     getAdditionalData: function(data, idx, record, orig) {
77497         return {};
77498     },
77499     
77500     
77501     enable: function() {
77502         this.disabled = false;
77503     },
77504     
77505     
77506     disable: function() {
77507         this.disabled = true;
77508     }
77509     
77510 });
77511
77512 Ext.define('Ext.grid.feature.AbstractSummary', {
77513     
77514     
77515    
77516     extend: 'Ext.grid.feature.Feature',
77517     
77518     alias: 'feature.abstractsummary',
77519    
77520     
77521    
77522    
77523     showSummaryRow: true,
77524     
77525     
77526     nestedIdRe: /\{\{id\}([\w\-]*)\}/g,
77527     
77528     
77529     toggleSummaryRow: function(visible){
77530         this.showSummaryRow = !!visible;
77531     },
77532     
77533     
77534     getSummaryFragments: function(){
77535         var fragments = {};
77536         if (this.showSummaryRow) {
77537             Ext.apply(fragments, {
77538                 printSummaryRow: Ext.bind(this.printSummaryRow, this)
77539             });
77540         }
77541         return fragments;
77542     },
77543     
77544     
77545     printSummaryRow: function(index){
77546         var inner = this.view.getTableChunker().metaRowTpl.join('');
77547         
77548         inner = inner.replace('x-grid-row', 'x-grid-row-summary');
77549         inner = inner.replace('{{id}}', '{gridSummaryValue}');
77550         inner = inner.replace(this.nestedIdRe, '{id$1}');  
77551         inner = inner.replace('{[this.embedRowCls()]}', '{rowCls}');
77552         inner = inner.replace('{[this.embedRowAttr()]}', '{rowAttr}');
77553         inner = Ext.create('Ext.XTemplate', inner, {
77554             firstOrLastCls: Ext.view.TableChunker.firstOrLastCls
77555         });
77556         
77557         return inner.applyTemplate({
77558             columns: this.getPrintData(index)
77559         });
77560     },
77561     
77562     
77563     getColumnValue: function(column, data){
77564         var comp = Ext.getCmp(column.id),
77565             value = data[column.dataIndex],
77566             renderer = comp.summaryRenderer || comp.renderer;
77567             
77568         if (renderer) {
77569             value = renderer.call(comp.scope || this, value, data, column.dataIndex);
77570         }
77571         return value;
77572     },
77573     
77574     
77575     getSummary: function(store, type, field, group){
77576         if (type) {
77577             if (Ext.isFunction(type)) {
77578                 return store.aggregate(type, null, group);
77579             }
77580             
77581             switch (type) {
77582                 case 'count':
77583                     return store.count(group);
77584                 case 'min':
77585                     return store.min(field, group);
77586                 case 'max':
77587                     return store.max(field, group);
77588                 case 'sum':
77589                     return store.sum(field, group);
77590                 case 'average':
77591                     return store.average(field, group);
77592                 default:
77593                     return group ? {} : '';
77594                     
77595             }
77596         }
77597     }
77598     
77599 });
77600
77601
77602 Ext.define('Ext.grid.feature.Chunking', {
77603     extend: 'Ext.grid.feature.Feature',
77604     alias: 'feature.chunking',
77605     
77606     chunkSize: 20,
77607     rowHeight: Ext.isIE ? 27 : 26,
77608     visibleChunk: 0,
77609     hasFeatureEvent: false,
77610     attachEvents: function() {
77611         var grid = this.view.up('gridpanel'),
77612             scroller = grid.down('gridscroller[dock=right]');
77613         scroller.el.on('scroll', this.onBodyScroll, this, {buffer: 300});
77614         
77615     },
77616     
77617     onBodyScroll: function(e, t) {
77618         var view = this.view,
77619             top  = t.scrollTop,
77620             nextChunk = Math.floor(top / this.rowHeight / this.chunkSize);
77621         if (nextChunk !== this.visibleChunk) {
77622         
77623             this.visibleChunk = nextChunk;
77624             view.refresh();
77625             view.el.dom.scrollTop = top;
77626             
77627             view.el.dom.scrollTop = top;
77628         }
77629     },
77630     
77631     collectData: function(records, preppedRecords, startIndex, fullWidth, orig) {
77632         var o = {
77633             fullWidth: orig.fullWidth,
77634             chunks: []
77635         },
77636         
77637         
77638         recordCount = orig.rows.length,
77639         start = 0,
77640         i = 0,
77641         visibleChunk = this.visibleChunk,
77642         chunk,
77643         rows,
77644         chunkLength;
77645
77646         for (; start < recordCount; start+=this.chunkSize, i++) {
77647             if (start+this.chunkSize > recordCount) {
77648                 chunkLength = recordCount - start;
77649             } else {
77650                 chunkLength = this.chunkSize;
77651             }
77652             
77653             if (i >= visibleChunk - 1 && i <= visibleChunk + 1) {
77654                 rows = orig.rows.slice(start, start+this.chunkSize);
77655             } else {
77656                 rows = [];
77657             }
77658             o.chunks.push({
77659                 rows: rows,
77660                 fullWidth: fullWidth,
77661                 chunkHeight: chunkLength * this.rowHeight
77662             });
77663         }
77664         
77665         
77666         return o;
77667     },
77668     
77669     getTableFragments: function() {
77670         return {
77671             openTableWrap: function() {
77672                 return '<tpl for="chunks"><div class="' + Ext.baseCSSPrefix + 'grid-chunk" style="height: {chunkHeight}px;">';
77673             },
77674             closeTableWrap: function() {
77675                 return '</div></tpl>';
77676             }
77677         };
77678     }
77679 });
77680
77681
77682 Ext.define('Ext.grid.feature.Grouping', {
77683     extend: 'Ext.grid.feature.Feature',
77684     alias: 'feature.grouping',
77685
77686     eventPrefix: 'group',
77687     eventSelector: '.' + Ext.baseCSSPrefix + 'grid-group-hd',
77688
77689     constructor: function() {
77690         this.collapsedState = {};
77691         this.callParent(arguments);
77692     },
77693     
77694     
77695
77696     
77697
77698     
77699
77700     
77701
77702     
77703
77704     
77705     groupHeaderTpl: 'Group: {name}',
77706
77707     
77708     depthToIndent: 17,
77709
77710     collapsedCls: Ext.baseCSSPrefix + 'grid-group-collapsed',
77711     hdCollapsedCls: Ext.baseCSSPrefix + 'grid-group-hd-collapsed',
77712
77713     
77714     groupByText : 'Group By This Field',
77715     
77716     showGroupsText : 'Show in Groups',
77717
77718     
77719     hideGroupedHeader : false,
77720
77721     
77722     startCollapsed : false,
77723
77724     
77725     enableGroupingMenu : true,
77726
77727     
77728     enableNoGroups : true,
77729     
77730     enable: function() {
77731         var me    = this,
77732             view  = me.view,
77733             store = view.store,
77734             groupToggleMenuItem;
77735             
77736         if (me.lastGroupIndex) {
77737             store.group(me.lastGroupIndex);
77738         }
77739         me.callParent();
77740         groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
77741         groupToggleMenuItem.setChecked(true, true);
77742         view.refresh();
77743     },
77744
77745     disable: function() {
77746         var me    = this,
77747             view  = me.view,
77748             store = view.store,
77749             groupToggleMenuItem,
77750             lastGroup;
77751             
77752         lastGroup = store.groupers.first();
77753         if (lastGroup) {
77754             me.lastGroupIndex = lastGroup.property;
77755             store.groupers.clear();
77756         }
77757         
77758         me.callParent();
77759         groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
77760         groupToggleMenuItem.setChecked(true, true);
77761         groupToggleMenuItem.setChecked(false, true);
77762         view.refresh();
77763     },
77764
77765     getFeatureTpl: function(values, parent, x, xcount) {
77766         var me = this;
77767         
77768         return [
77769             '<tpl if="typeof rows !== \'undefined\'">',
77770                 
77771                 '<tr class="' + Ext.baseCSSPrefix + 'grid-group-hd ' + (me.startCollapsed ? me.hdCollapsedCls : '') + ' {hdCollapsedCls}"><td class="' + Ext.baseCSSPrefix + 'grid-cell" colspan="' + parent.columns.length + '" {[this.indentByDepth(values)]}><div class="' + Ext.baseCSSPrefix + 'grid-cell-inner"><div class="' + Ext.baseCSSPrefix + 'grid-group-title">{collapsed}' + me.groupHeaderTpl + '</div></div></td></tr>',
77772                 
77773                 '<tr id="{viewId}-gp-{name}" class="' + Ext.baseCSSPrefix + 'grid-group-body ' + (me.startCollapsed ? me.collapsedCls : '') + ' {collapsedCls}"><td colspan="' + parent.columns.length + '">{[this.recurse(values)]}</td></tr>',
77774             '</tpl>'
77775         ].join('');
77776     },
77777
77778     getFragmentTpl: function() {
77779         return {
77780             indentByDepth: this.indentByDepth,
77781             depthToIndent: this.depthToIndent
77782         };
77783     },
77784
77785     indentByDepth: function(values) {
77786         var depth = values.depth || 0;
77787         return 'style="padding-left:'+ depth * this.depthToIndent + 'px;"';
77788     },
77789
77790     
77791     
77792     destroy: function() {
77793         var me = this;
77794         
77795         delete me.view;
77796         delete me.prunedHeader;
77797     },
77798
77799     
77800     attachEvents: function() {
77801         var me = this,
77802             view = me.view,
77803             header, headerId, menu, menuItem;
77804
77805         view.on({
77806             scope: me,
77807             groupclick: me.onGroupClick,
77808             rowfocus: me.onRowFocus
77809         });
77810         view.store.on('groupchange', me.onGroupChange, me);
77811
77812         me.pruneGroupedHeader();
77813
77814         if (me.enableGroupingMenu) {
77815             me.injectGroupingMenu();
77816         }
77817
77818         if (me.hideGroupedHeader) {
77819             header = view.headerCt.down('gridcolumn[dataIndex=' + me.getGroupField() + ']');
77820             headerId = header.id;
77821             menu = view.headerCt.getMenu();
77822             menuItem = menu.down('menuitem[headerId='+ headerId +']');
77823             if (menuItem) {
77824                 menuItem.setChecked(false);
77825             }
77826         }
77827     },
77828     
77829     injectGroupingMenu: function() {
77830         var me       = this,
77831             view     = me.view,
77832             headerCt = view.headerCt;
77833         headerCt.showMenuBy = me.showMenuBy;
77834         headerCt.getMenuItems = me.getMenuItems();
77835     },
77836     
77837     showMenuBy: function(t, header) {
77838         var menu = this.getMenu(),
77839             groupMenuItem  = menu.down('#groupMenuItem'),
77840             groupableMth = header.groupable === false ?  'disable' : 'enable';
77841             
77842         groupMenuItem[groupableMth]();
77843         Ext.grid.header.Container.prototype.showMenuBy.apply(this, arguments);
77844     },
77845     
77846     getMenuItems: function() {
77847         var me                 = this,
77848             groupByText        = me.groupByText,
77849             disabled           = me.disabled,
77850             showGroupsText     = me.showGroupsText,
77851             enableNoGroups     = me.enableNoGroups,
77852             groupMenuItemClick = Ext.Function.bind(me.onGroupMenuItemClick, me),
77853             groupToggleMenuItemClick = Ext.Function.bind(me.onGroupToggleMenuItemClick, me)
77854         
77855         
77856         return function() {
77857             var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
77858             o.push('-', {
77859                 itemId: 'groupMenuItem',
77860                 text: groupByText,
77861                 handler: groupMenuItemClick
77862             });
77863             if (enableNoGroups) {
77864                 o.push({
77865                     itemId: 'groupToggleMenuItem',
77866                     text: showGroupsText,
77867                     checked: !disabled,
77868                     checkHandler: groupToggleMenuItemClick
77869                 });
77870             }
77871             return o;
77872         };
77873     },
77874
77875
77876     
77877     onGroupMenuItemClick: function(menuItem, e) {
77878         var menu = menuItem.parentMenu,
77879             hdr  = menu.activeHeader,
77880             view = this.view;
77881
77882         delete this.lastGroupIndex;
77883         this.enable();
77884         view.store.group(hdr.dataIndex);
77885         this.pruneGroupedHeader();
77886         
77887     },
77888
77889     
77890     onGroupToggleMenuItemClick: function(menuItem, checked) {
77891         this[checked ? 'enable' : 'disable']();
77892     },
77893
77894     
77895     pruneGroupedHeader: function() {
77896         var me         = this,
77897             view       = me.view,
77898             store      = view.store,
77899             groupField = me.getGroupField(),
77900             headerCt   = view.headerCt,
77901             header     = headerCt.down('header[dataIndex=' + groupField + ']');
77902
77903         if (header) {
77904             if (me.prunedHeader) {
77905                 me.prunedHeader.show();
77906             }
77907             me.prunedHeader = header;
77908             header.hide();
77909         }
77910     },
77911
77912     getGroupField: function(){
77913         var group = this.view.store.groupers.first();
77914         if (group) {
77915             return group.property;    
77916         }
77917         return ''; 
77918     },
77919
77920     
77921     onRowFocus: function(rowIdx) {
77922         var node    = this.view.getNode(rowIdx),
77923             groupBd = Ext.fly(node).up('.' + this.collapsedCls);
77924
77925         if (groupBd) {
77926             
77927             
77928             this.expand(groupBd);
77929         }
77930     },
77931
77932     
77933     expand: function(groupBd) {
77934         var me = this,
77935             view = me.view,
77936             grid = view.up('gridpanel'),
77937             groupBdDom = Ext.getDom(groupBd);
77938             
77939         me.collapsedState[groupBdDom.id] = false;
77940
77941         groupBd.removeCls(me.collapsedCls);
77942         groupBd.prev().removeCls(me.hdCollapsedCls);
77943
77944         grid.determineScrollbars();
77945         grid.invalidateScroller();
77946         view.fireEvent('groupexpand');
77947     },
77948
77949     
77950     collapse: function(groupBd) {
77951         var me = this,
77952             view = me.view,
77953             grid = view.up('gridpanel'),
77954             groupBdDom = Ext.getDom(groupBd);
77955             
77956         me.collapsedState[groupBdDom.id] = true;
77957
77958         groupBd.addCls(me.collapsedCls);
77959         groupBd.prev().addCls(me.hdCollapsedCls);
77960
77961         grid.determineScrollbars();
77962         grid.invalidateScroller();
77963         view.fireEvent('groupcollapse');
77964     },
77965     
77966     onGroupChange: function(){
77967         this.view.refresh();
77968     },
77969
77970     
77971     onGroupClick: function(view, group, idx, foo, e) {
77972         var me = this,
77973             toggleCls = me.toggleCls,
77974             groupBd = Ext.fly(group.nextSibling, '_grouping');
77975
77976         if (groupBd.hasCls(me.collapsedCls)) {
77977             me.expand(groupBd);
77978         } else {
77979             me.collapse(groupBd);
77980         }
77981     },
77982
77983     
77984     getMetaRowTplFragments: function() {
77985         return {
77986             isRow: this.isRow,
77987             closeRow: this.closeRow
77988         };
77989     },
77990
77991     
77992     
77993     isRow: function() {
77994         return '<tpl if="typeof rows === \'undefined\'">';
77995     },
77996
77997     
77998     
77999     closeRow: function() {
78000         return '</tpl>';
78001     },
78002
78003     
78004     mutateMetaRowTpl: function(metaRowTpl) {
78005         metaRowTpl.unshift('{[this.isRow()]}');
78006         metaRowTpl.push('{[this.closeRow()]}');
78007     },
78008
78009     
78010     
78011     getAdditionalData: function(data, idx, record, orig) {
78012         var view = this.view,
78013             hCt  = view.headerCt,
78014             col  = hCt.items.getAt(0),
78015             o = {},
78016             tdAttrKey = col.id + '-tdAttr';
78017
78018         
78019         o[tdAttrKey] = this.indentByDepth(data) + " " + (orig[tdAttrKey] ? orig[tdAttrKey] : '');
78020         o.collapsed = 'true';
78021         return o;
78022     },
78023
78024     
78025     getGroupRows: function(group, records, preppedRecords, fullWidth) {
78026         var me = this,
78027             children = group.children,
78028             rows = group.rows = [],
78029             view = me.view;
78030         group.viewId = view.id;
78031
78032         Ext.Array.each(records, function(record, idx) {
78033             if (Ext.Array.indexOf(children, record) != -1) {
78034                 rows.push(Ext.apply(preppedRecords[idx], {
78035                     depth: 1
78036                 }));
78037             }
78038         });
78039         delete group.children;
78040         group.fullWidth = fullWidth;
78041         if (me.collapsedState[view.id + '-gp-' + group.name]) {
78042             group.collapsedCls = me.collapsedCls;
78043             group.hdCollapsedCls = me.hdCollapsedCls;
78044         }
78045
78046         return group;
78047     },
78048
78049     
78050     collectData: function(records, preppedRecords, startIndex, fullWidth, o) {
78051         var me    = this,
78052             store = me.view.store,
78053             groups;
78054             
78055         if (!me.disabled && store.isGrouped()) {
78056             groups = store.getGroups();
78057             Ext.Array.each(groups, function(group, idx){
78058                 me.getGroupRows(group, records, preppedRecords, fullWidth);
78059             }, me);
78060             return {
78061                 rows: groups,
78062                 fullWidth: fullWidth
78063             };
78064         }
78065         return o;
78066     },
78067     
78068     
78069     
78070     
78071     
78072     getFireEventArgs: function(type, view, featureTarget) {
78073         var returnArray = [type, view, featureTarget],
78074             groupBd     = Ext.fly(featureTarget.nextSibling, '_grouping'),
78075             groupBdId   = Ext.getDom(groupBd).id,
78076             prefix      = view.id + '-gp-',
78077             groupName   = groupBdId.substr(prefix.length);
78078         
78079         returnArray.push(groupName);
78080         
78081         return returnArray;
78082     }
78083 });
78084
78085
78086 Ext.define('Ext.grid.feature.GroupingSummary', {
78087     
78088     
78089     
78090     extend: 'Ext.grid.feature.Grouping',
78091     
78092     alias: 'feature.groupingsummary',
78093     
78094     mixins: {
78095         summary: 'Ext.grid.feature.AbstractSummary'
78096     },
78097     
78098     
78099
78100      
78101    
78102    getFeatureTpl: function() {
78103         var tpl = this.callParent(arguments);
78104             
78105         if (this.showSummaryRow) {
78106             
78107             tpl = tpl.replace('</tpl>', '');
78108             tpl += '{[this.printSummaryRow(xindex)]}</tpl>';
78109         }
78110         return tpl;
78111     },
78112     
78113     
78114     getFragmentTpl: function() {
78115         var me = this,
78116             fragments = me.callParent();
78117             
78118         Ext.apply(fragments, me.getSummaryFragments());
78119         if (me.showSummaryRow) {
78120             
78121             me.summaryGroups = me.view.store.getGroups();
78122             me.summaryData = me.generateSummaryData();
78123         }
78124         return fragments;
78125     },
78126     
78127     
78128     getPrintData: function(index){
78129         var me = this,
78130             columns = me.view.headerCt.getColumnsForTpl(),
78131             i = 0,
78132             length = columns.length,
78133             data = [],
78134             name = me.summaryGroups[index - 1].name,
78135             active = me.summaryData[name],
78136             column;
78137             
78138         for (; i < length; ++i) {
78139             column = columns[i];
78140             column.gridSummaryValue = this.getColumnValue(column, active);
78141             data.push(column);
78142         }
78143         return data;
78144     },
78145     
78146     
78147     generateSummaryData: function(){
78148         var me = this,
78149             data = {},
78150             remoteData = {},
78151             store = me.view.store,
78152             groupField = this.getGroupField(),
78153             reader = store.proxy.reader,
78154             groups = me.summaryGroups,
78155             columns = me.view.headerCt.getColumnsForTpl(),
78156             i,
78157             length,
78158             fieldData,
78159             root,
78160             key,
78161             comp;
78162             
78163         for (i = 0, length = groups.length; i < length; ++i) {
78164             data[groups[i].name] = {};
78165         }
78166         
78167     
78168         if (me.remoteRoot && reader.rawData) {
78169             
78170             root = reader.root;
78171             reader.root = me.remoteRoot;
78172             reader.buildExtractors(true);
78173             Ext.Array.each(reader.getRoot(reader.rawData), function(value) {
78174                  data[value[groupField]] = value;
78175                  data[value[groupField]]._remote = true;
78176             });
78177             
78178             reader.root = root;
78179             reader.buildExtractors(true);
78180         }
78181         
78182         for (i = 0, length = columns.length; i < length; ++i) {
78183             comp = Ext.getCmp(columns[i].id);
78184             fieldData = me.getSummary(store, comp.summaryType, comp.dataIndex, true);
78185             
78186             for (key in fieldData) {
78187                 if (fieldData.hasOwnProperty(key)) {
78188                     if (!data[key]._remote) {
78189                         data[key][comp.dataIndex] = fieldData[key];
78190                     }
78191                 }
78192             }
78193         }
78194         return data;
78195     }
78196 });
78197
78198
78199 Ext.define('Ext.grid.feature.RowBody', {
78200     extend: 'Ext.grid.feature.Feature',
78201     alias: 'feature.rowbody',
78202     rowBodyHiddenCls: Ext.baseCSSPrefix + 'grid-row-body-hidden',
78203     rowBodyTrCls: Ext.baseCSSPrefix + 'grid-rowbody-tr',
78204     rowBodyTdCls: Ext.baseCSSPrefix + 'grid-cell-rowbody',
78205     rowBodyDivCls: Ext.baseCSSPrefix + 'grid-rowbody',
78206
78207     eventPrefix: 'rowbody',
78208     eventSelector: '.' + Ext.baseCSSPrefix + 'grid-rowbody-tr',
78209     
78210     getRowBody: function(values) {
78211         return [
78212             '<tr class="' + this.rowBodyTrCls + ' {rowBodyCls}">',
78213                 '<td class="' + this.rowBodyTdCls + '" colspan="{rowBodyColspan}">',
78214                     '<div class="' + this.rowBodyDivCls + '">{rowBody}</div>',
78215                 '</td>',
78216             '</tr>'
78217         ].join('');
78218     },
78219     
78220     
78221     getMetaRowTplFragments: function() {
78222         return {
78223             getRowBody: this.getRowBody,
78224             rowBodyTrCls: this.rowBodyTrCls,
78225             rowBodyTdCls: this.rowBodyTdCls,
78226             rowBodyDivCls: this.rowBodyDivCls
78227         };
78228     },
78229
78230     mutateMetaRowTpl: function(metaRowTpl) {
78231         metaRowTpl.push('{[this.getRowBody(values)]}');
78232     },
78233
78234     
78235     getAdditionalData: function(data, idx, record, orig) {
78236         var headerCt = this.view.headerCt,
78237             colspan  = headerCt.getColumnCount();
78238
78239         return {
78240             rowBody: "",
78241             rowBodyCls: this.rowBodyCls,
78242             rowBodyColspan: colspan
78243         };
78244     }
78245 });
78246
78247 Ext.define('Ext.grid.feature.RowWrap', {
78248     extend: 'Ext.grid.feature.Feature',
78249     alias: 'feature.rowwrap',
78250
78251     
78252     hasFeatureEvent: false,
78253     
78254     mutateMetaRowTpl: function(metaRowTpl) {        
78255         
78256         
78257         metaRowTpl[0] = metaRowTpl[0].replace(Ext.baseCSSPrefix + 'grid-row', '');
78258         metaRowTpl[0] = metaRowTpl[0].replace("{[this.embedRowCls()]}", "");
78259         
78260         metaRowTpl.unshift('<table class="' + Ext.baseCSSPrefix + 'grid-table ' + Ext.baseCSSPrefix + 'grid-table-resizer" style="width: {[this.embedFullWidth()]}px;">');
78261         
78262         metaRowTpl.unshift('<tr class="' + Ext.baseCSSPrefix + 'grid-row {[this.embedRowCls()]}"><td colspan="{[this.embedColSpan()]}"><div class="' + Ext.baseCSSPrefix + 'grid-rowwrap-div">');
78263         
78264         
78265         metaRowTpl.push('</table>');
78266         
78267         metaRowTpl.push('</div></td></tr>');
78268     },
78269     
78270     embedColSpan: function() {
78271         return '{colspan}';
78272     },
78273     
78274     embedFullWidth: function() {
78275         return '{fullWidth}';
78276     },
78277     
78278     getAdditionalData: function(data, idx, record, orig) {
78279         var headerCt = this.view.headerCt,
78280             colspan  = headerCt.getColumnCount(),
78281             fullWidth = headerCt.getFullWidth(),
78282             items    = headerCt.query('gridcolumn'),
78283             itemsLn  = items.length,
78284             i = 0,
78285             o = {
78286                 colspan: colspan,
78287                 fullWidth: fullWidth
78288             },
78289             id,
78290             tdClsKey,
78291             colResizerCls;
78292
78293         for (; i < itemsLn; i++) {
78294             id = items[i].id;
78295             tdClsKey = id + '-tdCls';
78296             colResizerCls = Ext.baseCSSPrefix + 'grid-col-resizer-'+id;
78297             
78298             
78299             
78300             o[tdClsKey] = colResizerCls + " " + (orig[tdClsKey] ? orig[tdClsKey] : '');
78301             
78302             o[id+'-tdAttr'] = " style=\"width: " + (items[i].hidden ? 0 : items[i].getDesiredWidth()) + "px;\" ";
78303             if (orig[id+'-tdAttr']) {
78304                 o[id+'-tdAttr'] += orig[id+'-tdAttr'];
78305             }
78306             
78307         }
78308
78309         return o;
78310     },
78311     
78312     getMetaRowTplFragments: function() {
78313         return {
78314             embedFullWidth: this.embedFullWidth,
78315             embedColSpan: this.embedColSpan
78316         };
78317     }
78318     
78319 });
78320
78321 Ext.define('Ext.grid.feature.Summary', {
78322     
78323     
78324     
78325     extend: 'Ext.grid.feature.AbstractSummary',
78326     
78327     alias: 'feature.summary',
78328     
78329     
78330     
78331     
78332     getFragmentTpl: function() {
78333         
78334         this.summaryData = this.generateSummaryData(); 
78335         return this.getSummaryFragments();
78336     },
78337     
78338     
78339     getTableFragments: function(){
78340         if (this.showSummaryRow) {
78341             return {
78342                 closeRows: this.closeRows
78343             };
78344         }
78345     },
78346     
78347     
78348     closeRows: function() {
78349         return '</tpl>{[this.printSummaryRow()]}';
78350     },
78351     
78352     
78353     getPrintData: function(index){
78354         var me = this,
78355             columns = me.view.headerCt.getColumnsForTpl(),
78356             i = 0,
78357             length = columns.length,
78358             data = [],
78359             active = me.summaryData,
78360             column;
78361             
78362         for (; i < length; ++i) {
78363             column = columns[i];
78364             column.gridSummaryValue = this.getColumnValue(column, active);
78365             data.push(column);
78366         }
78367         return data;
78368     },
78369     
78370     
78371     generateSummaryData: function(){
78372         var me = this,
78373             data = {},
78374             store = me.view.store,
78375             columns = me.view.headerCt.getColumnsForTpl(),
78376             i = 0,
78377             length = columns.length,
78378             fieldData,
78379             key,
78380             comp;
78381             
78382         for (i = 0, length = columns.length; i < length; ++i) {
78383             comp = Ext.getCmp(columns[i].id);
78384             data[comp.dataIndex] = me.getSummary(store, comp.summaryType, comp.dataIndex, false);
78385         }
78386         return data;
78387     }
78388 });
78389
78390 Ext.define('Ext.grid.header.DragZone', {
78391     extend: 'Ext.dd.DragZone',
78392     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
78393     maxProxyWidth: 120,
78394
78395     constructor: function(headerCt) {
78396         this.headerCt = headerCt;
78397         this.ddGroup =  this.getDDGroup();
78398         this.callParent([headerCt.el]);
78399         this.proxy.el.addCls(Ext.baseCSSPrefix + 'grid-col-dd');
78400     },
78401
78402     getDDGroup: function() {
78403         return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
78404     },
78405
78406     getDragData: function(e) {
78407         var header = e.getTarget('.'+this.colHeaderCls),
78408             headerCmp;
78409
78410         if (header) {
78411             headerCmp = Ext.getCmp(header.id);
78412             if (!this.headerCt.dragging && headerCmp.draggable && !(headerCmp.isOnLeftEdge(e) || headerCmp.isOnRightEdge(e))) {
78413                 var ddel = document.createElement('div');
78414                 ddel.innerHTML = Ext.getCmp(header.id).text;
78415                 return {
78416                     ddel: ddel,
78417                     header: headerCmp
78418                 };
78419             }
78420         }
78421         return false;
78422     },
78423
78424     onBeforeDrag: function() {
78425         return !(this.headerCt.dragging || this.disabled);
78426     },
78427
78428     onInitDrag: function() {
78429         this.headerCt.dragging = true;
78430         this.callParent(arguments);
78431     },
78432
78433     onDragDrop: function() {
78434         this.headerCt.dragging = false;
78435         this.callParent(arguments);
78436     },
78437
78438     afterRepair: function() {
78439         this.callParent();
78440         this.headerCt.dragging = false;
78441     },
78442
78443     getRepairXY: function() {
78444         return this.dragData.header.el.getXY();
78445     },
78446     
78447     disable: function() {
78448         this.disabled = true;
78449     },
78450     
78451     enable: function() {
78452         this.disabled = false;
78453     }
78454 });
78455
78456
78457 Ext.define('Ext.grid.header.DropZone', {
78458     extend: 'Ext.dd.DropZone',
78459     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
78460     proxyOffsets: [-4, -9],
78461
78462     constructor: function(headerCt){
78463         this.headerCt = headerCt;
78464         this.ddGroup = this.getDDGroup();
78465         this.callParent([headerCt.el]);
78466     },
78467
78468     getDDGroup: function() {
78469         return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
78470     },
78471
78472     getTargetFromEvent : function(e){
78473         return e.getTarget('.' + this.colHeaderCls);
78474     },
78475
78476     getTopIndicator: function() {
78477         if (!this.topIndicator) {
78478             this.topIndicator = Ext.core.DomHelper.append(Ext.getBody(), {
78479                 cls: "col-move-top",
78480                 html: "&#160;"
78481             }, true);
78482         }
78483         return this.topIndicator;
78484     },
78485
78486     getBottomIndicator: function() {
78487         if (!this.bottomIndicator) {
78488             this.bottomIndicator = Ext.core.DomHelper.append(Ext.getBody(), {
78489                 cls: "col-move-bottom",
78490                 html: "&#160;"
78491             }, true);
78492         }
78493         return this.bottomIndicator;
78494     },
78495
78496     getLocation: function(e, t) {
78497         var x      = e.getXY()[0],
78498             region = Ext.fly(t).getRegion(),
78499             pos, header;
78500
78501         if ((region.right - x) <= (region.right - region.left) / 2) {
78502             pos = "after";
78503         } else {
78504             pos = "before";
78505         }
78506         return {
78507             pos: pos,
78508             header: Ext.getCmp(t.id),
78509             node: t
78510         };
78511     },
78512
78513     positionIndicator: function(draggedHeader, node, e){
78514         var location = this.getLocation(e, node),
78515             header = location.header,
78516             pos    = location.pos,
78517             nextHd = draggedHeader.nextSibling('gridcolumn:not([hidden])'),
78518             prevHd = draggedHeader.previousSibling('gridcolumn:not([hidden])'),
78519             region, topIndicator, bottomIndicator, topAnchor, bottomAnchor,
78520             topXY, bottomXY, headerCtEl, minX, maxX;
78521
78522         
78523         if (!header.draggable && header.getIndex() == 0) {
78524             return false;
78525         }
78526
78527         this.lastLocation = location;
78528
78529         if ((draggedHeader !== header) &&
78530             ((pos === "before" && nextHd !== header) ||
78531             (pos === "after" && prevHd !== header)) &&
78532             !header.isDescendantOf(draggedHeader)) {
78533
78534             
78535             
78536             
78537             var allDropZones = Ext.dd.DragDropManager.getRelated(this),
78538                 ln = allDropZones.length,
78539                 i  = 0,
78540                 dropZone;
78541
78542             for (; i < ln; i++) {
78543                 dropZone = allDropZones[i];
78544                 if (dropZone !== this && dropZone.invalidateDrop) {
78545                     dropZone.invalidateDrop();
78546                 }
78547             }
78548
78549
78550             this.valid = true;
78551             topIndicator = this.getTopIndicator();
78552             bottomIndicator = this.getBottomIndicator();
78553             if (pos === 'before') {
78554                 topAnchor = 'tl';
78555                 bottomAnchor = 'bl';
78556             } else {
78557                 topAnchor = 'tr';
78558                 bottomAnchor = 'br';
78559             }
78560             topXY = header.el.getAnchorXY(topAnchor);
78561             bottomXY = header.el.getAnchorXY(bottomAnchor);
78562
78563             
78564             headerCtEl = this.headerCt.el;
78565             minX = headerCtEl.getLeft();
78566             maxX = headerCtEl.getRight();
78567
78568             topXY[0] = Ext.Number.constrain(topXY[0], minX, maxX);
78569             bottomXY[0] = Ext.Number.constrain(bottomXY[0], minX, maxX);
78570
78571             
78572             
78573             topXY[0] -= 4;
78574             topXY[1] -= 9;
78575             bottomXY[0] -= 4;
78576
78577             
78578             topIndicator.setXY(topXY);
78579             bottomIndicator.setXY(bottomXY);
78580             topIndicator.show();
78581             bottomIndicator.show();
78582         
78583         } else {
78584             this.invalidateDrop();
78585         }
78586     },
78587
78588     invalidateDrop: function() {
78589         this.valid = false;
78590         this.hideIndicators();
78591     },
78592
78593     onNodeOver: function(node, dragZone, e, data) {
78594         if (data.header.el.dom !== node) {
78595             this.positionIndicator(data.header, node, e);
78596         }
78597         return this.valid ? this.dropAllowed : this.dropNotAllowed;
78598     },
78599
78600     hideIndicators: function() {
78601         this.getTopIndicator().hide();
78602         this.getBottomIndicator().hide();
78603     },
78604
78605     onNodeOut: function() {
78606         this.hideIndicators();
78607     },
78608
78609     onNodeDrop: function(node, dragZone, e, data) {
78610         if (this.valid) {
78611             this.invalidateDrop();
78612             var hd = data.header,
78613                 lastLocation = this.lastLocation,
78614                 fromCt  = hd.ownerCt,
78615                 fromIdx = fromCt.items.indexOf(hd), 
78616                 toCt    = lastLocation.header.ownerCt,
78617                 toIdx   = toCt.items.indexOf(lastLocation.header),
78618                 headerCt = this.headerCt,
78619                 groupCt,
78620                 scrollerOwner;
78621
78622             if (lastLocation.pos === 'after') {
78623                 toIdx++;
78624             }
78625
78626             
78627             
78628             
78629             if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && toCt.lockedCt) {
78630                 scrollerOwner = fromCt.up('[scrollerOwner]');
78631                 scrollerOwner.lock(hd, toIdx);
78632             } else if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && fromCt.lockedCt) {
78633                 scrollerOwner = fromCt.up('[scrollerOwner]');
78634                 scrollerOwner.unlock(hd, toIdx);
78635             } else {
78636                 
78637                 
78638                 if ((fromCt === toCt) && (toIdx > fromCt.items.indexOf(hd))) {
78639                     toIdx--;
78640                 }
78641
78642                 
78643                 if (fromCt !== toCt) {
78644                     fromCt.suspendLayout = true;
78645                     fromCt.remove(hd, false);
78646                     fromCt.suspendLayout = false;
78647                 }
78648
78649                 
78650                 if (fromCt.isGroupHeader) {
78651                     if (!fromCt.items.getCount()) {
78652                         groupCt = fromCt.ownerCt;
78653                         groupCt.suspendLayout = true;
78654                         groupCt.remove(fromCt, false);
78655                         fromCt.el.dom.parentNode.removeChild(fromCt.el.dom);
78656                         groupCt.suspendLayout = false;
78657                     } else {
78658                         fromCt.minWidth = fromCt.getWidth() - hd.getWidth();
78659                         fromCt.setWidth(fromCt.minWidth);
78660                     }
78661                 }
78662
78663                 
78664                 toCt.suspendLayout = true;
78665                 if (fromCt === toCt) {
78666                     toCt.move(fromIdx, toIdx);
78667                 } else {
78668                     toCt.insert(toIdx, hd);
78669                 }
78670                 toCt.suspendLayout = false;
78671
78672                 
78673                 
78674                 
78675                 if (toCt.isGroupHeader) {
78676                     hd.savedFlex = hd.flex;
78677                     delete hd.flex;
78678                     hd.width = hd.getWidth();
78679                     
78680                     
78681                     toCt.minWidth = toCt.getWidth() + hd.getWidth() - (hd.savedFlex ? 1 : 0);
78682                     toCt.setWidth(toCt.minWidth);
78683                 } else {
78684                     if (hd.savedFlex) {
78685                         hd.flex = hd.savedFlex;
78686                         delete hd.width;
78687                     }
78688                 }
78689
78690
78691                 
78692                 headerCt.purgeCache();
78693                 headerCt.doLayout();
78694                 headerCt.onHeaderMoved(hd, fromIdx, toIdx);
78695                 
78696                 if (!fromCt.items.getCount()) {
78697                     fromCt.destroy();
78698                 }
78699             }
78700         }
78701     }
78702 });
78703
78704
78705
78706 Ext.define('Ext.grid.plugin.Editing', {
78707     alias: 'editing.editing',
78708
78709     requires: [
78710         'Ext.grid.column.Column',
78711         'Ext.util.KeyNav'
78712     ],
78713
78714     mixins: {
78715         observable: 'Ext.util.Observable'
78716     },
78717
78718     
78719     clicksToEdit: 2,
78720
78721     
78722     defaultFieldXType: 'textfield',
78723
78724     
78725     editStyle: '',
78726
78727     constructor: function(config) {
78728         var me = this;
78729         Ext.apply(me, config);
78730
78731         me.addEvents(
78732             
78733             'beforeedit',
78734
78735             
78736             'edit',
78737
78738             
78739             'validateedit'
78740         );
78741         me.mixins.observable.constructor.call(me);
78742         
78743         me.relayEvents(me, ['afteredit'], 'after');
78744     },
78745
78746     
78747     init: function(grid) {
78748         var me = this;
78749
78750         me.grid = grid;
78751         me.view = grid.view;
78752         me.initEvents();
78753         me.initFieldAccessors(me.view.getGridColumns());
78754
78755         grid.relayEvents(me, ['beforeedit', 'edit', 'validateedit']);
78756         
78757         
78758         grid.isEditable = true;
78759         grid.editingPlugin = grid.view.editingPlugin = me;
78760     },
78761
78762     
78763     destroy: function() {
78764         var me = this,
78765             grid = me.grid,
78766             headerCt = grid.headerCt,
78767             events = grid.events;
78768
78769         Ext.destroy(me.keyNav);
78770         me.removeFieldAccessors(grid.getView().getGridColumns());
78771
78772         
78773         me.clearListeners();
78774
78775         delete me.grid.editingPlugin;
78776         delete me.grid.view.editingPlugin;
78777         delete me.grid;
78778         delete me.view;
78779         delete me.editor;
78780         delete me.keyNav;
78781     },
78782
78783     
78784     getEditStyle: function() {
78785         return this.editStyle;
78786     },
78787
78788     
78789     initFieldAccessors: function(column) {
78790         var me = this;
78791
78792         if (Ext.isArray(column)) {
78793             Ext.Array.forEach(column, me.initFieldAccessors, me);
78794             return;
78795         }
78796
78797         
78798         
78799         Ext.applyIf(column, {
78800             getEditor: function(record, defaultField) {
78801                 return me.getColumnField(this, defaultField);
78802             },
78803
78804             setEditor: function(field) {
78805                 me.setColumnField(this, field);
78806             }
78807         });
78808     },
78809
78810     
78811     removeFieldAccessors: function(column) {
78812         var me = this;
78813
78814         if (Ext.isArray(column)) {
78815             Ext.Array.forEach(column, me.removeFieldAccessors, me);
78816             return;
78817         }
78818
78819         delete column.getEditor;
78820         delete column.setEditor;
78821     },
78822
78823     
78824     
78825     getColumnField: function(columnHeader, defaultField) {
78826         var field = columnHeader.field;
78827
78828         if (!field && columnHeader.editor) {
78829             field = columnHeader.editor;
78830             delete columnHeader.editor;
78831         }
78832
78833         if (!field && defaultField) {
78834             field = defaultField;
78835         }
78836
78837         if (field) {
78838             if (Ext.isString(field)) {
78839                 field = { xtype: field };
78840             }
78841             if (Ext.isObject(field) && !field.isFormField) {
78842                 field = Ext.ComponentManager.create(field, this.defaultFieldXType);
78843                 columnHeader.field = field;
78844             }
78845
78846             Ext.apply(field, {
78847                 name: columnHeader.dataIndex
78848             });
78849
78850             return field;
78851         }
78852     },
78853
78854     
78855     
78856     setColumnField: function(column, field) {
78857         if (Ext.isObject(field) && !field.isFormField) {
78858             field = Ext.ComponentManager.create(field, this.defaultFieldXType);
78859         }
78860         column.field = field;
78861     },
78862
78863     
78864     initEvents: function() {
78865         var me = this;
78866         me.initEditTriggers();
78867         me.initCancelTriggers();
78868     },
78869
78870     
78871     initCancelTriggers: Ext.emptyFn,
78872
78873     
78874     initEditTriggers: function() {
78875         var me = this,
78876             view = me.view,
78877             clickEvent = me.clicksToEdit === 1 ? 'click' : 'dblclick';
78878
78879         
78880         me.mon(view, 'cell' + clickEvent, me.startEditByClick, me);
78881         view.on('render', function() {
78882             me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
78883                 enter: me.onEnterKey,
78884                 esc: me.onEscKey,
78885                 scope: me
78886             });
78887         }, me, { single: true });
78888     },
78889
78890     
78891     onEnterKey: function(e) {
78892         var me = this,
78893             grid = me.grid,
78894             selModel = grid.getSelectionModel(),
78895             record,
78896             columnHeader = grid.headerCt.getHeaderAtIndex(0);
78897
78898         
78899         
78900         if (selModel.getCurrentPosition) {
78901             pos = selModel.getCurrentPosition();
78902             record = grid.store.getAt(pos.row);
78903             columnHeader = grid.headerCt.getHeaderAtIndex(pos.column);
78904         }
78905         
78906         else {
78907             record = selModel.getLastSelected();
78908         }
78909         me.startEdit(record, columnHeader);
78910     },
78911
78912     
78913     onEscKey: function(e) {
78914         this.cancelEdit();
78915     },
78916
78917     
78918     startEditByClick: function(view, cell, colIdx, record, row, rowIdx, e) {
78919         this.startEdit(record, view.getHeaderAtIndex(colIdx));
78920     },
78921
78922     
78923     beforeEdit: Ext.emptyFn,
78924
78925     
78926     startEdit: function(record, columnHeader) {
78927         var me = this,
78928             context = me.getEditingContext(record, columnHeader);
78929
78930         if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
78931             return false;
78932         }
78933
78934         me.context = context;
78935         me.editing = true;
78936     },
78937
78938     
78939     getEditingContext: function(record, columnHeader) {
78940         var me = this,
78941             grid = me.grid,
78942             store = grid.store,
78943             rowIdx,
78944             colIdx,
78945             view = grid.getView(),
78946             value;
78947
78948         
78949         if (Ext.isNumber(record)) {
78950             rowIdx = record;
78951             record = store.getAt(rowIdx);
78952         } else {
78953             rowIdx = store.indexOf(record);
78954         }
78955         if (Ext.isNumber(columnHeader)) {
78956             colIdx = columnHeader;
78957             columnHeader = grid.headerCt.getHeaderAtIndex(colIdx);
78958         } else {
78959             colIdx = columnHeader.getIndex();
78960         }
78961
78962         value = record.get(columnHeader.dataIndex);
78963         return {
78964             grid: grid,
78965             record: record,
78966             field: columnHeader.dataIndex,
78967             value: value,
78968             row: view.getNode(rowIdx),
78969             column: columnHeader,
78970             rowIdx: rowIdx,
78971             colIdx: colIdx
78972         };
78973     },
78974
78975     
78976     cancelEdit: function() {
78977         this.editing = false;
78978     },
78979
78980     
78981     completeEdit: function() {
78982         var me = this;
78983
78984         if (me.editing && me.validateEdit()) {
78985             me.fireEvent('edit', me.context);
78986         }
78987
78988         delete me.context;
78989         me.editing = false;
78990     },
78991
78992     
78993     validateEdit: function() {
78994         var me = this,
78995             context = me.context;
78996
78997         return me.fireEvent('validateedit', me, context) !== false && !context.cancel;
78998     }
78999 });
79000
79001 Ext.define('Ext.grid.plugin.CellEditing', {
79002     alias: 'plugin.cellediting',
79003     extend: 'Ext.grid.plugin.Editing',
79004     requires: ['Ext.grid.CellEditor'],
79005
79006     constructor: function() {
79007         
79008         
79009         
79010         this.callParent(arguments);
79011         this.editors = Ext.create('Ext.util.MixedCollection', false, function(editor) {
79012             return editor.editorId;
79013         });
79014     },
79015
79016     
79017     destroy: function() {
79018         var me = this;
79019         me.editors.each(Ext.destroy, Ext);
79020         me.editors.clear();
79021         me.callParent(arguments);
79022     },
79023
79024     
79025     
79026     initCancelTriggers: function() {
79027         var me   = this;
79028             grid = me.grid,
79029             view   = grid.view;
79030
79031         me.mon(view, {
79032             mousewheel: {
79033                 element: 'el',
79034                 fn: me.cancelEdit,
79035                 scope: me
79036             }
79037         });
79038         me.mon(grid, {
79039             columnresize: me.cancelEdit,
79040             columnmove: me.cancelEdit,
79041             scope: me
79042         });
79043     },
79044
79045     
79046     startEdit: function(record, columnHeader) {
79047         var me = this,
79048             ed   = me.getEditor(record, columnHeader),
79049             value = record.get(columnHeader.dataIndex),
79050             context = me.getEditingContext(record, columnHeader);
79051
79052         record = context.record;
79053         columnHeader = context.column;
79054
79055         
79056         
79057         me.completeEdit();
79058
79059         
79060         if (columnHeader && !columnHeader.getEditor(record)) {
79061             return false;
79062         }
79063
79064         if (ed) {
79065             context.originalValue = context.value = value;
79066             if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
79067                 return false;
79068             }
79069
79070             me.context = context;
79071             me.setActiveEditor(ed);
79072             me.setActiveRecord(record);
79073             me.setActiveColumn(columnHeader);
79074
79075             
79076             Ext.defer(ed.startEdit, 15, ed, [me.getCell(record, columnHeader), value]);
79077         } else {
79078             
79079             
79080             
79081             
79082             me.grid.getView().el.focus((Ext.isWebKit || Ext.isIE) ? 10 : false);
79083         }
79084     },
79085
79086     completeEdit: function() {
79087         var activeEd = this.getActiveEditor();
79088         if (activeEd) {
79089             activeEd.completeEdit();
79090         }
79091     },
79092
79093     
79094     setActiveEditor: function(ed) {
79095         this.activeEditor = ed;
79096     },
79097
79098     getActiveEditor: function() {
79099         return this.activeEditor;
79100     },
79101
79102     setActiveColumn: function(column) {
79103         this.activeColumn = column;
79104     },
79105
79106     getActiveColumn: function() {
79107         return this.activeColumn;
79108     },
79109
79110     setActiveRecord: function(record) {
79111         this.activeRecord = record;
79112     },
79113
79114     getActiveRecord: function() {
79115         return this.activeRecord;
79116     },
79117
79118     getEditor: function(record, column) {
79119         var editors = this.editors,
79120             editorId = column.itemId || column.id,
79121             editor = editors.getByKey(editorId);
79122
79123         if (editor) {
79124             return editor;
79125         } else {
79126             editor = column.getEditor(record);
79127             if (!editor) {
79128                 return false;
79129             }
79130
79131             
79132             if (!(editor instanceof Ext.grid.CellEditor)) {
79133                 editor = Ext.create('Ext.grid.CellEditor', {
79134                     editorId: editorId,
79135                     field: editor
79136                 });
79137             }
79138             editor.parentEl = this.grid.getEditorParent();
79139             
79140             editor.on({
79141                 scope: this,
79142                 specialkey: this.onSpecialKey,
79143                 complete: this.onEditComplete,
79144                 canceledit: this.cancelEdit
79145             });
79146             editors.add(editor);
79147             return editor;
79148         }
79149     },
79150
79151     
79152     getCell: function(record, column) {
79153         return this.grid.getView().getCell(record, column);
79154     },
79155
79156     onSpecialKey: function(ed, field, e) {
79157         var grid = this.grid,
79158             sm;
79159         if (e.getKey() === e.TAB) {
79160             e.stopEvent();
79161             sm = grid.getSelectionModel();
79162             if (sm.onEditorTab) {
79163                 sm.onEditorTab(this, e);
79164             }
79165         }
79166     },
79167
79168     onEditComplete : function(ed, value, startValue) {
79169         var me = this,
79170             grid = me.grid,
79171             sm = grid.getSelectionModel(),
79172             dataIndex = me.getActiveColumn().dataIndex;
79173
79174         me.setActiveEditor(null);
79175         me.setActiveColumn(null);
79176         me.setActiveRecord(null);
79177         delete sm.wasEditing;
79178
79179         if (!me.validateEdit()) {
79180             return;
79181         }
79182         me.context.record.set(dataIndex, value);
79183         me.fireEvent('edit', me, me.context);
79184     },
79185
79186     
79187     cancelEdit: function() {
79188         var me = this,
79189             activeEd = me.getActiveEditor(),
79190             viewEl = me.grid.getView().el;
79191
79192         me.setActiveEditor(null);
79193         me.setActiveColumn(null);
79194         me.setActiveRecord(null);
79195         if (activeEd) {
79196             activeEd.cancelEdit();
79197             viewEl.focus();
79198         }
79199     },
79200
79201     
79202     startEditByPosition: function(position) {
79203         var me = this,
79204             grid = me.grid,
79205             sm = grid.getSelectionModel(),
79206             editRecord = grid.store.getAt(position.row),
79207             editColumnHeader = grid.headerCt.getHeaderAtIndex(position.column);
79208
79209         if (sm.selectByPosition) {
79210             sm.selectByPosition(position);
79211         }
79212         me.startEdit(editRecord, editColumnHeader);
79213     }
79214 });
79215
79216 Ext.define('Ext.grid.plugin.DragDrop', {
79217     extend: 'Ext.AbstractPlugin',
79218     alias: 'plugin.gridviewdragdrop',
79219
79220     uses: [
79221         'Ext.view.DragZone',
79222         'Ext.grid.ViewDropZone'
79223     ],
79224
79225     
79226
79227     
79228
79229     dragText : '{0} selected row{1}',
79230
79231     
79232     ddGroup : "GridDD",
79233
79234     
79235
79236     
79237
79238     
79239     enableDrop: true,
79240
79241     
79242     enableDrag: true,
79243
79244     init : function(view) {
79245         view.on('render', this.onViewRender, this, {single: true});
79246     },
79247
79248     
79249     destroy: function() {
79250         Ext.destroy(this.dragZone, this.dropZone);
79251     },
79252
79253     onViewRender : function(view) {
79254         var me = this;
79255
79256         if (me.enableDrag) {
79257             me.dragZone = Ext.create('Ext.view.DragZone', {
79258                 view: view,
79259                 ddGroup: me.dragGroup || me.ddGroup,
79260                 dragText: me.dragText
79261             });
79262         }
79263
79264         if (me.enableDrop) {
79265             me.dropZone = Ext.create('Ext.grid.ViewDropZone', {
79266                 view: view,
79267                 ddGroup: me.dropGroup || me.ddGroup
79268             });
79269         }
79270     }
79271 });
79272
79273 Ext.define('Ext.grid.plugin.HeaderReorderer', {
79274     extend: 'Ext.util.Observable',
79275     requires: ['Ext.grid.header.DragZone', 'Ext.grid.header.DropZone'],
79276     alias: 'plugin.gridheaderreorderer',
79277
79278     init: function(headerCt) {
79279         this.headerCt = headerCt;
79280         headerCt.on('render', this.onHeaderCtRender, this);
79281     },
79282
79283     
79284     destroy: function() {
79285         Ext.destroy(this.dragZone, this.dropZone);
79286     },
79287
79288     onHeaderCtRender: function() {
79289         this.dragZone = Ext.create('Ext.grid.header.DragZone', this.headerCt);
79290         this.dropZone = Ext.create('Ext.grid.header.DropZone', this.headerCt);
79291         if (this.disabled) {
79292             this.dragZone.disable();
79293         }
79294     },
79295     
79296     enable: function() {
79297         this.disabled = false;
79298         if (this.dragZone) {
79299             this.dragZone.enable();
79300         }
79301     },
79302     
79303     disable: function() {
79304         this.disabled = true;
79305         if (this.dragZone) {
79306             this.dragZone.disable();
79307         }
79308     }
79309 });
79310
79311 Ext.define('Ext.grid.plugin.HeaderResizer', {
79312     extend: 'Ext.util.Observable',
79313     requires: ['Ext.dd.DragTracker', 'Ext.util.Region'],
79314     alias: 'plugin.gridheaderresizer',
79315     
79316     disabled: false,
79317
79318     
79319     configs: {
79320         dynamic: true
79321     },
79322
79323     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
79324
79325     minColWidth: 40,
79326     maxColWidth: 1000,
79327     wResizeCursor: 'col-resize',
79328     eResizeCursor: 'col-resize',
79329     
79330     
79331     
79332     
79333
79334     init: function(headerCt) {
79335         this.headerCt = headerCt;
79336         headerCt.on('render', this.afterHeaderRender, this, {single: true});
79337     },
79338
79339     
79340     destroy: function() {
79341         if (this.tracker) {
79342             this.tracker.destroy();
79343         }
79344     },
79345
79346     afterHeaderRender: function() {
79347         var headerCt = this.headerCt,
79348             el = headerCt.el;
79349
79350         headerCt.mon(el, 'mousemove', this.onHeaderCtMouseMove, this);
79351
79352         this.tracker = Ext.create('Ext.dd.DragTracker', {
79353             disabled: this.disabled,
79354             onBeforeStart: Ext.Function.bind(this.onBeforeStart, this),
79355             onStart: Ext.Function.bind(this.onStart, this),
79356             onDrag: Ext.Function.bind(this.onDrag, this),
79357             onEnd: Ext.Function.bind(this.onEnd, this),
79358             tolerance: 3,
79359             autoStart: 300,
79360             el: el
79361         });
79362     },
79363
79364     
79365     
79366     
79367     onHeaderCtMouseMove: function(e, t) {
79368         if (this.headerCt.dragging) {
79369             if (this.activeHd) {
79370                 this.activeHd.el.dom.style.cursor = '';
79371                 delete this.activeHd;
79372             }
79373         } else {
79374             var headerEl = e.getTarget('.' + this.colHeaderCls, 3, true),
79375                 overHeader, resizeHeader;
79376
79377             if (headerEl){
79378                 overHeader = Ext.getCmp(headerEl.id);
79379
79380                 
79381                 if (overHeader.isOnLeftEdge(e)) {
79382                     resizeHeader = overHeader.previousNode('gridcolumn:not([hidden]):not([isGroupHeader])');
79383                 }
79384                 
79385                 else if (overHeader.isOnRightEdge(e)) {
79386                     resizeHeader = overHeader;
79387                 }
79388                 
79389                 else {
79390                     resizeHeader = null;
79391                 }
79392
79393                 
79394                 if (resizeHeader) {
79395                     
79396                     
79397                     
79398                     if (resizeHeader.isGroupHeader) {
79399                         resizeHeader = resizeHeader.getVisibleGridColumns();
79400                         resizeHeader = resizeHeader[resizeHeader.length - 1];
79401                     }
79402
79403                     if (resizeHeader && !resizeHeader.fixed) {
79404                         this.activeHd = resizeHeader;
79405                         overHeader.el.dom.style.cursor = this.eResizeCursor;
79406                     }
79407                 
79408                 } else {
79409                     overHeader.el.dom.style.cursor = '';
79410                     delete this.activeHd;
79411                 }
79412             }
79413         }
79414     },
79415
79416     
79417     onBeforeStart : function(e){
79418         var t = e.getTarget();
79419         
79420         this.dragHd = this.activeHd;
79421
79422         if (!!this.dragHd && !Ext.fly(t).hasCls('x-column-header-trigger') && !this.headerCt.dragging) {
79423             
79424             this.tracker.constrainTo = this.getConstrainRegion();
79425             return true;
79426         } else {
79427             this.headerCt.dragging = false;
79428             return false;
79429         }
79430     },
79431
79432     
79433     getConstrainRegion: function() {
79434         var dragHdEl = this.dragHd.el,
79435             region   = Ext.util.Region.getRegion(dragHdEl);
79436
79437         return region.adjust(
79438             0,
79439             this.maxColWidth - dragHdEl.getWidth(),
79440             0,
79441             this.minColWidth
79442         );
79443     },
79444
79445     
79446     
79447     onStart: function(e){
79448         var me       = this,
79449             dragHd   = me.dragHd,
79450             dragHdEl = dragHd.el,
79451             width    = dragHdEl.getWidth(),
79452             headerCt = me.headerCt,
79453             t        = e.getTarget();
79454
79455         if (me.dragHd && !Ext.fly(t).hasCls('x-column-header-trigger')) {
79456             headerCt.dragging = true;
79457         }
79458
79459         me.origWidth = width;
79460
79461         
79462         if (!me.dynamic) {
79463             var xy           = dragHdEl.getXY(),
79464                 gridSection  = headerCt.up('[scrollerOwner]'),
79465                 dragHct      = me.dragHd.up(':not([isGroupHeader])'),
79466                 firstSection = dragHct.up(),
79467                 lhsMarker    = gridSection.getLhsMarker(),
79468                 rhsMarker    = gridSection.getRhsMarker(),
79469                 el           = rhsMarker.parent(),
79470                 offsetLeft   = el.getLeft(true),
79471                 offsetTop    = el.getTop(true),
79472                 topLeft      = el.translatePoints(xy),
79473                 markerHeight = firstSection.body.getHeight() + headerCt.getHeight(),
79474                 top = topLeft.top - offsetTop;
79475
79476             lhsMarker.setTop(top);
79477             rhsMarker.setTop(top);
79478             lhsMarker.setHeight(markerHeight);
79479             rhsMarker.setHeight(markerHeight);
79480             lhsMarker.setLeft(topLeft.left - offsetLeft);
79481             rhsMarker.setLeft(topLeft.left + width - offsetLeft);
79482         }
79483     },
79484
79485     
79486     onDrag: function(e){
79487         if (!this.dynamic) {
79488             var xy          = this.tracker.getXY('point'),
79489                 gridSection = this.headerCt.up('[scrollerOwner]'),
79490                 rhsMarker   = gridSection.getRhsMarker(),
79491                 el          = rhsMarker.parent(),
79492                 topLeft     = el.translatePoints(xy),
79493                 offsetLeft  = el.getLeft(true);
79494
79495             rhsMarker.setLeft(topLeft.left - offsetLeft);
79496         
79497         } else {
79498             this.doResize();
79499         }
79500     },
79501
79502     onEnd: function(e){
79503         this.headerCt.dragging = false;
79504         if (this.dragHd) {
79505             if (!this.dynamic) {
79506                 var dragHd      = this.dragHd,
79507                     gridSection = this.headerCt.up('[scrollerOwner]'),
79508                     lhsMarker   = gridSection.getLhsMarker(),
79509                     rhsMarker   = gridSection.getRhsMarker(),
79510                     currWidth   = dragHd.getWidth(),
79511                     offset      = this.tracker.getOffset('point'),
79512                     offscreen   = -9999;
79513
79514                 
79515                 lhsMarker.setLeft(offscreen);
79516                 rhsMarker.setLeft(offscreen);
79517             }
79518             this.doResize();
79519         }
79520     },
79521
79522     doResize: function() {
79523         if (this.dragHd) {
79524             var dragHd = this.dragHd,
79525                 nextHd,
79526                 offset = this.tracker.getOffset('point');
79527
79528             
79529             if (dragHd.flex) {
79530                 delete dragHd.flex;
79531             }
79532
79533             
79534             
79535             if (this.headerCt.forceFit) {
79536                 nextHd = dragHd.nextNode('gridcolumn:not([hidden]):not([isGroupHeader])');
79537                 if (nextHd) {
79538                     this.headerCt.componentLayout.layoutBusy = true;
79539                 }
79540             }
79541
79542             
79543             
79544             dragHd.minWidth = this.origWidth + offset[0];
79545             dragHd.setWidth(dragHd.minWidth);
79546
79547             
79548             
79549             if (nextHd) {
79550                 delete nextHd.flex;
79551                 nextHd.setWidth(nextHd.getWidth() - offset[0]);
79552                 this.headerCt.componentLayout.layoutBusy = false;
79553                 this.headerCt.doComponentLayout();
79554             }
79555         }
79556     },
79557     
79558     disable: function() {
79559         this.disabled = true;
79560         if (this.tracker) {
79561             this.tracker.disable();
79562         }
79563     },
79564     
79565     enable: function() {
79566         this.disabled = false;
79567         if (this.tracker) {
79568             this.tracker.enable();
79569         }
79570     }
79571 });
79572
79573 Ext.define('Ext.grid.plugin.RowEditing', {
79574     extend: 'Ext.grid.plugin.Editing',
79575     alias: 'plugin.rowediting',
79576
79577     requires: [
79578         'Ext.grid.RowEditor'
79579     ],
79580
79581     editStyle: 'row',
79582
79583     
79584     autoCancel: true,
79585
79586     
79587
79588     
79589     errorSummary: true,
79590
79591     
79592     
79593     
79594
79595     constructor: function() {
79596         var me = this;
79597         me.callParent(arguments);
79598
79599         if (!me.clicksToMoveEditor) {
79600             me.clicksToMoveEditor = me.clicksToEdit;
79601         }
79602
79603         me.autoCancel = !!me.autoCancel;
79604     },
79605
79606     
79607     destroy: function() {
79608         var me = this;
79609         Ext.destroy(me.editor);
79610         me.callParent(arguments);
79611     },
79612
79613     
79614     startEdit: function(record, columnHeader) {
79615         var me = this,
79616             editor = me.getEditor();
79617
79618         if (me.callParent(arguments) === false) {
79619             return false;
79620         }
79621
79622         
79623         if (editor.beforeEdit() !== false) {
79624             editor.startEdit(me.context.record, me.context.column);
79625         }
79626     },
79627
79628     
79629     cancelEdit: function() {
79630         var me = this;
79631
79632         if (me.editing) {
79633             me.getEditor().cancelEdit();
79634             me.callParent(arguments);
79635         }
79636     },
79637
79638     
79639     completeEdit: function() {
79640         var me = this;
79641
79642         if (me.editing && me.validateEdit()) {
79643             me.editing = false;
79644             me.fireEvent('edit', me.context);
79645         }
79646     },
79647
79648     
79649     validateEdit: function() {
79650         var me = this;
79651         return me.callParent(arguments) && me.getEditor().completeEdit();
79652     },
79653
79654     
79655     getEditor: function() {
79656         var me = this;
79657
79658         if (!me.editor) {
79659             me.editor = me.initEditor();
79660         }
79661         return me.editor;
79662     },
79663
79664     
79665     initEditor: function() {
79666         var me = this,
79667             grid = me.grid,
79668             view = me.view,
79669             headerCt = grid.headerCt;
79670
79671         return Ext.create('Ext.grid.RowEditor', {
79672             autoCancel: me.autoCancel,
79673             errorSummary: me.errorSummary,
79674             fields: headerCt.getGridColumns(),
79675             hidden: true,
79676
79677             
79678             editingPlugin: me,
79679             renderTo: view.el
79680         });
79681     },
79682
79683     
79684     initEditTriggers: function() {
79685         var me = this,
79686             grid = me.grid,
79687             view = me.view,
79688             headerCt = grid.headerCt,
79689             moveEditorEvent = me.clicksToMoveEditor === 1 ? 'click' : 'dblclick';
79690
79691         me.callParent(arguments);
79692
79693         if (me.clicksToMoveEditor !== me.clicksToEdit) {
79694             me.mon(view, 'cell' + moveEditorEvent, me.moveEditorByClick, me);
79695         }
79696
79697         view.on('render', function() {
79698             
79699             me.mon(headerCt, {
79700                 add: me.onColumnAdd,
79701                 remove: me.onColumnRemove,
79702                 columnresize: me.onColumnResize,
79703                 columnhide: me.onColumnHide,
79704                 columnshow: me.onColumnShow,
79705                 columnmove: me.onColumnMove,
79706                 scope: me
79707             });
79708         }, me, { single: true });
79709     },
79710
79711     startEditByClick: function() {
79712         var me = this;
79713         if (!me.editing || me.clicksToMoveEditor === me.clicksToEdit) {
79714             me.callParent(arguments);
79715         }
79716     },
79717
79718     moveEditorByClick: function() {
79719         var me = this;
79720         if (me.editing) {
79721             me.superclass.startEditByClick.apply(me, arguments);
79722         }
79723     },
79724
79725     
79726     onColumnAdd: function(ct, column) {
79727         var me = this,
79728             editor = me.getEditor();
79729
79730         me.initFieldAccessors(column);
79731         if (editor && editor.onColumnAdd) {
79732             editor.onColumnAdd(column);
79733         }
79734     },
79735
79736     
79737     onColumnRemove: function(ct, column) {
79738         var me = this,
79739             editor = me.getEditor();
79740
79741         if (editor && editor.onColumnRemove) {
79742             editor.onColumnRemove(column);
79743         }
79744         me.removeFieldAccessors(column);
79745     },
79746
79747     
79748     onColumnResize: function(ct, column, width) {
79749         var me = this,
79750             editor = me.getEditor();
79751
79752         if (editor && editor.onColumnResize) {
79753             editor.onColumnResize(column, width);
79754         }
79755     },
79756
79757     
79758     onColumnHide: function(ct, column) {
79759         var me = this,
79760             editor = me.getEditor();
79761
79762         if (editor && editor.onColumnHide) {
79763             editor.onColumnHide(column);
79764         }
79765     },
79766
79767     
79768     onColumnShow: function(ct, column) {
79769         var me = this,
79770             editor = me.getEditor();
79771
79772         if (editor && editor.onColumnShow) {
79773             editor.onColumnShow(column);
79774         }
79775     },
79776
79777     
79778     onColumnMove: function(ct, column, fromIdx, toIdx) {
79779         var me = this,
79780             editor = me.getEditor();
79781
79782         if (editor && editor.onColumnMove) {
79783             editor.onColumnMove(column, fromIdx, toIdx);
79784         }
79785     },
79786
79787     
79788     setColumnField: function(column, field) {
79789         var me = this;
79790         me.callParent(arguments);
79791         me.getEditor().setField(column.field, column);
79792     }
79793 });
79794
79795 Ext.define('Ext.grid.property.Grid', {
79796
79797     extend: 'Ext.grid.Panel',
79798
79799     alternateClassName: 'Ext.grid.PropertyGrid',
79800
79801     uses: [
79802        'Ext.grid.plugin.CellEditing',
79803        'Ext.grid.property.Store',
79804        'Ext.grid.property.HeaderContainer',
79805        'Ext.XTemplate',
79806        'Ext.grid.CellEditor',
79807        'Ext.form.field.Date',
79808        'Ext.form.field.Text',
79809        'Ext.form.field.Number'
79810     ],
79811
79812    
79813
79814     
79815
79816     
79817
79818     
79819
79820     
79821
79822     
79823     valueField: 'value',
79824
79825     
79826     nameField: 'name',
79827
79828     
79829     enableColumnMove: false,
79830     columnLines: true,
79831     stripeRows: false,
79832     trackMouseOver: false,
79833     clicksToEdit: 1,
79834     enableHdMenu: false,
79835
79836     
79837     initComponent : function(){
79838         var me = this;
79839
79840         me.addCls(Ext.baseCSSPrefix + 'property-grid');
79841         me.plugins = me.plugins || [];
79842
79843         
79844         me.plugins.push(Ext.create('Ext.grid.plugin.CellEditing', {
79845             clicksToEdit: me.clicksToEdit,
79846
79847             
79848             startEdit: function(record, column) {
79849                 
79850                 Ext.grid.plugin.CellEditing.prototype.startEdit.call(this, record, me.headerCt.child('#' + me.valueField));
79851             }
79852         }));
79853
79854         me.selModel = {
79855             selType: 'cellmodel',
79856             onCellSelect: function(position) {
79857                 if (position.column != 1) {
79858                     position.column = 1;
79859                     Ext.selection.CellModel.prototype.onCellSelect.call(this, position);
79860                 }
79861             }
79862         };
79863         me.customRenderers = me.customRenderers || {};
79864         me.customEditors = me.customEditors || {};
79865
79866         
79867         if (!me.store) {
79868             me.propStore = me.store = Ext.create('Ext.grid.property.Store', me, me.source);
79869         }
79870
79871         me.store.sort('name', 'ASC');
79872         me.columns = Ext.create('Ext.grid.property.HeaderContainer', me, me.store);
79873
79874         me.addEvents(
79875             
79876             'beforepropertychange',
79877             
79878             'propertychange'
79879         );
79880         me.callParent();
79881
79882         
79883         me.getView().walkCells = this.walkCells;
79884
79885         
79886         me.editors = {
79887             'date'    : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Date',   {selectOnFocus: true})}),
79888             'string'  : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Text',   {selectOnFocus: true})}),
79889             'number'  : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Number', {selectOnFocus: true})}),
79890             'boolean' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.ComboBox', {
79891                 editable: false,
79892                 store: [[ true, me.headerCt.trueText ], [false, me.headerCt.falseText ]]
79893             })})
79894         };
79895
79896         
79897         this.store.on('update', me.onUpdate, me);
79898     },
79899
79900     
79901     onUpdate : function(store, record, operation) {
79902         var me = this,
79903             v, oldValue;
79904
79905         if (operation == Ext.data.Model.EDIT) {
79906             v = record.get(me.valueField);
79907             oldValue = record.modified.value;
79908             if (me.fireEvent('beforepropertychange', me.source, record.id, v, oldValue) !== false) {
79909                 if (me.source) {
79910                     me.source[record.id] = v;
79911                 }
79912                 record.commit();
79913                 me.fireEvent('propertychange', me.source, record.id, v, oldValue);
79914             } else {
79915                 record.reject();
79916             }
79917         }
79918     },
79919
79920     
79921     walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
79922         if (direction == 'left') {
79923             direction = 'up';
79924         } else if (direction == 'right') {
79925             direction = 'down';
79926         }
79927         var pos = Ext.view.Table.prototype.walkCells.call(this, pos, direction, e, preventWrap, verifierFn, scope);
79928         if (!pos.column) {
79929             pos.column = 1;
79930         }
79931         return pos;
79932     },
79933
79934     
79935     
79936     getCellEditor : function(record, column) {
79937         var me = this,
79938             propName = record.get(me.nameField), 
79939             val = record.get(me.valueField),
79940             editor = me.customEditors[propName];
79941
79942         
79943         
79944         if (editor) {
79945             if (!(editor instanceof Ext.grid.CellEditor)) {
79946                 if (!(editor instanceof Ext.form.field.Base)) {
79947                     editor = Ext.ComponentManager.create(editor, 'textfield');
79948                 }
79949                 editor = me.customEditors[propName] = Ext.create('Ext.grid.CellEditor', { field: editor });
79950             }
79951         } else if (Ext.isDate(val)) {
79952             editor = me.editors.date;
79953         } else if (Ext.isNumber(val)) {
79954             editor = me.editors.number;
79955         } else if (Ext.isBoolean(val)) {
79956             editor = me.editors['boolean'];
79957         } else {
79958             editor = me.editors.string;
79959         }
79960
79961         
79962         editor.editorId = propName;
79963         return editor;
79964     },
79965
79966     beforeDestroy: function() {
79967         var me = this;
79968         me.callParent();
79969         me.destroyEditors(me.editors);
79970         me.destroyEditors(me.customEditors);
79971         delete me.source;
79972     },
79973
79974     destroyEditors: function (editors) {
79975         for (var ed in editors) {
79976             Ext.destroy(editors[ed]);
79977         }
79978     },
79979
79980     
79981     setSource: function(source) {
79982         this.source = source;
79983         this.propStore.setSource(source);
79984     },
79985
79986     
79987     getSource: function() {
79988         return this.propStore.getSource();
79989     },
79990
79991     
79992     setProperty: function(prop, value, create) {
79993         this.propStore.setValue(prop, value, create);
79994     },
79995
79996     
79997     removeProperty: function(prop) {
79998         this.propStore.remove(prop);
79999     }
80000
80001     
80002     
80003     
80004     
80005 });
80006
80007 Ext.define('Ext.grid.property.HeaderContainer', {
80008
80009     extend: 'Ext.grid.header.Container',
80010
80011     alternateClassName: 'Ext.grid.PropertyColumnModel',
80012
80013     
80014     nameText : 'Name',
80015     valueText : 'Value',
80016     dateFormat : 'm/j/Y',
80017     trueText: 'true',
80018     falseText: 'false',
80019
80020     
80021     nameColumnCls: Ext.baseCSSPrefix + 'grid-property-name',
80022     
80023     constructor : function(grid, store) {
80024
80025         this.grid = grid;
80026         this.store = store;
80027         this.callParent([{
80028             items: [{
80029                 header: this.nameText,
80030                 width: 115,
80031                 sortable: true,
80032                 dataIndex: grid.nameField,
80033                 renderer: Ext.Function.bind(this.renderProp, this),
80034                 itemId: grid.nameField,
80035                 menuDisabled :true,
80036                 tdCls: this.nameColumnCls
80037             }, {
80038                 header: this.valueText,
80039                 renderer: Ext.Function.bind(this.renderCell, this),
80040                 getEditor: function(record) {
80041                     return grid.getCellEditor(record, this);
80042                 },
80043                 flex: 1,
80044                 fixed: true,
80045                 dataIndex: grid.valueField,
80046                 itemId: grid.valueField,
80047                 menuDisabled: true
80048             }]
80049         }]);
80050     },
80051
80052     
80053     
80054     renderProp : function(v) {
80055         return this.getPropertyName(v);
80056     },
80057
80058     
80059     
80060     renderCell : function(val, meta, rec) {
80061         var me = this,
80062             renderer = this.grid.customRenderers[rec.get(me.grid.nameField)],
80063             result = val;
80064
80065         if (renderer) {
80066             return renderer.apply(this, arguments);
80067         }
80068         if (Ext.isDate(val)) {
80069             result = this.renderDate(val);
80070         } else if (Ext.isBoolean(val)) {
80071             result = this.renderBool(val);
80072         }
80073         return Ext.util.Format.htmlEncode(result);
80074     },
80075
80076     
80077     renderDate : Ext.util.Format.date,
80078
80079     
80080     renderBool : function(bVal) {
80081         return this[bVal ? 'trueText' : 'falseText'];
80082     },
80083
80084     
80085     
80086     getPropertyName : function(name) {
80087         var pn = this.grid.propertyNames;
80088         return pn && pn[name] ? pn[name] : name;
80089     }
80090 });
80091
80092 Ext.define('Ext.grid.property.Property', {
80093     extend: 'Ext.data.Model',
80094
80095     alternateClassName: 'Ext.PropGridProperty',
80096
80097     fields: [{
80098         name: 'name',
80099         type: 'string'
80100     }, {
80101         name: 'value'
80102     }],
80103     idProperty: 'name'
80104 });
80105
80106 Ext.define('Ext.grid.property.Store', {
80107
80108     extend: 'Ext.data.Store',
80109
80110     alternateClassName: 'Ext.grid.PropertyStore',
80111
80112     uses: ['Ext.data.reader.Reader', 'Ext.data.proxy.Proxy', 'Ext.data.ResultSet', 'Ext.grid.property.Property'],
80113
80114     constructor : function(grid, source){
80115         this.grid = grid;
80116         this.source = source;
80117         this.callParent([{
80118             data: source,
80119             model: Ext.grid.property.Property,
80120             proxy: this.getProxy()
80121         }]);
80122     },
80123
80124     
80125     getProxy: function() {
80126         if (!this.proxy) {
80127             Ext.grid.property.Store.prototype.proxy = Ext.create('Ext.data.proxy.Memory', {
80128                 model: Ext.grid.property.Property,
80129                 reader: this.getReader()
80130             });
80131         }
80132         return this.proxy;
80133     },
80134
80135     
80136     getReader: function() {
80137         if (!this.reader) {
80138             Ext.grid.property.Store.prototype.reader = Ext.create('Ext.data.reader.Reader', {
80139                 model: Ext.grid.property.Property,
80140
80141                 buildExtractors: Ext.emptyFn,
80142
80143                 read: function(dataObject) {
80144                     return this.readRecords(dataObject);
80145                 },
80146
80147                 readRecords: function(dataObject) {
80148                     var val,
80149                         result = {
80150                             records: [],
80151                             success: true
80152                         };
80153
80154                     for (var propName in dataObject) {
80155                         val = dataObject[propName];
80156                         if (dataObject.hasOwnProperty(propName) && this.isEditableValue(val)) {
80157                             result.records.push(new Ext.grid.property.Property({
80158                                 name: propName,
80159                                 value: val
80160                             }, propName));
80161                         }
80162                     }
80163                     result.total = result.count = result.records.length;
80164                     return Ext.create('Ext.data.ResultSet', result);
80165                 },
80166
80167                 
80168                 isEditableValue: function(val){
80169                     return Ext.isPrimitive(val) || Ext.isDate(val);
80170                 }
80171             });
80172         }
80173         return this.reader;
80174     },
80175
80176     
80177     setSource : function(dataObject) {
80178         var me = this;
80179
80180         me.source = dataObject;
80181         me.suspendEvents();
80182         me.removeAll();
80183         me.proxy.data = dataObject;
80184         me.load();
80185         me.resumeEvents();
80186         me.fireEvent('datachanged', me);
80187     },
80188
80189     
80190     getProperty : function(row) {
80191        return Ext.isNumber(row) ? this.store.getAt(row) : this.store.getById(row);
80192     },
80193
80194     
80195     setValue : function(prop, value, create){
80196         var r = this.getRec(prop);
80197         if (r) {
80198             r.set('value', value);
80199             this.source[prop] = value;
80200         } else if (create) {
80201             
80202             this.source[prop] = value;
80203             r = new Ext.grid.property.Property({name: prop, value: value}, prop);
80204             this.store.add(r);
80205         }
80206     },
80207
80208     
80209     remove : function(prop) {
80210         var r = this.getRec(prop);
80211         if(r) {
80212             this.store.remove(r);
80213             delete this.source[prop];
80214         }
80215     },
80216
80217     
80218     getRec : function(prop) {
80219         return this.store.getById(prop);
80220     },
80221
80222     
80223     getSource : function() {
80224         return this.source;
80225     }
80226 });
80227
80228
80229 Ext.define('Ext.layout.component.Body', {
80230
80231     
80232
80233     alias: ['layout.body'],
80234
80235     extend: 'Ext.layout.component.Component',
80236
80237     uses: ['Ext.layout.container.Container'],
80238
80239     
80240
80241     type: 'body',
80242     
80243     onLayout: function(width, height) {
80244         var me = this,
80245             owner = me.owner;
80246
80247         
80248         me.setTargetSize(width, height);
80249
80250         
80251         me.setBodySize.apply(me, arguments);
80252
80253         
80254         if (owner && owner.layout && owner.layout.isLayout) {
80255             if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
80256                 owner.layout.bindToOwnerCtComponent = true;
80257             }
80258             else {
80259                 owner.layout.bindToOwnerCtComponent = false;
80260             }
80261         }
80262         
80263         me.callParent(arguments);
80264     },
80265
80266     
80267     setBodySize: function(width, height) {
80268         var me = this,
80269             owner = me.owner,
80270             frameSize = owner.frameSize,
80271             isNumber = Ext.isNumber;
80272
80273         if (isNumber(width)) {
80274             width -= owner.el.getFrameWidth('lr') - frameSize.left - frameSize.right;
80275         }
80276         if (isNumber(height)) {
80277             height -= owner.el.getFrameWidth('tb') - frameSize.top - frameSize.bottom;
80278         }
80279
80280         me.setElementSize(owner.body, width, height);
80281     }
80282 });
80283
80284 Ext.define('Ext.layout.component.FieldSet', {
80285     extend: 'Ext.layout.component.Body',
80286     alias: ['layout.fieldset'],
80287
80288     type: 'fieldset',
80289
80290     doContainerLayout: function() {
80291         
80292         if (!this.owner.collapsed) {
80293             this.callParent();
80294         }
80295     }
80296 });
80297
80298 Ext.define('Ext.layout.component.Tab', {
80299
80300     alias: ['layout.tab'],
80301
80302     extend: 'Ext.layout.component.Button',
80303
80304     
80305
80306     beforeLayout: function() {
80307         var me = this, dirty = me.lastClosable !== me.owner.closable;
80308
80309         if (dirty) {
80310             delete me.adjWidth;
80311         }
80312
80313         return this.callParent(arguments) || dirty;
80314     },
80315
80316     onLayout: function () {
80317         var me = this;
80318
80319         me.callParent(arguments);
80320
80321         me.lastClosable = me.owner.closable;
80322     }
80323 });
80324
80325
80326 Ext.define('Ext.layout.component.field.File', {
80327     alias: ['layout.filefield'],
80328     extend: 'Ext.layout.component.field.Field',
80329
80330     type: 'filefield',
80331
80332     sizeBodyContents: function(width, height) {
80333         var me = this,
80334             owner = me.owner;
80335
80336         if (!owner.buttonOnly) {
80337             
80338             
80339             me.setElementSize(owner.inputEl, Ext.isNumber(width) ? width - owner.button.getWidth() - owner.buttonMargin : width);
80340         }
80341     }
80342 });
80343
80344
80345 Ext.define('Ext.layout.component.field.Slider', {
80346
80347     
80348
80349     alias: ['layout.sliderfield'],
80350
80351     extend: 'Ext.layout.component.field.Field',
80352
80353     
80354
80355     type: 'sliderfield',
80356
80357     sizeBodyContents: function(width, height) {
80358         var owner = this.owner,
80359             thumbs = owner.thumbs,
80360             length = thumbs.length,
80361             inputEl = owner.inputEl,
80362             innerEl = owner.innerEl,
80363             endEl = owner.endEl,
80364             i = 0;
80365
80366         
80367         for(; i < length; ++i) {
80368             thumbs[i].el.stopAnimation();
80369         }
80370         
80371         if (owner.vertical) {
80372             inputEl.setHeight(height);
80373             innerEl.setHeight(Ext.isNumber(height) ? height - inputEl.getPadding('t') - endEl.getPadding('b') : height);
80374         }
80375         else {
80376             inputEl.setWidth(width);
80377             innerEl.setWidth(Ext.isNumber(width) ? width - inputEl.getPadding('l') - endEl.getPadding('r') : width);
80378         }
80379         owner.syncThumbs();
80380     }
80381 });
80382
80383
80384
80385 Ext.define('Ext.layout.container.Absolute', {
80386
80387     
80388
80389     alias: 'layout.absolute',
80390     extend: 'Ext.layout.container.Anchor',
80391     requires: ['Ext.chart.axis.Axis', 'Ext.fx.Anim'],
80392     alternateClassName: 'Ext.layout.AbsoluteLayout',
80393
80394     
80395
80396     itemCls: Ext.baseCSSPrefix + 'abs-layout-item',
80397
80398     type: 'absolute',
80399
80400     onLayout: function() {
80401         var me = this,
80402             target = me.getTarget(),
80403             targetIsBody = target.dom === document.body;
80404
80405         
80406         if (!targetIsBody) {
80407             target.position();
80408         }
80409         me.paddingLeft = target.getPadding('l');
80410         me.paddingTop = target.getPadding('t');
80411         me.callParent(arguments);
80412     },
80413
80414     
80415     adjustWidthAnchor: function(value, comp) {
80416         
80417         return value ? value - comp.getPosition(true)[0] : value;
80418     },
80419
80420     
80421     adjustHeightAnchor: function(value, comp) {
80422         
80423         return value ? value - comp.getPosition(true)[1] : value;
80424     }
80425 });
80426
80427 Ext.define('Ext.layout.container.Accordion', {
80428     extend: 'Ext.layout.container.VBox',
80429     alias: ['layout.accordion'],
80430     alternateClassName: 'Ext.layout.AccordionLayout',
80431     
80432     align: 'stretch',
80433
80434     
80435     fill : true,
80436     
80437     autoWidth : true,
80438     
80439     titleCollapse : true,
80440     
80441     hideCollapseTool : false,
80442     
80443     collapseFirst : false,
80444     
80445     animate : true,
80446     
80447     activeOnTop : false,
80448     
80449     multi: false,
80450
80451     constructor: function() {
80452         var me = this;
80453
80454         me.callParent(arguments);
80455
80456         
80457         me.initialAnimate = me.animate;
80458         me.animate = false;
80459
80460         
80461         if (me.fill === false) {
80462             me.itemCls = Ext.baseCSSPrefix + 'accordion-item';
80463         }
80464     },
80465
80466     
80467     
80468     beforeLayout: function() {
80469         var me = this;
80470
80471         me.callParent(arguments);
80472         if (me.fill) {
80473             if (!me.owner.el.dom.style.height) {
80474                 return false;
80475             }
80476         } else {
80477             me.owner.componentLayout.monitorChildren = false;
80478             me.autoSize = true;
80479             me.owner.setAutoScroll(true);
80480         }
80481     },
80482
80483     renderItems : function(items, target) {
80484         var me = this,
80485             ln = items.length,
80486             i = 0,
80487             comp,
80488             targetSize = me.getLayoutTargetSize(),
80489             renderedPanels = [],
80490             border;
80491
80492         for (; i < ln; i++) {
80493             comp = items[i];
80494             if (!comp.rendered) {
80495                 renderedPanels.push(comp);
80496
80497                 
80498                 if (me.collapseFirst) {
80499                     comp.collapseFirst = me.collapseFirst;
80500                 }
80501                 if (me.hideCollapseTool) {
80502                     comp.hideCollapseTool = me.hideCollapseTool;
80503                     comp.titleCollapse = true;
80504                 }
80505                 else if (me.titleCollapse) {
80506                     comp.titleCollapse = me.titleCollapse;
80507                 }
80508
80509                 delete comp.hideHeader;
80510                 comp.collapsible = true;
80511                 comp.title = comp.title || '&#160;';
80512                 comp.setBorder(false);
80513
80514                 
80515                 comp.width = targetSize.width;
80516                 if (me.fill) {
80517                     delete comp.height;
80518                     delete comp.flex;
80519
80520                     
80521                     if (me.expandedItem !== undefined) {
80522                         comp.collapsed = true;
80523                     }
80524                     
80525                     else if (comp.collapsed === false) {
80526                         comp.flex = 1;
80527                         me.expandedItem = i;
80528                     } else {
80529                         comp.collapsed = true;
80530                     }
80531                 } else {
80532                     delete comp.flex;
80533                     comp.animCollapse = me.initialAnimate;
80534                     comp.autoHeight = true;
80535                     comp.autoScroll = false;
80536                 }
80537             }
80538         }
80539
80540         
80541         if (ln && me.expandedItem === undefined) {
80542             me.expandedItem = 0;
80543             comp = items[0];
80544             comp.collapsed = false;
80545             if (me.fill) {
80546                 comp.flex = 1;
80547             }
80548         }
80549         
80550         
80551         me.callParent(arguments);
80552                 
80553         
80554         ln = renderedPanels.length;
80555         for (i = 0; i < ln; i++) {
80556             comp = renderedPanels[i];
80557
80558             
80559             delete comp.width;
80560
80561             comp.header.addCls(Ext.baseCSSPrefix + 'accordion-hd');
80562             comp.body.addCls(Ext.baseCSSPrefix + 'accordion-body');
80563             
80564             
80565             if (me.fill) {
80566                 me.owner.mon(comp, {
80567                     show: me.onComponentShow,
80568                     beforeexpand: me.onComponentExpand,
80569                     beforecollapse: me.onComponentCollapse,
80570                     scope: me
80571                 });
80572             }
80573         }
80574     },
80575
80576     onLayout: function() {
80577         var me = this;
80578         
80579         me.updatePanelClasses();
80580                 
80581         if (me.fill) {
80582             me.callParent(arguments);
80583         } else {
80584             var targetSize = me.getLayoutTargetSize(),
80585                 items = me.getVisibleItems(),
80586                 len = items.length,
80587                 i = 0, comp;
80588
80589             for (; i < len; i++) {
80590                 comp = items[i];
80591                 if (comp.collapsed) {
80592                     items[i].setWidth(targetSize.width);
80593                 } else {
80594                     items[i].setSize(null, null);
80595                 }
80596             }
80597         }
80598         
80599         return me;
80600     },
80601     
80602     updatePanelClasses: function() {
80603         var children = this.getLayoutItems(),
80604             ln = children.length,
80605             siblingCollapsed = true,
80606             i, child;
80607             
80608         for (i = 0; i < ln; i++) {
80609             child = children[i];
80610             if (!siblingCollapsed) {
80611                 child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
80612             }
80613             else {
80614                 child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
80615             }
80616             if (i + 1 == ln && child.collapsed) {
80617                 child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
80618             }
80619             else {
80620                 child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
80621             }
80622             siblingCollapsed = child.collapsed;
80623         }
80624     },
80625
80626     
80627     
80628     
80629     onComponentExpand: function(toExpand) {
80630         var me = this,
80631             it = me.owner.items.items,
80632             len = it.length,
80633             i = 0,
80634             comp;
80635
80636         for (; i < len; i++) {
80637             comp = it[i];
80638             if (comp === toExpand && comp.collapsed) {
80639                 me.setExpanded(comp);
80640             } else if (!me.multi && (comp.rendered && comp.header.rendered && comp !== toExpand && !comp.collapsed)) {
80641                 me.setCollapsed(comp);
80642             }
80643         }
80644         
80645         me.animate = me.initialAnimate;
80646         me.layout();
80647         me.animate = false;
80648         return false;
80649     },
80650
80651     onComponentCollapse: function(comp) {
80652         var me = this,
80653             toExpand = comp.next() || comp.prev(),
80654             expanded = me.multi ? me.owner.query('>panel:not([collapsed])') : [];
80655
80656         
80657         
80658         if (me.multi) {
80659             me.setCollapsed(comp);
80660
80661             
80662             
80663             if (expanded.length === 1 && expanded[0] === comp) {
80664                 me.setExpanded(toExpand);
80665             }
80666             
80667             me.animate = me.initialAnimate;
80668             me.layout();
80669             me.animate = false;
80670         }
80671         
80672         else if (toExpand) {
80673             me.onComponentExpand(toExpand);
80674         }
80675         return false;
80676     },
80677
80678     onComponentShow: function(comp) {
80679         
80680         this.onComponentExpand(comp);
80681     },
80682
80683     setCollapsed: function(comp) {
80684         var otherDocks = comp.getDockedItems(),
80685             dockItem,
80686             len = otherDocks.length,
80687             i = 0;
80688
80689         
80690         comp.hiddenDocked = [];
80691         for (; i < len; i++) {
80692             dockItem = otherDocks[i];
80693             if ((dockItem !== comp.header) && !dockItem.hidden) {
80694                 dockItem.hidden = true;
80695                 comp.hiddenDocked.push(dockItem);
80696             }
80697         }
80698         comp.addCls(comp.collapsedCls);
80699         comp.header.addCls(comp.collapsedHeaderCls);
80700         comp.height = comp.header.getHeight();
80701         comp.el.setHeight(comp.height);
80702         comp.collapsed = true;
80703         delete comp.flex;
80704         comp.fireEvent('collapse', comp);
80705         if (comp.collapseTool) {
80706             comp.collapseTool.setType('expand-' + comp.getOppositeDirection(comp.collapseDirection));
80707         }
80708     },
80709
80710     setExpanded: function(comp) {
80711         var otherDocks = comp.hiddenDocked,
80712             len = otherDocks ? otherDocks.length : 0,
80713             i = 0;
80714
80715         
80716         for (; i < len; i++) {
80717             otherDocks[i].hidden = false;
80718         }
80719
80720         
80721         if (!comp.body.isVisible()) {
80722             comp.body.show();
80723         }
80724         delete comp.collapsed;
80725         delete comp.height;
80726         delete comp.componentLayout.lastComponentSize;
80727         comp.suspendLayout = false;
80728         comp.flex = 1;
80729         comp.removeCls(comp.collapsedCls);
80730         comp.header.removeCls(comp.collapsedHeaderCls);
80731         comp.fireEvent('expand', comp);
80732         if (comp.collapseTool) {
80733             comp.collapseTool.setType('collapse-' + comp.collapseDirection);
80734         }
80735         comp.setAutoScroll(comp.initialConfig.autoScroll);
80736     }
80737 });
80738
80739 Ext.define('Ext.resizer.Splitter', {
80740     extend: 'Ext.Component',
80741     requires: ['Ext.XTemplate'],
80742     uses: ['Ext.resizer.SplitterTracker'],
80743     alias: 'widget.splitter',
80744
80745     renderTpl: [
80746         '<tpl if="collapsible===true"><div class="' + Ext.baseCSSPrefix + 'collapse-el ' + Ext.baseCSSPrefix + 'layout-split-{collapseDir}">&nbsp;</div></tpl>'
80747     ],
80748
80749     baseCls: Ext.baseCSSPrefix + 'splitter',
80750     collapsedCls: Ext.baseCSSPrefix + 'splitter-collapsed',
80751
80752     
80753     collapsible: false,
80754
80755     
80756
80757     
80758     collapseOnDblClick: true,
80759
80760     
80761     defaultSplitMin: 40,
80762
80763     
80764     defaultSplitMax: 1000,
80765
80766     width: 5,
80767     height: 5,
80768
80769     
80770     collapseTarget: 'next',
80771
80772     
80773
80774     onRender: function() {
80775         var me = this,
80776             target = me.getCollapseTarget(),
80777             collapseDir = me.getCollapseDirection();
80778
80779         Ext.applyIf(me.renderData, {
80780             collapseDir: collapseDir,
80781             collapsible: me.collapsible || target.collapsible
80782         });
80783         Ext.applyIf(me.renderSelectors, {
80784             collapseEl: '.' + Ext.baseCSSPrefix + 'collapse-el'
80785         });
80786
80787         this.callParent(arguments);
80788
80789         
80790         if (me.performCollapse !== false) {
80791             if (me.renderData.collapsible) {
80792                 me.mon(me.collapseEl, 'click', me.toggleTargetCmp, me);
80793             }
80794             if (me.collapseOnDblClick) {
80795                 me.mon(me.el, 'dblclick', me.toggleTargetCmp, me);
80796             }
80797         }
80798
80799         
80800         me.mon(target, 'collapse', me.onTargetCollapse, me);
80801         me.mon(target, 'expand', me.onTargetExpand, me);
80802
80803         me.el.addCls(me.baseCls + '-' + me.orientation);
80804         me.el.unselectable();
80805
80806         me.tracker = Ext.create('Ext.resizer.SplitterTracker', {
80807             el: me.el
80808         });
80809     },
80810
80811     getCollapseDirection: function() {
80812         var me = this,
80813             idx,
80814             type = me.ownerCt.layout.type;
80815
80816         
80817         
80818         
80819         
80820         
80821         
80822         
80823         if (me.collapseTarget.isComponent) {
80824             idx = Number(me.ownerCt.items.indexOf(me.collapseTarget) == me.ownerCt.items.indexOf(me) - 1) << 1 | Number(type == 'hbox');
80825         } else {
80826             idx = Number(me.collapseTarget == 'prev') << 1 | Number(type == 'hbox');
80827         }
80828
80829         
80830         me.orientation = ['horizontal', 'vertical'][idx & 1];
80831         return ['bottom', 'right', 'top', 'left'][idx];
80832     },
80833
80834     getCollapseTarget: function() {
80835         return this.collapseTarget.isComponent ? this.collapseTarget : this.collapseTarget == 'prev' ? this.previousSibling() : this.nextSibling();
80836     },
80837
80838     onTargetCollapse: function(target) {
80839         this.el.addCls(this.collapsedCls);
80840     },
80841
80842     onTargetExpand: function(target) {
80843         this.el.removeCls(this.collapsedCls);
80844     },
80845
80846     toggleTargetCmp: function(e, t) {
80847         var cmp = this.getCollapseTarget();
80848
80849         if (cmp.isVisible()) {
80850             
80851             if (cmp.collapsed) {
80852                 cmp.expand(cmp.animCollapse);
80853             
80854             } else {
80855                 cmp.collapse(this.renderData.collapseDir, cmp.animCollapse);
80856             }
80857         }
80858     },
80859
80860     
80861     setSize: function() {
80862         var me = this;
80863         me.callParent(arguments);
80864         if (Ext.isIE) {
80865             me.el.repaint();
80866         }
80867     }
80868 });
80869
80870
80871 Ext.define('Ext.layout.container.Border', {
80872
80873     alias: ['layout.border'],
80874     extend: 'Ext.layout.container.Container',
80875     requires: ['Ext.resizer.Splitter', 'Ext.container.Container', 'Ext.fx.Anim'],
80876     alternateClassName: 'Ext.layout.BorderLayout',
80877
80878     targetCls: Ext.baseCSSPrefix + 'border-layout-ct',
80879
80880     itemCls: Ext.baseCSSPrefix + 'border-item',
80881
80882     bindToOwnerCtContainer: true,
80883
80884     fixedLayout: false,
80885
80886     percentageRe: /(\d+)%/,
80887
80888     slideDirection: {
80889         north: 't',
80890         south: 'b',
80891         west: 'l',
80892         east: 'r'
80893     },
80894
80895     constructor: function(config) {
80896         this.initialConfig = config;
80897         this.callParent(arguments);
80898     },
80899
80900     onLayout: function() {
80901         var me = this;
80902         if (!me.borderLayoutInitialized) {
80903             me.initializeBorderLayout();
80904         }
80905
80906         
80907         me.shadowLayout.onLayout();
80908         if (me.embeddedContainer) {
80909             me.embeddedContainer.layout.onLayout();
80910         }
80911
80912         
80913         
80914         if (!me.initialCollapsedComplete) {
80915             Ext.iterate(me.regions, function(name, region){
80916                 if (region.borderCollapse) {
80917                     me.onBeforeRegionCollapse(region, region.collapseDirection, false, 0);
80918                 }
80919             });
80920             me.initialCollapsedComplete = true;
80921         }
80922     },
80923
80924     isValidParent : function(item, target, position) {
80925         if (!this.borderLayoutInitialized) {
80926             this.initializeBorderLayout();
80927         }
80928
80929         
80930         return this.shadowLayout.isValidParent(item, target, position);
80931     },
80932
80933     beforeLayout: function() {
80934         if (!this.borderLayoutInitialized) {
80935             this.initializeBorderLayout();
80936         }
80937
80938         
80939         this.shadowLayout.beforeLayout();
80940     },
80941
80942     renderItems: function(items, target) {
80943         Ext.Error.raise('This should not be called');
80944     },
80945
80946     renderItem: function(item) {
80947         Ext.Error.raise('This should not be called');
80948     },
80949
80950     initializeBorderLayout: function() {
80951         var me = this,
80952             i = 0,
80953             items = me.getLayoutItems(),
80954             ln = items.length,
80955             regions = (me.regions = {}),
80956             vBoxItems = [],
80957             hBoxItems = [],
80958             horizontalFlex = 0,
80959             verticalFlex = 0,
80960             comp, percentage;
80961
80962         
80963         me.splitters = {};
80964
80965         
80966         for (; i < ln; i++) {
80967             comp = items[i];
80968             regions[comp.region] = comp;
80969
80970             
80971             if (comp.region != 'center' && comp.collapsible && comp.collapseMode != 'header') {
80972
80973                 
80974                 comp.borderCollapse = comp.collapsed;
80975                 delete comp.collapsed;
80976
80977                 comp.on({
80978                     beforecollapse: me.onBeforeRegionCollapse,
80979                     beforeexpand: me.onBeforeRegionExpand,
80980                     destroy: me.onRegionDestroy,
80981                     scope: me
80982                 });
80983                 me.setupState(comp);
80984             }
80985         }
80986         if (!regions.center) {
80987             Ext.Error.raise("You must specify a center region when defining a BorderLayout.");
80988         }
80989         comp = regions.center;
80990         if (!comp.flex) {
80991             comp.flex = 1;
80992         }
80993         delete comp.width;
80994         comp.maintainFlex = true;
80995
80996         
80997         comp = regions.west;
80998         if (comp) {
80999             comp.collapseDirection = Ext.Component.DIRECTION_LEFT;
81000             hBoxItems.push(comp);
81001             if (comp.split) {
81002                 hBoxItems.push(me.splitters.west = me.createSplitter(comp));
81003             }
81004             percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
81005             if (percentage) {
81006                 horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
81007                 delete comp.width;
81008             }
81009         }
81010         comp = regions.north;
81011         if (comp) {
81012             comp.collapseDirection = Ext.Component.DIRECTION_TOP;
81013             vBoxItems.push(comp);
81014             if (comp.split) {
81015                 vBoxItems.push(me.splitters.north = me.createSplitter(comp));
81016             }
81017             percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
81018             if (percentage) {
81019                 verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
81020                 delete comp.height;
81021             }
81022         }
81023
81024         
81025         if (regions.north || regions.south) {
81026             if (regions.east || regions.west) {
81027
81028                 
81029                 vBoxItems.push(me.embeddedContainer = Ext.create('Ext.container.Container', {
81030                     xtype: 'container',
81031                     region: 'center',
81032                     id: me.owner.id + '-embedded-center',
81033                     cls: Ext.baseCSSPrefix + 'border-item',
81034                     flex: regions.center.flex,
81035                     maintainFlex: true,
81036                     layout: {
81037                         type: 'hbox',
81038                         align: 'stretch'
81039                     }
81040                 }));
81041                 hBoxItems.push(regions.center);
81042             }
81043             
81044             else {
81045                 vBoxItems.push(regions.center);
81046             }
81047         }
81048         
81049         else {
81050             hBoxItems.push(regions.center);
81051         }
81052
81053         
81054         comp = regions.south;
81055         if (comp) {
81056             comp.collapseDirection = Ext.Component.DIRECTION_BOTTOM;
81057             if (comp.split) {
81058                 vBoxItems.push(me.splitters.south = me.createSplitter(comp));
81059             }
81060             percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
81061             if (percentage) {
81062                 verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
81063                 delete comp.height;
81064             }
81065             vBoxItems.push(comp);
81066         }
81067         comp = regions.east;
81068         if (comp) {
81069             comp.collapseDirection = Ext.Component.DIRECTION_RIGHT;
81070             if (comp.split) {
81071                 hBoxItems.push(me.splitters.east = me.createSplitter(comp));
81072             }
81073             percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
81074             if (percentage) {
81075                 horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
81076                 delete comp.width;
81077             }
81078             hBoxItems.push(comp);
81079         }
81080
81081         
81082         
81083         
81084         
81085         if (regions.north || regions.south) {
81086
81087             me.shadowContainer = Ext.create('Ext.container.Container', {
81088                 ownerCt: me.owner,
81089                 el: me.getTarget(),
81090                 layout: Ext.applyIf({
81091                     type: 'vbox',
81092                     align: 'stretch'
81093                 }, me.initialConfig)
81094             });
81095             me.createItems(me.shadowContainer, vBoxItems);
81096
81097             
81098             if (me.splitters.north) {
81099                 me.splitters.north.ownerCt = me.shadowContainer;
81100             }
81101             if (me.splitters.south) {
81102                 me.splitters.south.ownerCt = me.shadowContainer;
81103             }
81104
81105             
81106             if (me.embeddedContainer) {
81107                 me.embeddedContainer.ownerCt = me.shadowContainer;
81108                 me.createItems(me.embeddedContainer, hBoxItems);
81109
81110                 
81111                 if (me.splitters.east) {
81112                     me.splitters.east.ownerCt = me.embeddedContainer;
81113                 }
81114                 if (me.splitters.west) {
81115                     me.splitters.west.ownerCt = me.embeddedContainer;
81116                 }
81117
81118                 
81119                 if (horizontalFlex) {
81120                     regions.center.flex -= horizontalFlex;
81121                 }
81122                 
81123                 if (verticalFlex) {
81124                     me.embeddedContainer.flex -= verticalFlex;
81125                 }
81126             } else {
81127                 
81128                 if (verticalFlex) {
81129                     regions.center.flex -= verticalFlex;
81130                 }
81131             }
81132         }
81133         
81134         
81135         else {
81136             me.shadowContainer = Ext.create('Ext.container.Container', {
81137                 ownerCt: me.owner,
81138                 el: me.getTarget(),
81139                 layout: Ext.applyIf({
81140                     type: (hBoxItems.length == 1) ? 'fit' : 'hbox',
81141                     align: 'stretch'
81142                 }, me.initialConfig)
81143             });
81144             me.createItems(me.shadowContainer, hBoxItems);
81145
81146             
81147             if (me.splitters.east) {
81148                 me.splitters.east.ownerCt = me.shadowContainer;
81149             }
81150             if (me.splitters.west) {
81151                 me.splitters.west.ownerCt = me.shadowContainer;
81152             }
81153
81154             
81155             if (horizontalFlex) {
81156                 regions.center.flex -= verticalFlex;
81157             }
81158         }
81159
81160         
81161         for (i = 0, items = me.shadowContainer.items.items, ln = items.length; i < ln; i++) {
81162             items[i].shadowOwnerCt = me.shadowContainer;
81163         }
81164         if (me.embeddedContainer) {
81165             for (i = 0, items = me.embeddedContainer.items.items, ln = items.length; i < ln; i++) {
81166                 items[i].shadowOwnerCt = me.embeddedContainer;
81167             }
81168         }
81169
81170         
81171         me.shadowLayout = me.shadowContainer.getLayout();
81172
81173         me.borderLayoutInitialized = true;
81174     },
81175
81176
81177     setupState: function(comp){
81178         var getState = comp.getState;
81179         comp.getState = function(){
81180             
81181             var state = getState.call(comp) || {},
81182                 region = comp.region;
81183
81184             state.collapsed = !!comp.collapsed;
81185             if (region == 'west' || region == 'east') {
81186                 state.width = comp.getWidth();
81187             } else {
81188                 state.height = comp.getHeight();
81189             }
81190             return state;
81191         };
81192         comp.addStateEvents(['collapse', 'expand', 'resize']);
81193     },
81194
81195     
81196     createItems: function(container, items){
81197         
81198         
81199         delete container.items;
81200         container.initItems();
81201         container.items.addAll(items);
81202     },
81203
81204     
81205     
81206     createSplitter: function(comp) {
81207         var me = this,
81208             interceptCollapse = (comp.collapseMode != 'header'),
81209             resizer;
81210
81211         resizer = Ext.create('Ext.resizer.Splitter', {
81212             hidden: !!comp.hidden,
81213             collapseTarget: comp,
81214             performCollapse: !interceptCollapse,
81215             listeners: interceptCollapse ? {
81216                 click: {
81217                     fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
81218                     element: 'collapseEl'
81219                 }
81220             } : null
81221         });
81222
81223         
81224         if (comp.collapseMode == 'mini') {
81225             comp.placeholder = resizer;
81226         }
81227
81228         
81229         comp.on({
81230             hide: me.onRegionVisibilityChange,
81231             show: me.onRegionVisibilityChange,
81232             scope: me
81233         });
81234         return resizer;
81235     },
81236
81237     
81238     onRegionVisibilityChange: function(comp){
81239         this.splitters[comp.region][comp.hidden ? 'hide' : 'show']();
81240         this.layout();
81241     },
81242
81243     
81244     
81245     
81246     onSplitterCollapseClick: function(comp) {
81247         if (comp.collapsed) {
81248             this.onPlaceHolderToolClick(null, null, null, {client: comp});
81249         } else {
81250             comp.collapse();
81251         }
81252     },
81253
81254     
81255     getPlaceholder: function(comp) {
81256         var me = this,
81257             placeholder = comp.placeholder,
81258             shadowContainer = comp.shadowOwnerCt,
81259             shadowLayout = shadowContainer.layout,
81260             oppositeDirection = Ext.panel.Panel.prototype.getOppositeDirection(comp.collapseDirection),
81261             horiz = (comp.region == 'north' || comp.region == 'south');
81262
81263         
81264         if (comp.collapseMode == 'header') {
81265             return;
81266         }
81267
81268         
81269         if (!placeholder) {
81270             if (comp.collapseMode == 'mini') {
81271                 placeholder = Ext.create('Ext.resizer.Splitter', {
81272                     id: 'collapse-placeholder-' + comp.id,
81273                     collapseTarget: comp,
81274                     performCollapse: false,
81275                     listeners: {
81276                         click: {
81277                             fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
81278                             element: 'collapseEl'
81279                         }
81280                     }
81281                 });
81282                 placeholder.addCls(placeholder.collapsedCls);
81283             } else {
81284                 placeholder = {
81285                     id: 'collapse-placeholder-' + comp.id,
81286                     margins: comp.initialConfig.margins || Ext.getClass(comp).prototype.margins,
81287                     xtype: 'header',
81288                     orientation: horiz ? 'horizontal' : 'vertical',
81289                     title: comp.title,
81290                     textCls: comp.headerTextCls,
81291                     iconCls: comp.iconCls,
81292                     baseCls: comp.baseCls + '-header',
81293                     ui: comp.ui,
81294                     indicateDrag: comp.draggable,
81295                     cls: Ext.baseCSSPrefix + 'region-collapsed-placeholder ' + Ext.baseCSSPrefix + 'region-collapsed-' + comp.collapseDirection + '-placeholder',
81296                     listeners: comp.floatable ? {
81297                         click: {
81298                             fn: function(e) {
81299                                 me.floatCollapsedPanel(e, comp);
81300                             },
81301                             element: 'el'
81302                         }
81303                     } : null
81304                 };
81305                 
81306                 if ((Ext.isIE6 || Ext.isIE7 || (Ext.isIEQuirks)) && !horiz) {
81307                     placeholder.width = 25;
81308                 }
81309                 placeholder[horiz ? 'tools' : 'items'] = [{
81310                     xtype: 'tool',
81311                     client: comp,
81312                     type: 'expand-' + oppositeDirection,
81313                     handler: me.onPlaceHolderToolClick,
81314                     scope: me
81315                 }];
81316             }
81317             placeholder = me.owner.createComponent(placeholder);
81318             if (comp.isXType('panel')) {
81319                 comp.on({
81320                     titlechange: me.onRegionTitleChange,
81321                     iconchange: me.onRegionIconChange,
81322                     scope: me
81323                 });
81324             }
81325         }
81326
81327         
81328         comp.placeholder = placeholder;
81329         placeholder.comp = comp;
81330
81331         return placeholder;
81332     },
81333
81334     
81335     onRegionTitleChange: function(comp, newTitle) {
81336         comp.placeholder.setTitle(newTitle);
81337     },
81338
81339     
81340     onRegionIconChange: function(comp, newIconCls) {
81341         comp.placeholder.setIconCls(newIconCls);
81342     },
81343
81344     
81345     calculateChildBox: function(comp) {
81346         var me = this;
81347         if (me.shadowContainer.items.contains(comp)) {
81348             return me.shadowContainer.layout.calculateChildBox(comp);
81349         }
81350         else if (me.embeddedContainer && me.embeddedContainer.items.contains(comp)) {
81351             return me.embeddedContainer.layout.calculateChildBox(comp);
81352         }
81353     },
81354
81355     
81356     onBeforeRegionCollapse: function(comp, direction, animate) {
81357         var me = this,
81358             compEl = comp.el,
81359             miniCollapse = comp.collapseMode == 'mini',
81360             shadowContainer = comp.shadowOwnerCt,
81361             shadowLayout = shadowContainer.layout,
81362             placeholder = comp.placeholder,
81363             placeholderBox,
81364             targetSize = shadowLayout.getLayoutTargetSize(),
81365             sl = me.owner.suspendLayout,
81366             scsl = shadowContainer.suspendLayout,
81367             isNorthOrWest = (comp.region == 'north' || comp.region == 'west'); 
81368
81369         
81370         me.owner.suspendLayout = true;
81371         shadowContainer.suspendLayout = true;
81372
81373         
81374         shadowLayout.layoutBusy = true;
81375         if (shadowContainer.componentLayout) {
81376             shadowContainer.componentLayout.layoutBusy = true;
81377         }
81378         me.shadowContainer.layout.layoutBusy = true;
81379         me.layoutBusy = true;
81380         me.owner.componentLayout.layoutBusy = true;
81381
81382         
81383         if (!placeholder) {
81384             placeholder = me.getPlaceholder(comp);
81385         }
81386
81387         
81388         if (placeholder.shadowOwnerCt === shadowContainer) {
81389             placeholder.show();
81390         }
81391         
81392         
81393         
81394         else {
81395             shadowContainer.insert(shadowContainer.items.indexOf(comp) + (isNorthOrWest ? 0 : 1), placeholder);
81396             placeholder.shadowOwnerCt = shadowContainer;
81397             placeholder.ownerCt = me.owner;
81398         }
81399
81400         
81401         
81402         
81403         comp.hidden = true;
81404
81405         if (!placeholder.rendered) {
81406             shadowLayout.renderItem(placeholder, shadowLayout.innerCt);
81407         }
81408
81409         
81410         function afterCollapse() {
81411
81412             
81413             me.owner.suspendLayout = sl;
81414             shadowContainer.suspendLayout = scsl;
81415             delete shadowLayout.layoutBusy;
81416             if (shadowContainer.componentLayout) {
81417                 delete shadowContainer.componentLayout.layoutBusy;
81418             }
81419             delete me.shadowContainer.layout.layoutBusy;
81420             delete me.layoutBusy;
81421             delete me.owner.componentLayout.layoutBusy;
81422
81423             
81424             comp.collapsed = true;
81425             comp.fireEvent('collapse', comp);
81426         }
81427
81428         
81429         if (comp.animCollapse && me.initialCollapsedComplete) {
81430             shadowLayout.layout();
81431             compEl.dom.style.zIndex = 100;
81432
81433             
81434             if (!miniCollapse) {
81435                 placeholder.el.hide();
81436             }
81437             compEl.slideOut(me.slideDirection[comp.region], {
81438                 duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
81439                 listeners: {
81440                     afteranimate: function() {
81441                         compEl.show().setLeftTop(-10000, -10000);
81442                         compEl.dom.style.zIndex = '';
81443
81444                         
81445                        if (!miniCollapse) {
81446                             placeholder.el.slideIn(me.slideDirection[comp.region], {
81447                                 easing: 'linear',
81448                                 duration: 100
81449                             });
81450                         }
81451                         afterCollapse();
81452                     }
81453                 }
81454             });
81455         } else {
81456             compEl.setLeftTop(-10000, -10000);
81457             shadowLayout.layout();
81458             afterCollapse();
81459
81460             
81461             if (Ext.isIE) {
81462                 placeholder.setCalculatedSize(placeholder.el.getWidth());
81463             }
81464         }
81465
81466         return false;
81467     },
81468
81469     
81470     onBeforeRegionExpand: function(comp, animate) {
81471         this.onPlaceHolderToolClick(null, null, null, {client: comp});
81472         return false;
81473     },
81474
81475     
81476     onPlaceHolderToolClick: function(e, target, owner, tool) {
81477         var me = this,
81478             comp = tool.client,
81479
81480             
81481             hidePlaceholder = (comp.collapseMode != 'mini') || !comp.split,
81482             compEl = comp.el,
81483             toCompBox,
81484             placeholder = comp.placeholder,
81485             placeholderEl = placeholder.el,
81486             shadowContainer = comp.shadowOwnerCt,
81487             shadowLayout = shadowContainer.layout,
81488             curSize,
81489             sl = me.owner.suspendLayout,
81490             scsl = shadowContainer.suspendLayout,
81491             isFloating;
81492
81493         
81494         
81495         
81496         if (comp.getActiveAnimation()) {
81497             comp.stopAnimation();
81498         }
81499
81500         
81501         
81502         
81503         if (comp.slideOutAnim) {
81504             
81505             compEl.un(comp.panelMouseMon);
81506             placeholderEl.un(comp.placeholderMouseMon);
81507
81508             delete comp.slideOutAnim;
81509             delete comp.panelMouseMon;
81510             delete comp.placeholderMouseMon;
81511
81512             
81513             isFloating = true;
81514         }
81515
81516         
81517         me.owner.suspendLayout = true;
81518         shadowContainer.suspendLayout = true;
81519
81520         
81521         shadowLayout.layoutBusy = true;
81522         if (shadowContainer.componentLayout) {
81523             shadowContainer.componentLayout.layoutBusy = true;
81524         }
81525         me.shadowContainer.layout.layoutBusy = true;
81526         me.layoutBusy = true;
81527         me.owner.componentLayout.layoutBusy = true;
81528
81529         
81530         
81531         comp.hidden = false;
81532         comp.collapsed = false;
81533         if (hidePlaceholder) {
81534             placeholder.hidden = true;
81535         }
81536         toCompBox = shadowLayout.calculateChildBox(comp);
81537
81538         
81539         if (comp.collapseTool) {
81540             comp.collapseTool.show();
81541         }
81542
81543         
81544         if (comp.animCollapse && !isFloating) {
81545             compEl.setStyle('visibility', 'hidden');
81546         }
81547         compEl.setLeftTop(toCompBox.left, toCompBox.top);
81548
81549         
81550         
81551         curSize = comp.getSize();
81552         if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
81553             me.setItemSize(comp, toCompBox.width, toCompBox.height);
81554         }
81555
81556         
81557         function afterExpand() {
81558             
81559             me.owner.suspendLayout = sl;
81560             shadowContainer.suspendLayout = scsl;
81561             delete shadowLayout.layoutBusy;
81562             if (shadowContainer.componentLayout) {
81563                 delete shadowContainer.componentLayout.layoutBusy;
81564             }
81565             delete me.shadowContainer.layout.layoutBusy;
81566             delete me.layoutBusy;
81567             delete me.owner.componentLayout.layoutBusy;
81568
81569             
81570             comp.removeCls(Ext.baseCSSPrefix + 'border-region-slide-in');
81571
81572             
81573             comp.fireEvent('expand', comp);
81574         }
81575
81576         
81577         if (hidePlaceholder) {
81578             placeholder.el.hide();
81579         }
81580
81581         
81582         
81583         if (comp.animCollapse && !isFloating) {
81584             compEl.dom.style.zIndex = 100;
81585             compEl.slideIn(me.slideDirection[comp.region], {
81586                 duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
81587                 listeners: {
81588                     afteranimate: function() {
81589                         compEl.dom.style.zIndex = '';
81590                         comp.hidden = false;
81591                         shadowLayout.onLayout();
81592                         afterExpand();
81593                     }
81594                 }
81595             });
81596         } else {
81597             shadowLayout.onLayout();
81598             afterExpand();
81599         }
81600     },
81601
81602     floatCollapsedPanel: function(e, comp) {
81603
81604         if (comp.floatable === false) {
81605             return;
81606         }
81607
81608         var me = this,
81609             compEl = comp.el,
81610             placeholder = comp.placeholder,
81611             placeholderEl = placeholder.el,
81612             shadowContainer = comp.shadowOwnerCt,
81613             shadowLayout = shadowContainer.layout,
81614             placeholderBox = shadowLayout.getChildBox(placeholder),
81615             scsl = shadowContainer.suspendLayout,
81616             curSize, toCompBox, compAnim;
81617
81618         
81619         if (e.getTarget('.' + Ext.baseCSSPrefix + 'tool')) {
81620             return;
81621         }
81622
81623         
81624         
81625         if (compEl.getActiveAnimation()) {
81626             return;
81627         }
81628
81629         
81630         
81631         if (comp.slideOutAnim) {
81632             me.slideOutFloatedComponent(comp);
81633             return;
81634         }
81635
81636         
81637         
81638         function onMouseLeaveFloated(e) {
81639             var slideRegion = compEl.getRegion().union(placeholderEl.getRegion()).adjust(1, -1, -1, 1);
81640
81641             
81642             if (!slideRegion.contains(e.getPoint())) {
81643                 me.slideOutFloatedComponent(comp);
81644             }
81645         }
81646
81647         
81648         comp.placeholderMouseMon = placeholderEl.monitorMouseLeave(500, onMouseLeaveFloated);
81649
81650         
81651         shadowContainer.suspendLayout = true;
81652
81653         
81654         me.layoutBusy = true;
81655         me.owner.componentLayout.layoutBusy = true;
81656
81657         
81658         
81659         if (comp.collapseTool) {
81660             comp.collapseTool.hide();
81661         }
81662
81663         
81664         comp.hidden = false;
81665         comp.collapsed = false;
81666         placeholder.hidden = true;
81667
81668         
81669         toCompBox = shadowLayout.calculateChildBox(comp);
81670         placeholder.hidden = false;
81671
81672         
81673         if (comp.region == 'north' || comp.region == 'west') {
81674             toCompBox[shadowLayout.parallelBefore] += placeholderBox[shadowLayout.parallelPrefix] - 1;
81675         } else {
81676             toCompBox[shadowLayout.parallelBefore] -= (placeholderBox[shadowLayout.parallelPrefix] - 1);
81677         }
81678         compEl.setStyle('visibility', 'hidden');
81679         compEl.setLeftTop(toCompBox.left, toCompBox.top);
81680
81681         
81682         
81683         curSize = comp.getSize();
81684         if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
81685             me.setItemSize(comp, toCompBox.width, toCompBox.height);
81686         }
81687
81688         
81689         compAnim = {
81690             listeners: {
81691                 afteranimate: function() {
81692                     shadowContainer.suspendLayout = scsl;
81693                     delete me.layoutBusy;
81694                     delete me.owner.componentLayout.layoutBusy;
81695
81696                     
81697                     compAnim.listeners = {
81698                         afterAnimate: function() {
81699                             compEl.show().removeCls(Ext.baseCSSPrefix + 'border-region-slide-in').setLeftTop(-10000, -10000);
81700
81701                             
81702                             comp.hidden = true;
81703                             comp.collapsed = true;
81704                             delete comp.slideOutAnim;
81705                             delete comp.panelMouseMon;
81706                             delete comp.placeholderMouseMon;
81707                         }
81708                     };
81709                     comp.slideOutAnim = compAnim;
81710                 }
81711             },
81712             duration: 500
81713         };
81714
81715         
81716         compEl.addCls(Ext.baseCSSPrefix + 'border-region-slide-in');
81717
81718         
81719         compEl.slideIn(me.slideDirection[comp.region], compAnim);
81720
81721         
81722         comp.panelMouseMon = compEl.monitorMouseLeave(500, onMouseLeaveFloated);
81723
81724     },
81725
81726     slideOutFloatedComponent: function(comp) {
81727         var compEl = comp.el,
81728             slideOutAnim;
81729
81730         
81731         compEl.un(comp.panelMouseMon);
81732         comp.placeholder.el.un(comp.placeholderMouseMon);
81733
81734         
81735         compEl.slideOut(this.slideDirection[comp.region], comp.slideOutAnim);
81736
81737         delete comp.slideOutAnim;
81738         delete comp.panelMouseMon;
81739         delete comp.placeholderMouseMon;
81740     },
81741
81742     
81743     onRegionDestroy: function(comp) {
81744         var placeholder = comp.placeholder;
81745         if (placeholder) {
81746             delete placeholder.ownerCt;
81747             placeholder.destroy();
81748         }
81749     },
81750
81751     
81752     onDestroy: function() {
81753         var me = this,
81754             shadowContainer = me.shadowContainer,
81755             embeddedContainer = me.embeddedContainer;
81756
81757         if (shadowContainer) {
81758             delete shadowContainer.ownerCt;
81759             Ext.destroy(shadowContainer);
81760         }
81761
81762         if (embeddedContainer) {
81763             delete embeddedContainer.ownerCt;
81764             Ext.destroy(embeddedContainer);
81765         }
81766         delete me.regions;
81767         delete me.splitters;
81768         delete me.shadowContainer;
81769         delete me.embeddedContainer;
81770         me.callParent(arguments);
81771     }
81772 });
81773
81774
81775 Ext.define('Ext.layout.container.Card', {
81776
81777     
81778
81779     alias: ['layout.card'],
81780     alternateClassName: 'Ext.layout.CardLayout',
81781
81782     extend: 'Ext.layout.container.AbstractCard',
81783
81784     
81785
81786     setActiveItem: function(newCard) {
81787         var me = this,
81788             owner = me.owner,
81789             oldCard = me.activeItem,
81790             newIndex;
81791
81792         
81793         me.layoutBusy = true;
81794
81795         newCard = me.parseActiveItem(newCard);
81796         newIndex = owner.items.indexOf(newCard);
81797
81798         
81799         if (newIndex == -1) {
81800             newIndex = owner.items.items.length;
81801             owner.add(newCard);
81802         }
81803
81804         
81805         if (newCard && oldCard != newCard) {
81806             
81807             if (!newCard.rendered) {
81808                 me.renderItem(newCard, me.getRenderTarget(), owner.items.length);
81809                 me.configureItem(newCard, 0);
81810             }
81811
81812             me.activeItem = newCard;
81813
81814             
81815             if (newCard.fireEvent('beforeactivate', newCard, oldCard) === false) {
81816                 me.layoutBusy = false;
81817                 return false;
81818             }
81819             if (oldCard && oldCard.fireEvent('beforedeactivate', oldCard, newCard) === false) {
81820                 me.layoutBusy = false;
81821                 return false;
81822             }
81823
81824             
81825             if (!me.sizeAllCards) {
81826                 me.setItemBox(newCard, me.getTargetBox());
81827             }
81828             else {
81829                 
81830                 me.onLayout();
81831             }
81832
81833             if (oldCard) {
81834                 if (me.hideInactive) {
81835                     oldCard.hide();
81836                 }
81837                 oldCard.fireEvent('deactivate', oldCard, newCard);
81838             }
81839
81840             
81841             if (newCard.hidden) {
81842                 newCard.show();
81843             }
81844
81845             newCard.fireEvent('activate', newCard, oldCard);
81846
81847             me.layoutBusy = false;
81848
81849             if (!me.sizeAllCards) {
81850                 if (!owner.componentLayout.layoutBusy) {
81851                     me.onLayout();
81852                 }
81853             }
81854             return newCard;
81855         }
81856
81857         me.layoutBusy = false;
81858         return false;
81859     }
81860 });
81861
81862 Ext.define('Ext.layout.container.Column', {
81863
81864     extend: 'Ext.layout.container.Auto',
81865     alias: ['layout.column'],
81866     alternateClassName: 'Ext.layout.ColumnLayout',
81867
81868     type: 'column',
81869
81870     itemCls: Ext.baseCSSPrefix + 'column',
81871
81872     targetCls: Ext.baseCSSPrefix + 'column-layout-ct',
81873
81874     scrollOffset: 0,
81875
81876     bindToOwnerCtComponent: false,
81877
81878     getRenderTarget : function() {
81879         if (!this.innerCt) {
81880
81881             
81882             
81883             this.innerCt = this.getTarget().createChild({
81884                 cls: Ext.baseCSSPrefix + 'column-inner'
81885             });
81886
81887             
81888             
81889             
81890             this.clearEl = this.innerCt.createChild({
81891                 cls: Ext.baseCSSPrefix + 'clear',
81892                 role: 'presentation'
81893             });
81894         }
81895         return this.innerCt;
81896     },
81897
81898     
81899     onLayout : function() {
81900         var me = this,
81901             target = me.getTarget(),
81902             items = me.getLayoutItems(),
81903             len = items.length,
81904             item,
81905             i,
81906             parallelMargins = [],
81907             itemParallelMargins,
81908             size,
81909             availableWidth,
81910             columnWidth;
81911
81912         size = me.getLayoutTargetSize();
81913         if (size.width < len * 10) { 
81914             return;
81915         }
81916
81917         
81918         
81919         
81920         if (me.adjustmentPass) {
81921             if (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) {
81922                 size.width = me.adjustedWidth;
81923             }
81924         } else {
81925             i = target.getStyle('overflow');
81926             if (i && i != 'hidden') {
81927                 me.autoScroll = true;
81928                 if (!(Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks)) {
81929                     target.setStyle('overflow', 'hidden');
81930                     size = me.getLayoutTargetSize();
81931                 }
81932             }
81933         }
81934
81935         availableWidth = size.width - me.scrollOffset;
81936         me.innerCt.setWidth(availableWidth);
81937
81938         
81939         
81940         for (i = 0; i < len; i++) {
81941             item = items[i];
81942             itemParallelMargins = parallelMargins[i] = item.getEl().getMargin('lr');
81943             if (!item.columnWidth) {
81944                 availableWidth -= (item.getWidth() + itemParallelMargins);
81945             }
81946         }
81947
81948         availableWidth = availableWidth < 0 ? 0 : availableWidth;
81949         for (i = 0; i < len; i++) {
81950             item = items[i];
81951             if (item.columnWidth) {
81952                 columnWidth = Math.floor(item.columnWidth * availableWidth) - parallelMargins[i];
81953                 if (item.getWidth() != columnWidth) {
81954                     me.setItemSize(item, columnWidth, item.height);
81955                 }
81956             }
81957         }
81958
81959         
81960         if (!me.adjustmentPass && me.autoScroll) {
81961
81962             
81963             target.setStyle('overflow', 'auto');
81964             me.adjustmentPass = (target.dom.scrollHeight > size.height);
81965             if (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) {
81966                 me.adjustedWidth = size.width - Ext.getScrollBarWidth();
81967             } else {
81968                 target.setStyle('overflow', 'auto');
81969             }
81970
81971             
81972             if (me.adjustmentPass) {
81973                 me.onLayout();
81974             }
81975         }
81976         delete me.adjustmentPass;
81977     }
81978 });
81979
81980
81981 Ext.define('Ext.layout.container.Table', {
81982
81983     
81984
81985     alias: ['layout.table'],
81986     extend: 'Ext.layout.container.Auto',
81987     alternateClassName: 'Ext.layout.TableLayout',
81988
81989     
81990
81991     
81992
81993     
81994     monitorResize:false,
81995
81996     type: 'table',
81997
81998     
81999     
82000     autoSize: true,
82001
82002     clearEl: true, 
82003
82004     targetCls: Ext.baseCSSPrefix + 'table-layout-ct',
82005     tableCls: Ext.baseCSSPrefix + 'table-layout',
82006     cellCls: Ext.baseCSSPrefix + 'table-layout-cell',
82007
82008     
82009     tableAttrs:null,
82010
82011     
82012     renderItems: function(items) {
82013         var tbody = this.getTable().tBodies[0],
82014             rows = tbody.rows,
82015             i = 0,
82016             len = items.length,
82017             cells, curCell, rowIdx, cellIdx, item, trEl, tdEl, itemCt;
82018
82019         
82020         cells = this.calculateCells(items);
82021
82022         
82023         
82024         
82025         for (; i < len; i++) {
82026             curCell = cells[i];
82027             rowIdx = curCell.rowIdx;
82028             cellIdx = curCell.cellIdx;
82029             item = items[i];
82030
82031             
82032             trEl = rows[rowIdx];
82033             if (!trEl) {
82034                 trEl = tbody.insertRow(rowIdx);
82035             }
82036
82037             
82038             itemCt = tdEl = Ext.get(trEl.cells[cellIdx] || trEl.insertCell(cellIdx));
82039             if (this.needsDivWrap()) { 
82040                 itemCt = tdEl.first() || tdEl.createChild({tag: 'div'});
82041                 itemCt.setWidth(null);
82042             }
82043
82044             
82045             if (!item.rendered) {
82046                 this.renderItem(item, itemCt, 0);
82047             }
82048             else if (!this.isValidParent(item, itemCt, 0)) {
82049                 this.moveItem(item, itemCt, 0);
82050             }
82051
82052             
82053             tdEl.set({
82054                 colSpan: item.colspan || 1,
82055                 rowSpan: item.rowspan || 1,
82056                 id: item.cellId || '',
82057                 cls: this.cellCls + ' ' + (item.cellCls || '')
82058             });
82059
82060             
82061             if (!cells[i + 1] || cells[i + 1].rowIdx !== rowIdx) {
82062                 cellIdx++;
82063                 while (trEl.cells[cellIdx]) {
82064                     trEl.deleteCell(cellIdx);
82065                 }
82066             }
82067         }
82068
82069         
82070         rowIdx++;
82071         while (tbody.rows[rowIdx]) {
82072             tbody.deleteRow(rowIdx);
82073         }
82074     },
82075
82076     afterLayout: function() {
82077         this.callParent();
82078
82079         if (this.needsDivWrap()) {
82080             
82081             Ext.Array.forEach(this.getLayoutItems(), function(item) {
82082                 Ext.fly(item.el.dom.parentNode).setWidth(item.getWidth());
82083             });
82084         }
82085     },
82086
82087     
82088     calculateCells: function(items) {
82089         var cells = [],
82090             rowIdx = 0,
82091             colIdx = 0,
82092             cellIdx = 0,
82093             totalCols = this.columns || Infinity,
82094             rowspans = [], 
82095             i = 0, j,
82096             len = items.length,
82097             item;
82098
82099         for (; i < len; i++) {
82100             item = items[i];
82101
82102             
82103             while (colIdx >= totalCols || rowspans[colIdx] > 0) {
82104                 if (colIdx >= totalCols) {
82105                     
82106                     colIdx = 0;
82107                     cellIdx = 0;
82108                     rowIdx++;
82109
82110                     
82111                     for (j = 0; j < totalCols; j++) {
82112                         if (rowspans[j] > 0) {
82113                             rowspans[j]--;
82114                         }
82115                     }
82116                 } else {
82117                     colIdx++;
82118                 }
82119             }
82120
82121             
82122             cells.push({
82123                 rowIdx: rowIdx,
82124                 cellIdx: cellIdx
82125             });
82126
82127             
82128             rowspans[colIdx] = item.rowspan || 1;
82129             colIdx += item.colspan || 1;
82130             cellIdx++;
82131         }
82132
82133         return cells;
82134     },
82135
82136     
82137     getTable: function() {
82138         var table = this.table;
82139         if (!table) {
82140             table = this.table = this.getTarget().createChild(
82141                 Ext.apply({
82142                     tag: 'table',
82143                     role: 'presentation',
82144                     cls: this.tableCls,
82145                     cellspacing: 0, 
82146                     cn: {tag: 'tbody'}
82147                 }, this.tableAttrs),
82148                 null, true
82149             );
82150         }
82151         return table;
82152     },
82153
82154     
82155     needsDivWrap: function() {
82156         return Ext.isOpera10_5;
82157     }
82158 });
82159
82160 Ext.define('Ext.menu.Item', {
82161     extend: 'Ext.Component',
82162     alias: 'widget.menuitem',
82163     alternateClassName: 'Ext.menu.TextItem',
82164     
82165     
82166
82167     
82168     activeCls: Ext.baseCSSPrefix + 'menu-item-active',
82169     
82170     
82171     ariaRole: 'menuitem',
82172     
82173     
82174     canActivate: true,
82175     
82176     
82177     clickHideDelay: 1,
82178     
82179     
82180     destroyMenu: true,
82181     
82182     
82183     disabledCls: Ext.baseCSSPrefix + 'menu-item-disabled',
82184     
82185     
82186      
82187      
82188     
82189     
82190     hideOnClick: true,
82191     
82192     
82193      
82194     
82195     
82196     isMenuItem: true,
82197     
82198     
82199     
82200     
82201     menuAlign: 'tl-tr?',
82202     
82203     
82204     menuExpandDelay: 200,
82205     
82206     
82207     menuHideDelay: 200,
82208     
82209     
82210     
82211     renderTpl: [
82212         '<tpl if="plain">',
82213             '{text}',
82214         '</tpl>',
82215         '<tpl if="!plain">',
82216             '<a class="' + Ext.baseCSSPrefix + 'menu-item-link" href="{href}" <tpl if="hrefTarget">target="{hrefTarget}"</tpl> hidefocus="true" unselectable="on">',
82217                 '<img src="{icon}" class="' + Ext.baseCSSPrefix + 'menu-item-icon {iconCls}" />',
82218                 '<span class="' + Ext.baseCSSPrefix + 'menu-item-text" <tpl if="menu">style="margin-right: 17px;"</tpl> >{text}</span>',
82219                 '<tpl if="menu">',
82220                     '<img src="' + Ext.BLANK_IMAGE_URL + '" class="' + Ext.baseCSSPrefix + 'menu-item-arrow" />',
82221                 '</tpl>',
82222             '</a>',
82223         '</tpl>'
82224     ],
82225     
82226     maskOnDisable: false,
82227     
82228     
82229     
82230     activate: function() {
82231         var me = this;
82232         
82233         if (!me.activated && me.canActivate && me.rendered && !me.isDisabled() && me.isVisible()) {
82234             me.el.addCls(me.activeCls);
82235             me.focus();
82236             me.activated = true;
82237             me.fireEvent('activate', me);
82238         }
82239     },
82240     
82241     blur: function() {
82242         this.$focused = false;
82243         this.callParent(arguments);
82244     },
82245     
82246     deactivate: function() {
82247         var me = this;
82248         
82249         if (me.activated) {
82250             me.el.removeCls(me.activeCls);
82251             me.blur();
82252             me.hideMenu();
82253             me.activated = false;
82254             me.fireEvent('deactivate', me);
82255         }
82256     },
82257     
82258     deferExpandMenu: function() {
82259         var me = this;
82260         
82261         if (!me.menu.rendered || !me.menu.isVisible()) {
82262             me.parentMenu.activeChild = me.menu;
82263             me.menu.parentItem = me;
82264             me.menu.parentMenu = me.menu.ownerCt = me.parentMenu;
82265             me.menu.showBy(me, me.menuAlign);
82266         }
82267     },
82268     
82269     deferHideMenu: function() {
82270         if (this.menu.isVisible()) {
82271             this.menu.hide();
82272         }
82273     },
82274     
82275     deferHideParentMenus: function() {
82276         Ext.menu.Manager.hideAll();
82277     },
82278     
82279     expandMenu: function(delay) {
82280         var me = this;
82281         
82282         if (me.menu) {
82283             clearTimeout(me.hideMenuTimer);
82284             if (delay === 0) {
82285                 me.deferExpandMenu();
82286             } else {
82287                 me.expandMenuTimer = Ext.defer(me.deferExpandMenu, Ext.isNumber(delay) ? delay : me.menuExpandDelay, me);
82288             }
82289         }
82290     },
82291     
82292     focus: function() {
82293         this.$focused = true;
82294         this.callParent(arguments);
82295     },
82296     
82297     getRefItems: function(deep){
82298         var menu = this.menu,
82299             items;
82300         
82301         if (menu) {
82302             items = menu.getRefItems(deep);
82303             items.unshift(menu);
82304         }   
82305         return items || [];   
82306     },
82307     
82308     hideMenu: function(delay) {
82309         var me = this;
82310         
82311         if (me.menu) {
82312             clearTimeout(me.expandMenuTimer);
82313             me.hideMenuTimer = Ext.defer(me.deferHideMenu, Ext.isNumber(delay) ? delay : me.menuHideDelay, me);
82314         }
82315     },
82316     
82317     initComponent: function() {
82318         var me = this,
82319             prefix = Ext.baseCSSPrefix,
82320             cls = [prefix + 'menu-item'];
82321         
82322         me.addEvents(
82323             
82324             'activate',
82325             
82326             
82327             'click',
82328             
82329             
82330             'deactivate'
82331         );
82332         
82333         if (me.plain) {
82334             cls.push(prefix + 'menu-item-plain');
82335         }
82336         
82337         if (me.cls) {
82338             cls.push(me.cls);
82339         }
82340         
82341         me.cls = cls.join(' ');
82342         
82343         if (me.menu) {
82344             me.menu = Ext.menu.Manager.get(me.menu);
82345         }
82346         
82347         me.callParent(arguments);
82348     },
82349     
82350     onClick: function(e) {
82351         var me = this;
82352         
82353         if (!me.href) {
82354             e.stopEvent();
82355         }
82356         
82357         if (me.disabled) {
82358             return;
82359         }
82360         
82361         if (me.hideOnClick) {
82362             me.deferHideParentMenusTimer = Ext.defer(me.deferHideParentMenus, me.clickHideDelay, me);
82363         }
82364         
82365         Ext.callback(me.handler, me.scope || me, [me, e]);
82366         me.fireEvent('click', me, e);
82367         
82368         if (!me.hideOnClick) {
82369             me.focus();
82370         }
82371     },
82372     
82373     onDestroy: function() {
82374         var me = this;
82375         
82376         clearTimeout(me.expandMenuTimer);
82377         clearTimeout(me.hideMenuTimer);
82378         clearTimeout(me.deferHideParentMenusTimer);
82379         
82380         if (me.menu) {
82381             delete me.menu.parentItem;
82382             delete me.menu.parentMenu;
82383             delete me.menu.ownerCt;
82384             if (me.destroyMenu !== false) {
82385                 me.menu.destroy();
82386             }
82387         }
82388         me.callParent(arguments);
82389     },
82390     
82391     onRender: function(ct, pos) {
82392         var me = this,
82393             prefix = '.' + Ext.baseCSSPrefix;
82394         
82395         Ext.applyIf(me.renderData, {
82396             href: me.href || '#',
82397             hrefTarget: me.hrefTarget,
82398             icon: me.icon || Ext.BLANK_IMAGE_URL,
82399             iconCls: me.iconCls,
82400             menu: Ext.isDefined(me.menu),
82401             plain: me.plain,
82402             text: me.text
82403         });
82404         
82405         Ext.applyIf(me.renderSelectors, {
82406             itemEl: prefix + 'menu-item-link',
82407             iconEl: prefix + 'menu-item-icon',
82408             textEl: prefix + 'menu-item-text',
82409             arrowEl: prefix + 'menu-item-arrow'
82410         });
82411         
82412         me.callParent(arguments);
82413     },
82414     
82415     
82416     setHandler: function(fn, scope) {
82417         this.handler = fn || null;
82418         this.scope = scope;
82419     },
82420     
82421     
82422     setIconCls: function(iconCls) {
82423         var me = this;
82424         
82425         if (me.iconEl) {
82426             if (me.iconCls) {
82427                 me.iconEl.removeCls(me.iconCls);
82428             }
82429             
82430             if (iconCls) {
82431                 me.iconEl.addCls(iconCls);
82432             }
82433         }
82434         
82435         me.iconCls = iconCls;
82436     },
82437     
82438     
82439     setText: function(text) {
82440         var me = this,
82441             el = me.textEl || me.el,
82442             newWidth;
82443         
82444         if (text && el) {
82445             el.update(text);
82446                 
82447             if (me.textEl) {
82448                 
82449                 newWidth = me.textEl.getWidth() + me.iconEl.getWidth() + 25 + (me.arrowEl ? me.arrowEl.getWidth() : 0);
82450                 if (newWidth > me.itemEl.getWidth()) {
82451                     me.parentMenu.setWidth(newWidth);
82452                 }
82453             }
82454         } else if (el) {
82455             el.update('');
82456         }
82457         
82458         me.text = text;
82459     }
82460 });
82461
82462
82463
82464 Ext.define('Ext.menu.CheckItem', {
82465     extend: 'Ext.menu.Item',
82466     alias: 'widget.menucheckitem',
82467
82468     
82469     checkedCls: Ext.baseCSSPrefix + 'menu-item-checked',
82470     
82471     uncheckedCls: Ext.baseCSSPrefix + 'menu-item-unchecked',
82472     
82473     groupCls: Ext.baseCSSPrefix + 'menu-group-icon',
82474
82475     
82476     hideOnClick: false,
82477
82478     afterRender: function() {
82479         var me = this;
82480         this.callParent();
82481         me.checked = !me.checked;
82482         me.setChecked(!me.checked, true);
82483     },
82484
82485     initComponent: function() {
82486         var me = this;
82487         me.addEvents(
82488             
82489             'beforecheckchange',
82490
82491             
82492             'checkchange'
82493         );
82494
82495         me.callParent(arguments);
82496
82497         Ext.menu.Manager.registerCheckable(me);
82498
82499         if (me.group) {
82500             if (!me.iconCls) {
82501                 me.iconCls = me.groupCls;
82502             }
82503             if (me.initialConfig.hideOnClick !== false) {
82504                 me.hideOnClick = true;
82505             }
82506         }
82507     },
82508
82509     
82510     disableCheckChange: function() {
82511         var me = this;
82512
82513         me.iconEl.addCls(me.disabledCls);
82514         me.checkChangeDisabled = true;
82515     },
82516
82517     
82518     enableCheckChange: function() {
82519         var me = this;
82520
82521         me.iconEl.removeCls(me.disabledCls);
82522         me.checkChangeDisabled = false;
82523     },
82524
82525     onClick: function(e) {
82526         var me = this;
82527         if(!me.disabled && !me.checkChangeDisabled && !(me.checked && me.group)) {
82528             me.setChecked(!me.checked);
82529         }
82530         this.callParent([e]);
82531     },
82532
82533     onDestroy: function() {
82534         Ext.menu.Manager.unregisterCheckable(this);
82535         this.callParent(arguments);
82536     },
82537
82538     
82539     setChecked: function(checked, suppressEvents) {
82540         var me = this;
82541         if (me.checked !== checked && (suppressEvents || me.fireEvent('beforecheckchange', me, checked) !== false)) {
82542             if (me.el) {
82543                 me.el[checked  ? 'addCls' : 'removeCls'](me.checkedCls)[!checked ? 'addCls' : 'removeCls'](me.uncheckedCls);
82544             }
82545             me.checked = checked;
82546             Ext.menu.Manager.onCheckChange(me, checked);
82547             if (!suppressEvents) {
82548                 Ext.callback(me.checkHandler, me.scope, [me, checked]);
82549                 me.fireEvent('checkchange', me, checked);
82550             }
82551         }
82552     }
82553 });
82554
82555
82556 Ext.define('Ext.menu.KeyNav', {
82557     extend: 'Ext.util.KeyNav',
82558
82559     requires: ['Ext.FocusManager'],
82560     
82561     constructor: function(menu) {
82562         var me = this;
82563
82564         me.menu = menu;
82565         me.callParent([menu.el, {
82566             down: me.down,
82567             enter: me.enter,
82568             esc: me.escape,
82569             left: me.left,
82570             right: me.right,
82571             space: me.enter,
82572             tab: me.tab,
82573             up: me.up
82574         }]);
82575     },
82576
82577     down: function(e) {
82578         var me = this,
82579             fi = me.menu.focusedItem;
82580
82581         if (fi && e.getKey() == Ext.EventObject.DOWN && me.isWhitelisted(fi)) {
82582             return true;
82583         }
82584         me.focusNextItem(1);
82585     },
82586
82587     enter: function(e) {
82588         var menu = this.menu;
82589
82590         if (menu.activeItem) {
82591             menu.onClick(e);
82592         }
82593     },
82594
82595     escape: function(e) {
82596         Ext.menu.Manager.hideAll();
82597     },
82598
82599     focusNextItem: function(step) {
82600         var menu = this.menu,
82601             items = menu.items,
82602             focusedItem = menu.focusedItem,
82603             startIdx = focusedItem ? items.indexOf(focusedItem) : -1,
82604             idx = startIdx + step;
82605
82606         while (idx != startIdx) {
82607             if (idx < 0) {
82608                 idx = items.length - 1;
82609             } else if (idx >= items.length) {
82610                 idx = 0;
82611             }
82612
82613             var item = items.getAt(idx);
82614             if (menu.canActivateItem(item)) {
82615                 menu.setActiveItem(item);
82616                 break;
82617             }
82618             idx += step;
82619         }
82620     },
82621
82622     isWhitelisted: function(item) {
82623         return Ext.FocusManager.isWhitelisted(item);
82624     },
82625
82626     left: function(e) {
82627         var menu = this.menu,
82628             fi = menu.focusedItem,
82629             ai = menu.activeItem;
82630
82631         if (fi && this.isWhitelisted(fi)) {
82632             return true;
82633         }
82634
82635         menu.hide();
82636         if (menu.parentMenu) {
82637             menu.parentMenu.focus();
82638         }
82639     },
82640
82641     right: function(e) {
82642         var menu = this.menu,
82643             fi = menu.focusedItem,
82644             ai = menu.activeItem,
82645             am;
82646
82647         if (fi && this.isWhitelisted(fi)) {
82648             return true;
82649         }
82650
82651         if (ai) {
82652             am = menu.activeItem.menu;
82653             if (am) {
82654                 ai.expandMenu(0);
82655                 Ext.defer(function() {
82656                     am.setActiveItem(am.items.getAt(0));
82657                 }, 25);
82658             }
82659         }
82660     },
82661
82662     tab: function(e) {
82663         var me = this;
82664
82665         if (e.shiftKey) {
82666             me.up(e);
82667         } else {
82668             me.down(e);
82669         }
82670     },
82671
82672     up: function(e) {
82673         var me = this,
82674             fi = me.menu.focusedItem;
82675
82676         if (fi && e.getKey() == Ext.EventObject.UP && me.isWhitelisted(fi)) {
82677             return true;
82678         }
82679         me.focusNextItem(-1);
82680     }
82681 });
82682
82683 Ext.define('Ext.menu.Separator', {
82684     extend: 'Ext.menu.Item',
82685     alias: 'widget.menuseparator',
82686     
82687     
82688     
82689     
82690     canActivate: false,
82691     
82692     
82693      
82694     
82695      
82696     
82697      
82698     focusable: false,
82699      
82700     
82701     
82702     
82703     
82704     
82705     hideOnClick: false,
82706     
82707     
82708     
82709     
82710     
82711     
82712     
82713     
82714     
82715     
82716     
82717     
82718     
82719     
82720     plain: true,
82721     
82722     
82723     separatorCls: Ext.baseCSSPrefix + 'menu-item-separator',
82724     
82725     
82726     text: '&#160;',
82727     
82728     onRender: function(ct, pos) {
82729         var me = this,
82730             sepCls = me.separatorCls;
82731             
82732         me.cls += ' ' + sepCls;
82733         
82734         Ext.applyIf(me.renderSelectors, {
82735             itemSepEl: '.' + sepCls
82736         });
82737         
82738         me.callParent(arguments);
82739     }
82740 });
82741
82742 Ext.define('Ext.menu.Menu', {
82743     extend: 'Ext.panel.Panel',
82744     alias: 'widget.menu',
82745     requires: [
82746         'Ext.layout.container.Fit',
82747         'Ext.layout.container.VBox',
82748         'Ext.menu.CheckItem',
82749         'Ext.menu.Item',
82750         'Ext.menu.KeyNav',
82751         'Ext.menu.Manager',
82752         'Ext.menu.Separator'
82753     ],
82754
82755     
82756     allowOtherMenus: false,
82757
82758     
82759     ariaRole: 'menu',
82760
82761     
82762
82763     
82764     defaultAlign: 'tl-bl?',
82765
82766     
82767     floating: true,
82768
82769     
82770     constrain: false,
82771
82772     
82773     hidden: true,
82774
82775     
82776     ignoreParentClicks: false,
82777
82778     isMenu: true,
82779
82780     
82781
82782     
82783     showSeparator : true,
82784
82785     
82786     minWidth: 120,
82787
82788     
82789
82790     initComponent: function() {
82791         var me = this,
82792             prefix = Ext.baseCSSPrefix;
82793
82794         me.addEvents(
82795             
82796             'click',
82797
82798             
82799             'mouseenter',
82800
82801             
82802             'mouseleave',
82803
82804             
82805             'mouseover'
82806         );
82807
82808         Ext.menu.Manager.register(me);
82809
82810         
82811         var cls = [prefix + 'menu'];
82812         if (me.plain) {
82813             cls.push(prefix + 'menu-plain');
82814         }
82815         me.cls = cls.join(' ');
82816
82817         
82818         var bodyCls = me.bodyCls ? [me.bodyCls] : [];
82819         bodyCls.unshift(prefix + 'menu-body');
82820         me.bodyCls = bodyCls.join(' ');
82821
82822         
82823         
82824         
82825         
82826         me.layout = {
82827             type: 'vbox',
82828             align: 'stretchmax',
82829             autoSize: true,
82830             clearInnerCtOnLayout: true,
82831             overflowHandler: 'Scroller'
82832         };
82833
82834         
82835         if (me.floating === false && me.initialConfig.hidden !== true) {
82836             me.hidden = false;
82837         }
82838
82839         me.callParent(arguments);
82840
82841         me.on('beforeshow', function() {
82842             var hasItems = !!me.items.length;
82843             
82844             
82845             
82846             if (hasItems && me.rendered) {
82847                 me.el.setStyle('visibility', null);
82848             }
82849             return hasItems;
82850         });
82851     },
82852
82853     afterRender: function(ct) {
82854         var me = this,
82855             prefix = Ext.baseCSSPrefix,
82856             space = '&#160;';
82857
82858         me.callParent(arguments);
82859
82860         
82861         if (me.showSeparator) {
82862             me.iconSepEl = me.layout.getRenderTarget().insertFirst({
82863                 cls: prefix + 'menu-icon-separator',
82864                 html: space
82865             });
82866         }
82867
82868         me.focusEl = me.el.createChild({
82869             cls: prefix + 'menu-focus',
82870             tabIndex: '-1',
82871             html: space
82872         });
82873
82874         me.mon(me.el, {
82875             click: me.onClick,
82876             mouseover: me.onMouseOver,
82877             scope: me
82878         });
82879         me.mouseMonitor = me.el.monitorMouseLeave(100, me.onMouseLeave, me);
82880
82881         if (me.showSeparator && ((!Ext.isStrict && Ext.isIE) || Ext.isIE6)) {
82882             me.iconSepEl.setHeight(me.el.getHeight());
82883         }
82884
82885         me.keyNav = Ext.create('Ext.menu.KeyNav', me);
82886     },
82887
82888     afterLayout: function() {
82889         var me = this;
82890         me.callParent(arguments);
82891
82892         
82893         
82894         
82895         
82896         if ((!Ext.iStrict && Ext.isIE) || Ext.isIE6) {
82897             var innerCt = me.layout.getRenderTarget(),
82898                 innerCtWidth = 0,
82899                 dis = me.dockedItems,
82900                 l = dis.length,
82901                 i = 0,
82902                 di, clone, newWidth;
82903
82904             innerCtWidth = innerCt.getWidth();
82905
82906             newWidth = innerCtWidth + me.body.getBorderWidth('lr') + me.body.getPadding('lr');
82907
82908             
82909             me.body.setWidth(newWidth);
82910
82911             
82912             for (; i < l, di = dis.getAt(i); i++) {
82913                 if (di.dock == 'left' || di.dock == 'right') {
82914                     newWidth += di.getWidth();
82915                 }
82916             }
82917             me.el.setWidth(newWidth);
82918         }
82919     },
82920
82921     
82922     canActivateItem: function(item) {
82923         return item && !item.isDisabled() && item.isVisible() && (item.canActivate || item.getXTypes().indexOf('menuitem') < 0);
82924     },
82925
82926     
82927     deactivateActiveItem: function() {
82928         var me = this;
82929
82930         if (me.activeItem) {
82931             me.activeItem.deactivate();
82932             if (!me.activeItem.activated) {
82933                 delete me.activeItem;
82934             }
82935         }
82936         if (me.focusedItem) {
82937             me.focusedItem.blur();
82938             if (!me.focusedItem.$focused) {
82939                 delete me.focusedItem;
82940             }
82941         }
82942     },
82943
82944     
82945     getFocusEl: function() {
82946         return this.focusEl;
82947     },
82948
82949     
82950     hide: function() {
82951         this.deactivateActiveItem();
82952         this.callParent(arguments);
82953     },
82954
82955     
82956     getItemFromEvent: function(e) {
82957         return this.getChildByElement(e.getTarget());
82958     },
82959
82960     lookupComponent: function(cmp) {
82961         var me = this;
82962
82963         if (Ext.isString(cmp)) {
82964             cmp = me.lookupItemFromString(cmp);
82965         } else if (Ext.isObject(cmp)) {
82966             cmp = me.lookupItemFromObject(cmp);
82967         }
82968
82969         
82970         
82971         cmp.minWidth = cmp.minWidth || me.minWidth;
82972
82973         return cmp;
82974     },
82975
82976     
82977     lookupItemFromObject: function(cmp) {
82978         var me = this,
82979             prefix = Ext.baseCSSPrefix;
82980
82981         if (!cmp.isComponent) {
82982             if (!cmp.xtype) {
82983                 cmp = Ext.create('Ext.menu.' + (Ext.isBoolean(cmp.checked) ? 'Check': '') + 'Item', cmp);
82984             } else {
82985                 cmp = Ext.ComponentManager.create(cmp, cmp.xtype);
82986             }
82987         }
82988
82989         if (cmp.isMenuItem) {
82990             cmp.parentMenu = me;
82991         }
82992
82993         if (!cmp.isMenuItem && !cmp.dock) {
82994             var cls = [
82995                     prefix + 'menu-item',
82996                     prefix + 'menu-item-cmp'
82997                 ],
82998                 intercept = Ext.Function.createInterceptor;
82999
83000             
83001             cmp.focus = intercept(cmp.focus, function() {
83002                 this.$focused = true;
83003             }, cmp);
83004             cmp.blur = intercept(cmp.blur, function() {
83005                 this.$focused = false;
83006             }, cmp);
83007
83008             if (!me.plain && (cmp.indent === true || cmp.iconCls === 'no-icon')) {
83009                 cls.push(prefix + 'menu-item-indent');
83010             }
83011
83012             if (cmp.rendered) {
83013                 cmp.el.addCls(cls);
83014             } else {
83015                 cmp.cls = (cmp.cls ? cmp.cls : '') + ' ' + cls.join(' ');
83016             }
83017             cmp.isMenuItem = true;
83018         }
83019         return cmp;
83020     },
83021
83022     
83023     lookupItemFromString: function(cmp) {
83024         return (cmp == 'separator' || cmp == '-') ?
83025             Ext.createWidget('menuseparator')
83026             : Ext.createWidget('menuitem', {
83027                 canActivate: false,
83028                 hideOnClick: false,
83029                 plain: true,
83030                 text: cmp
83031             });
83032     },
83033
83034     onClick: function(e) {
83035         var me = this,
83036             item;
83037
83038         if (me.disabled) {
83039             e.stopEvent();
83040             return;
83041         }
83042
83043         if ((e.getTarget() == me.focusEl.dom) || e.within(me.layout.getRenderTarget())) {
83044             item = me.getItemFromEvent(e) || me.activeItem;
83045
83046             if (item) {
83047                 if (item.getXTypes().indexOf('menuitem') >= 0) {
83048                     if (!item.menu || !me.ignoreParentClicks) {
83049                         item.onClick(e);
83050                     } else {
83051                         e.stopEvent();
83052                     }
83053                 }
83054             }
83055             me.fireEvent('click', me, item, e);
83056         }
83057     },
83058
83059     onDestroy: function() {
83060         var me = this;
83061
83062         Ext.menu.Manager.unregister(me);
83063         if (me.rendered) {
83064             me.el.un(me.mouseMonitor);
83065             me.keyNav.destroy();
83066             delete me.keyNav;
83067         }
83068         me.callParent(arguments);
83069     },
83070
83071     onMouseLeave: function(e) {
83072         var me = this;
83073
83074         me.deactivateActiveItem();
83075
83076         if (me.disabled) {
83077             return;
83078         }
83079
83080         me.fireEvent('mouseleave', me, e);
83081     },
83082
83083     onMouseOver: function(e) {
83084         var me = this,
83085             fromEl = e.getRelatedTarget(),
83086             mouseEnter = !me.el.contains(fromEl),
83087             item = me.getItemFromEvent(e);
83088
83089         if (mouseEnter && me.parentMenu) {
83090             me.parentMenu.setActiveItem(me.parentItem);
83091             me.parentMenu.mouseMonitor.mouseenter();
83092         }
83093
83094         if (me.disabled) {
83095             return;
83096         }
83097
83098         if (item) {
83099             me.setActiveItem(item);
83100             if (item.activated && item.expandMenu) {
83101                 item.expandMenu();
83102             }
83103         }
83104         if (mouseEnter) {
83105             me.fireEvent('mouseenter', me, e);
83106         }
83107         me.fireEvent('mouseover', me, item, e);
83108     },
83109
83110     setActiveItem: function(item) {
83111         var me = this;
83112
83113         if (item && (item != me.activeItem && item != me.focusedItem)) {
83114             me.deactivateActiveItem();
83115             if (me.canActivateItem(item)) {
83116                 if (item.activate) {
83117                     item.activate();
83118                     if (item.activated) {
83119                         me.activeItem = item;
83120                         me.focusedItem = item;
83121                         me.focus();
83122                     }
83123                 } else {
83124                     item.focus();
83125                     me.focusedItem = item;
83126                 }
83127             }
83128             item.el.scrollIntoView(me.layout.getRenderTarget());
83129         }
83130     },
83131
83132     
83133     showBy: function(cmp, pos, off) {
83134         var me = this;
83135
83136         if (me.floating && cmp) {
83137             me.layout.autoSize = true;
83138             me.show();
83139
83140             
83141             cmp = cmp.el || cmp;
83142
83143             
83144             var xy = me.el.getAlignToXY(cmp, pos || me.defaultAlign, off);
83145             if (me.floatParent) {
83146                 var r = me.floatParent.getTargetEl().getViewRegion();
83147                 xy[0] -= r.x;
83148                 xy[1] -= r.y;
83149             }
83150             me.showAt(xy);
83151             me.doConstrain();
83152         }
83153         return me;
83154     },
83155
83156     doConstrain : function() {
83157         var me = this,
83158             y = this.el.getY(),
83159             max, full,
83160             returnY = y, normalY, parentEl, scrollTop, viewHeight;
83161
83162         delete me.height;
83163         me.setSize();
83164         full = me.getHeight();
83165         if (me.floating) {
83166             parentEl = Ext.fly(me.el.dom.parentNode);
83167             scrollTop = parentEl.getScroll().top;
83168             viewHeight = parentEl.getViewSize().height;
83169             
83170             
83171             normalY = y - scrollTop;
83172             max = me.maxHeight ? me.maxHeight : viewHeight - normalY;
83173             if (full > viewHeight) {
83174                 max = viewHeight;
83175                 
83176                 returnY = y - normalY;
83177             } else if (max < full) {
83178                 returnY = y - (full - max);
83179                 max = full;
83180             }
83181         }else{
83182             max = me.getHeight();
83183         }
83184         
83185         if (me.maxHeight){
83186             max = Math.min(me.maxHeight, max);
83187         }
83188         if (full > max && max > 0){
83189             me.layout.autoSize = false;
83190             me.setHeight(max);
83191             if (me.showSeparator){
83192                 me.iconSepEl.setHeight(me.layout.getRenderTarget().dom.scrollHeight);
83193             }
83194         }
83195         me.el.setY(returnY);
83196     }
83197 });
83198
83199  Ext.define('Ext.menu.ColorPicker', {
83200      extend: 'Ext.menu.Menu',
83201
83202      alias: 'widget.colormenu',
83203
83204      requires: [
83205         'Ext.picker.Color'
83206      ],
83207
83208     
83209     hideOnClick : true,
83210
83211     
83212     pickerId : null,
83213
83214     
83215
83216     
83217
83218     
83219
83220     
83221
83222     initComponent : function(){
83223         var me = this;
83224
83225         Ext.apply(me, {
83226             plain: true,
83227             showSeparator: false,
83228             items: Ext.applyIf({
83229                 cls: Ext.baseCSSPrefix + 'menu-color-item',
83230                 id: me.pickerId,
83231                 xtype: 'colorpicker'
83232             }, me.initialConfig)
83233         });
83234
83235         me.callParent(arguments);
83236
83237         me.picker = me.down('colorpicker');
83238
83239         
83240         me.relayEvents(me.picker, ['select']);
83241
83242         if (me.hideOnClick) {
83243             me.on('select', me.hidePickerOnSelect, me);
83244         }
83245     },
83246
83247     
83248     hidePickerOnSelect: function() {
83249         Ext.menu.Manager.hideAll();
83250     }
83251  });
83252
83253  Ext.define('Ext.menu.DatePicker', {
83254      extend: 'Ext.menu.Menu',
83255
83256      alias: 'widget.datemenu',
83257
83258      requires: [
83259         'Ext.picker.Date'
83260      ],
83261
83262     
83263     hideOnClick : true,
83264
83265     
83266     pickerId : null,
83267
83268     
83269
83270     
83271
83272     
83273
83274     
83275
83276     initComponent : function(){
83277         var me = this;
83278
83279         Ext.apply(me, {
83280             showSeparator: false,
83281             plain: true,
83282             items: Ext.applyIf({
83283                 cls: Ext.baseCSSPrefix + 'menu-date-item',
83284                 id: me.pickerId,
83285                 xtype: 'datepicker'
83286             }, me.initialConfig)
83287         });
83288
83289         me.callParent(arguments);
83290
83291         me.picker = me.down('datepicker');
83292         
83293         me.relayEvents(me.picker, ['select']);
83294
83295         if (me.hideOnClick) {
83296             me.on('select', me.hidePickerOnSelect, me);
83297         }
83298     },
83299
83300     hidePickerOnSelect: function() {
83301         Ext.menu.Manager.hideAll();
83302     }
83303  });
83304
83305 Ext.define('Ext.panel.Tool', {
83306     extend: 'Ext.Component',
83307     requires: ['Ext.tip.QuickTipManager'],
83308     alias: 'widget.tool',
83309
83310     baseCls: Ext.baseCSSPrefix + 'tool',
83311     disabledCls: Ext.baseCSSPrefix + 'tool-disabled',
83312     toolPressedCls: Ext.baseCSSPrefix + 'tool-pressed',
83313     toolOverCls: Ext.baseCSSPrefix + 'tool-over',
83314     ariaRole: 'button',
83315     renderTpl: ['<img src="{blank}" class="{baseCls}-{type}" role="presentation"/>'],
83316     
83317     
83318     
83319     
83320     
83321     
83322     
83323     
83324     
83325     
83326     stopEvent: true,
83327
83328     initComponent: function() {
83329         var me = this;
83330         me.addEvents(
83331             
83332             'click'
83333         );
83334         
83335         var types = [
83336             'close', 
83337             'collapse', 
83338             'down', 
83339             'expand', 
83340             'gear', 
83341             'help', 
83342             'left', 
83343             'maximize', 
83344             'minimize', 
83345             'minus', 
83346             'move', 
83347             'next', 
83348             'pin', 
83349             'plus', 
83350             'prev', 
83351             'print', 
83352             'refresh', 
83353             'resize', 
83354             'restore', 
83355             'right', 
83356             'save', 
83357             'search', 
83358             'toggle',
83359             'unpin', 
83360             'up'
83361         ];
83362         
83363         if (me.id && Ext.Array.indexOf(types, me.id) > -1) {
83364             Ext.global.console.warn('When specifying a tool you should use the type option, the id can conflict now that tool is a Component');
83365         }
83366         
83367         me.type = me.type || me.id;
83368
83369         Ext.applyIf(me.renderData, {
83370             baseCls: me.baseCls,
83371             blank: Ext.BLANK_IMAGE_URL,
83372             type: me.type
83373         });
83374         me.renderSelectors.toolEl = '.' + me.baseCls + '-' + me.type;
83375         me.callParent();
83376     },
83377
83378     
83379     afterRender: function() {
83380         var me = this;
83381         me.callParent(arguments);
83382         if (me.qtip) {
83383             if (Ext.isObject(me.qtip)) {
83384                 Ext.tip.QuickTipManager.register(Ext.apply({
83385                     target: me.id
83386                 }, me.qtip));
83387             }
83388             else {
83389                 me.toolEl.dom.qtip = me.qtip;
83390             }
83391         }
83392
83393         me.mon(me.toolEl, {
83394             click: me.onClick,
83395             mousedown: me.onMouseDown,
83396             mouseover: me.onMouseOver,
83397             mouseout: me.onMouseOut,
83398             scope: me
83399         });
83400     },
83401
83402     
83403     setType: function(type) {
83404         var me = this;
83405         
83406         me.type = type;
83407         if (me.rendered) {
83408             me.toolEl.dom.className = me.baseCls + '-' + type;
83409         }
83410         return me;
83411     },
83412
83413     
83414     bindTo: function(component) {
83415         this.owner = component;
83416     },
83417
83418     
83419     onClick: function(e, target) {
83420         var me = this,
83421             owner;
83422             
83423         if (me.disabled) {
83424             return false;
83425         }
83426         owner = me.owner || me.ownerCt;
83427
83428         
83429         me.el.removeCls(me.toolPressedCls);
83430         me.el.removeCls(me.toolOverCls);
83431
83432         if (me.stopEvent !== false) {
83433             e.stopEvent();
83434         }
83435
83436         Ext.callback(me.handler, me.scope || me, [e, target, owner, me]);
83437         me.fireEvent('click', me, e);
83438         return true;
83439     },
83440     
83441     
83442     onDestroy: function(){
83443         if (Ext.isObject(this.tooltip)) {
83444             Ext.tip.QuickTipManager.unregister(this.id);
83445         }    
83446         this.callParent();
83447     },
83448
83449     
83450     onMouseDown: function() {
83451         if (this.disabled) {
83452             return false;
83453         }
83454
83455         this.el.addCls(this.toolPressedCls);
83456     },
83457
83458     
83459     onMouseOver: function() {
83460         if (this.disabled) {
83461             return false;
83462         }
83463         this.el.addCls(this.toolOverCls);
83464     },
83465
83466     
83467     onMouseOut: function() {
83468         this.el.removeCls(this.toolOverCls);
83469     }
83470 });
83471
83472 Ext.define('Ext.resizer.Handle', {
83473     extend: 'Ext.Component',
83474     handleCls: '',
83475     baseHandleCls: Ext.baseCSSPrefix + 'resizable-handle',
83476     
83477     
83478     region: '',
83479
83480     onRender: function() {
83481         this.addCls(
83482             this.baseHandleCls,
83483             this.baseHandleCls + '-' + this.region,
83484             this.handleCls
83485         );
83486         this.callParent(arguments);
83487         this.el.unselectable();
83488     }
83489 });
83490
83491
83492 Ext.define('Ext.resizer.Resizer', {
83493     mixins: {
83494         observable: 'Ext.util.Observable'
83495     },
83496     uses: ['Ext.resizer.ResizeTracker', 'Ext.Component'],
83497
83498     alternateClassName: 'Ext.Resizable',
83499
83500     handleCls: Ext.baseCSSPrefix + 'resizable-handle',
83501     pinnedCls: Ext.baseCSSPrefix + 'resizable-pinned',
83502     overCls:   Ext.baseCSSPrefix + 'resizable-over',
83503     proxyCls:  Ext.baseCSSPrefix + 'resizable-proxy',
83504     wrapCls:   Ext.baseCSSPrefix + 'resizable-wrap',
83505
83506     
83507     dynamic: true,
83508
83509     
83510     handles: 's e se',
83511
83512     
83513     height : null,
83514
83515     
83516     width : null,
83517
83518     
83519     minHeight : 20,
83520
83521     
83522     minWidth : 20,
83523
83524     
83525     maxHeight : 10000,
83526
83527     
83528     maxWidth : 10000,
83529
83530     
83531     pinned: false,
83532
83533     
83534     preserveRatio: false,
83535
83536     
83537     transparent: false,
83538
83539     
83540
83541     possiblePositions: {
83542         n:  'north',
83543         s:  'south',
83544         e:  'east',
83545         w:  'west',
83546         se: 'southeast',
83547         sw: 'southwest',
83548         nw: 'northwest',
83549         ne: 'northeast'
83550     },
83551
83552     
83553
83554     
83555
83556     constructor: function(config) {
83557         var me = this,
83558             target,
83559             tag,
83560             handles = me.handles,
83561             handleCls,
83562             possibles,
83563             len,
83564             i = 0,
83565             pos;
83566
83567         this.addEvents(
83568             
83569             'beforeresize',
83570             
83571             'resizedrag',
83572             
83573             'resize'
83574         );
83575
83576         if (Ext.isString(config) || Ext.isElement(config) || config.dom) {
83577             target = config;
83578             config = arguments[1] || {};
83579             config.target = target;
83580         }
83581         
83582         me.mixins.observable.constructor.call(me, config);
83583
83584         
83585         
83586         target = me.target;
83587         if (target) {
83588             if (target.isComponent) {
83589                 me.el = target.getEl();
83590                 if (target.minWidth) {
83591                     me.minWidth = target.minWidth;
83592                 }
83593                 if (target.minHeight) {
83594                     me.minHeight = target.minHeight;
83595                 }
83596                 if (target.maxWidth) {
83597                     me.maxWidth = target.maxWidth;
83598                 }
83599                 if (target.maxHeight) {
83600                     me.maxHeight = target.maxHeight;
83601                 }
83602                 if (target.floating) {
83603                     if (!this.hasOwnProperty('handles')) {
83604                         this.handles = 'n ne e se s sw w nw';
83605                     }
83606                 }
83607             } else {
83608                 me.el = me.target = Ext.get(target);
83609             }
83610         }
83611         
83612         else {
83613             me.target = me.el = Ext.get(me.el);
83614         }
83615
83616         
83617         
83618         
83619         tag = me.el.dom.tagName;
83620         if (tag == 'TEXTAREA' || tag == 'IMG') {
83621             
83622             me.originalTarget = me.target;
83623             me.target = me.el = me.el.wrap({
83624                 cls: me.wrapCls,
83625                 id: me.el.id + '-rzwrap'
83626             });
83627
83628             
83629             me.el.setPositioning(me.originalTarget.getPositioning());
83630             me.originalTarget.clearPositioning();
83631             var box = me.originalTarget.getBox();
83632             me.el.setBox(box);
83633         }
83634
83635         
83636         
83637         me.el.position();
83638         if (me.pinned) {
83639             me.el.addCls(me.pinnedCls);
83640         }
83641
83642         
83643         me.resizeTracker = Ext.create('Ext.resizer.ResizeTracker', {
83644             disabled: me.disabled,
83645             target: me.target,
83646             constrainTo: me.constrainTo,
83647             overCls: me.overCls,
83648             throttle: me.throttle,
83649             originalTarget: me.originalTarget,
83650             delegate: '.' + me.handleCls,
83651             dynamic: me.dynamic,
83652             preserveRatio: me.preserveRatio,
83653             minHeight: me.minHeight,
83654             maxHeight: me.maxHeight,
83655             minWidth: me.minWidth,
83656             maxWidth: me.maxWidth
83657         });
83658
83659         
83660         me.resizeTracker.on('mousedown', me.onBeforeResize, me);
83661         me.resizeTracker.on('drag', me.onResize, me);
83662         me.resizeTracker.on('dragend', me.onResizeEnd, me);
83663
83664         if (me.handles == 'all') {
83665             me.handles = 'n s e w ne nw se sw';
83666         }
83667
83668         handles = me.handles = me.handles.split(/ |\s*?[,;]\s*?/);
83669         possibles = me.possiblePositions;
83670         len = handles.length;
83671         handleCls = me.handleCls + ' ' + (this.target.isComponent ? (me.target.baseCls + '-handle ') : '') + me.handleCls + '-';
83672
83673         for(; i < len; i++){
83674             
83675             if (handles[i] && possibles[handles[i]]) {
83676                 pos = possibles[handles[i]];
83677                 
83678
83679                 me[pos] = Ext.create('Ext.Component', {
83680                     owner: this,
83681                     region: pos,
83682                     cls: handleCls + pos,
83683                     renderTo: me.el
83684                 });
83685                 me[pos].el.unselectable();
83686                 if (me.transparent) {
83687                     me[pos].el.setOpacity(0);
83688                 }
83689             }
83690         }
83691
83692         
83693         if (Ext.isNumber(me.width)) {
83694             me.width = Ext.Number.constrain(me.width, me.minWidth, me.maxWidth);
83695         }
83696         if (Ext.isNumber(me.height)) {
83697             me.height = Ext.Number.constrain(me.height, me.minHeight, me.maxHeight);
83698         }
83699
83700         
83701         if (me.width != null || me.height != null) {
83702             if (me.originalTarget) {
83703                 me.originalTarget.setWidth(me.width);
83704                 me.originalTarget.setHeight(me.height);
83705             }
83706             me.resizeTo(me.width, me.height);
83707         }
83708
83709         me.forceHandlesHeight();
83710     },
83711
83712     disable: function() {
83713         this.resizeTracker.disable();
83714     },
83715
83716     enable: function() {
83717         this.resizeTracker.enable();
83718     },
83719
83720     
83721     onBeforeResize: function(tracker, e) {
83722         var b = this.target.getBox();
83723         return this.fireEvent('beforeresize', this, b.width, b.height, e);
83724     },
83725
83726     
83727     onResize: function(tracker, e) {
83728         var me = this,
83729             b = me.target.getBox();
83730         me.forceHandlesHeight();
83731         return me.fireEvent('resizedrag', me, b.width, b.height, e);
83732     },
83733
83734     
83735     onResizeEnd: function(tracker, e) {
83736         var me = this,
83737             b = me.target.getBox();
83738         me.forceHandlesHeight();
83739         return me.fireEvent('resize', me, b.width, b.height, e);
83740     },
83741
83742     
83743     resizeTo : function(width, height){
83744         this.target.setSize(width, height);
83745         this.fireEvent('resize', this, width, height, null);
83746     },
83747
83748     
83749     getEl : function() {
83750         return this.el;
83751     },
83752
83753     
83754     getTarget: function() {
83755         return this.target;
83756     },
83757
83758     destroy: function() {
83759         var h;
83760         for (var i = 0, l = this.handles.length; i < l; i++) {
83761             h = this[this.possiblePositions[this.handles[i]]];
83762             delete h.owner;
83763             Ext.destroy(h);
83764         }
83765     },
83766
83767     
83768     forceHandlesHeight : function() {
83769         var me = this,
83770             handle;
83771         if (Ext.isIE6) {
83772             handle = me.east; 
83773             if (handle) {
83774                 handle.setHeight(me.el.getHeight());
83775             }
83776             handle = me.west; 
83777             if (handle) {
83778                 handle.setHeight(me.el.getHeight());
83779             }
83780             me.el.repaint();
83781         }
83782     }
83783 });
83784
83785
83786 Ext.define('Ext.resizer.ResizeTracker', {
83787     extend: 'Ext.dd.DragTracker',
83788     dynamic: true,
83789     preserveRatio: false,
83790
83791     
83792     constrainTo: null,
83793
83794     constructor: function(config) {
83795         var me = this;
83796
83797         if (!config.el) {
83798             if (config.target.isComponent) {
83799                 me.el = config.target.getEl();
83800             } else {
83801                 me.el = config.target;
83802             }
83803         }
83804         this.callParent(arguments);
83805
83806         
83807         if (me.preserveRatio && me.minWidth && me.minHeight) {
83808             var widthRatio = me.minWidth / me.el.getWidth(),
83809                 heightRatio = me.minHeight / me.el.getHeight();
83810
83811             
83812             
83813             
83814             if (heightRatio > widthRatio) {
83815                 me.minWidth = me.el.getWidth() * heightRatio;
83816             } else {
83817                 me.minHeight = me.el.getHeight() * widthRatio;
83818             }
83819         }
83820
83821         
83822         
83823         if (me.throttle) {
83824             var throttledResizeFn = Ext.Function.createThrottled(function() {
83825                     Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
83826                 }, me.throttle);
83827
83828             me.resize = function(box, direction, atEnd) {
83829                 if (atEnd) {
83830                     Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
83831                 } else {
83832                     throttledResizeFn.apply(null, arguments);
83833                 }
83834             };
83835         }
83836     },
83837
83838     onBeforeStart: function(e) {
83839         
83840         this.startBox = this.el.getBox();
83841     },
83842
83843     
83844     getDynamicTarget: function() {
83845         var d = this.target;
83846         if (this.dynamic) {
83847             return d;
83848         } else if (!this.proxy) {
83849             this.proxy = d.isComponent ? d.getProxy().addCls(Ext.baseCSSPrefix + 'resizable-proxy') : d.createProxy({tag: 'div', cls: Ext.baseCSSPrefix + 'resizable-proxy', id: d.id + '-rzproxy'}, Ext.getBody());
83850             this.proxy.removeCls(Ext.baseCSSPrefix + 'proxy-el');
83851         }
83852         this.proxy.show();
83853         return this.proxy;
83854     },
83855
83856     onStart: function(e) {
83857         
83858         this.activeResizeHandle = Ext.getCmp(this.getDragTarget().id);
83859
83860         
83861         if (!this.dynamic) {
83862             this.resize(this.startBox, {
83863                 horizontal: 'none',
83864                 vertical: 'none'
83865             });
83866         }
83867     },
83868
83869     onDrag: function(e) {
83870         
83871         if (this.dynamic || this.proxy) {
83872             this.updateDimensions(e);
83873         }
83874     },
83875
83876     updateDimensions: function(e, atEnd) {
83877         var me = this,
83878             region = me.activeResizeHandle.region,
83879             offset = me.getOffset(me.constrainTo ? 'dragTarget' : null),
83880             box = me.startBox,
83881             ratio,
83882             widthAdjust = 0,
83883             heightAdjust = 0,
83884             adjustX = 0,
83885             adjustY = 0,
83886             dragRatio,
83887             horizDir = offset[0] < 0 ? 'right' : 'left',
83888             vertDir = offset[1] < 0 ? 'down' : 'up',
83889             oppositeCorner,
83890             axis; 
83891
83892         switch (region) {
83893             case 'south':
83894                 heightAdjust = offset[1];
83895                 axis = 2;
83896                 break;
83897             case 'north':
83898                 heightAdjust = -offset[1];
83899                 adjustY = -heightAdjust;
83900                 axis = 2;
83901                 break;
83902             case 'east':
83903                 widthAdjust = offset[0];
83904                 axis = 1;
83905                 break;
83906             case 'west':
83907                 widthAdjust = -offset[0];
83908                 adjustX = -widthAdjust;
83909                 axis = 1;
83910                 break;
83911             case 'northeast':
83912                 heightAdjust = -offset[1];
83913                 adjustY = -heightAdjust;
83914                 widthAdjust = offset[0];
83915                 oppositeCorner = [box.x, box.y + box.height];
83916                 axis = 3;
83917                 break;
83918             case 'southeast':
83919                 heightAdjust = offset[1];
83920                 widthAdjust = offset[0];
83921                 oppositeCorner = [box.x, box.y];
83922                 axis = 3;
83923                 break;
83924             case 'southwest':
83925                 widthAdjust = -offset[0];
83926                 adjustX = -widthAdjust;
83927                 heightAdjust = offset[1];
83928                 oppositeCorner = [box.x + box.width, box.y];
83929                 axis = 3;
83930                 break;
83931             case 'northwest':
83932                 heightAdjust = -offset[1];
83933                 adjustY = -heightAdjust;
83934                 widthAdjust = -offset[0];
83935                 adjustX = -widthAdjust;
83936                 oppositeCorner = [box.x + box.width, box.y + box.height];
83937                 axis = 3;
83938                 break;
83939         }
83940
83941         var newBox = {
83942             width: box.width + widthAdjust,
83943             height: box.height + heightAdjust,
83944             x: box.x + adjustX,
83945             y: box.y + adjustY
83946         };
83947
83948         
83949         if (newBox.width < me.minWidth || newBox.width > me.maxWidth) {
83950             newBox.width = Ext.Number.constrain(newBox.width, me.minWidth, me.maxWidth);
83951             newBox.x = me.lastX || newBox.x;
83952         } else {
83953             me.lastX = newBox.x;
83954         }
83955         if (newBox.height < me.minHeight || newBox.height > me.maxHeight) {
83956             newBox.height = Ext.Number.constrain(newBox.height, me.minHeight, me.maxHeight);
83957             newBox.y = me.lastY || newBox.y;
83958         } else {
83959             me.lastY = newBox.y;
83960         }
83961
83962         
83963         if (me.preserveRatio || e.shiftKey) {
83964             var newHeight,
83965                 newWidth;
83966
83967             ratio = me.startBox.width / me.startBox.height;
83968
83969             
83970             newHeight = Math.min(Math.max(me.minHeight, newBox.width / ratio), me.maxHeight);
83971             newWidth = Math.min(Math.max(me.minWidth, newBox.height * ratio), me.maxWidth);
83972
83973             
83974             if (axis == 1) {
83975                 newBox.height = newHeight;
83976             }
83977
83978             
83979             else if (axis == 2) {
83980                 newBox.width = newWidth;
83981             }
83982
83983             
83984             else {
83985                 
83986                 
83987                 dragRatio = Math.abs(oppositeCorner[0] - this.lastXY[0]) / Math.abs(oppositeCorner[1] - this.lastXY[1]);
83988
83989                 
83990                 if (dragRatio > ratio) {
83991                     newBox.height = newHeight;
83992                 } else {
83993                     newBox.width = newWidth;
83994                 }
83995
83996                 
83997                 if (region == 'northeast') {
83998                     newBox.y = box.y - (newBox.height - box.height);
83999                 } else if (region == 'northwest') {
84000                     newBox.y = box.y - (newBox.height - box.height);
84001                     newBox.x = box.x - (newBox.width - box.width);
84002                 } else if (region == 'southwest') {
84003                     newBox.x = box.x - (newBox.width - box.width);
84004                 }
84005             }
84006         }
84007
84008         if (heightAdjust === 0) {
84009             vertDir = 'none';
84010         }
84011         if (widthAdjust === 0) {
84012             horizDir = 'none';
84013         }
84014         me.resize(newBox, {
84015             horizontal: horizDir,
84016             vertical: vertDir
84017         }, atEnd);
84018     },
84019
84020     getResizeTarget: function(atEnd) {
84021         return atEnd ? this.target : this.getDynamicTarget();
84022     },
84023
84024     resize: function(box, direction, atEnd) {
84025         var target = this.getResizeTarget(atEnd);
84026         if (target.isComponent) {
84027             if (target.floating) {
84028                 target.setPagePosition(box.x, box.y);
84029             }
84030             target.setSize(box.width, box.height);
84031         } else {
84032             target.setBox(box);
84033             
84034             if (this.originalTarget) {
84035                 this.originalTarget.setBox(box);
84036             }
84037         }
84038     },
84039
84040     onEnd: function(e) {
84041         this.updateDimensions(e, true);
84042         if (this.proxy) {
84043             this.proxy.hide();
84044         }
84045     }
84046 });
84047
84048
84049 Ext.define('Ext.resizer.SplitterTracker', {
84050     extend: 'Ext.dd.DragTracker',
84051     requires: ['Ext.util.Region'],
84052     enabled: true,
84053
84054     getPrevCmp: function() {
84055         var splitter = this.getSplitter();
84056         return splitter.previousSibling();
84057     },
84058
84059     getNextCmp: function() {
84060         var splitter = this.getSplitter();
84061         return splitter.nextSibling();
84062     },
84063
84064     
84065     
84066     onBeforeStart: function(e) {
84067         var prevCmp = this.getPrevCmp(),
84068             nextCmp = this.getNextCmp();
84069
84070         
84071         if (nextCmp.collapsed || prevCmp.collapsed) {
84072             return false;
84073         }
84074         
84075         this.prevBox  = prevCmp.getEl().getBox();
84076         this.nextBox  = nextCmp.getEl().getBox();
84077         this.constrainTo = this.calculateConstrainRegion();
84078     },
84079
84080     
84081     onStart: function(e) {
84082         var splitter = this.getSplitter();
84083         splitter.addCls(splitter.baseCls + '-active');
84084     },
84085
84086     
84087     calculateConstrainRegion: function() {
84088         var splitter   = this.getSplitter(),
84089             topPad     = 0,
84090             bottomPad  = 0,
84091             splitWidth = splitter.getWidth(),
84092             defaultMin = splitter.defaultSplitMin,
84093             orient     = splitter.orientation,
84094             prevBox    = this.prevBox,
84095             prevCmp    = this.getPrevCmp(),
84096             nextBox    = this.nextBox,
84097             nextCmp    = this.getNextCmp(),
84098             
84099             
84100             
84101             prevConstrainRegion, nextConstrainRegion;
84102
84103         
84104         if (orient === 'vertical') {
84105
84106             
84107             
84108             prevConstrainRegion = Ext.create('Ext.util.Region',
84109                 prevBox.y,
84110                 
84111                 
84112                 (prevCmp.maxWidth ? prevBox.x + prevCmp.maxWidth : nextBox.right - (nextCmp.minWidth || defaultMin)) + splitWidth,
84113                 prevBox.bottom,
84114                 prevBox.x + (prevCmp.minWidth || defaultMin)
84115             );
84116             
84117             nextConstrainRegion = Ext.create('Ext.util.Region',
84118                 nextBox.y,
84119                 nextBox.right - (nextCmp.minWidth || defaultMin),
84120                 nextBox.bottom,
84121                 
84122                 
84123                 (nextCmp.maxWidth ? nextBox.right - nextCmp.maxWidth : prevBox.x + (prevBox.minWidth || defaultMin)) - splitWidth
84124             );
84125         } else {
84126             
84127             prevConstrainRegion = Ext.create('Ext.util.Region',
84128                 prevBox.y + (prevCmp.minHeight || defaultMin),
84129                 prevBox.right,
84130                 
84131                 
84132                 (prevCmp.maxHeight ? prevBox.y + prevCmp.maxHeight : nextBox.bottom - (nextCmp.minHeight || defaultMin)) + splitWidth,
84133                 prevBox.x
84134             );
84135             
84136             nextConstrainRegion = Ext.create('Ext.util.Region',
84137                 
84138                 
84139                 (nextCmp.maxHeight ? nextBox.bottom - nextCmp.maxHeight : prevBox.y + (prevCmp.minHeight || defaultMin)) - splitWidth,
84140                 nextBox.right,
84141                 nextBox.bottom - (nextCmp.minHeight || defaultMin),
84142                 nextBox.x
84143             );
84144         }
84145
84146         
84147         return  prevConstrainRegion.intersect(nextConstrainRegion);
84148     },
84149
84150     
84151     performResize: function(e) {
84152         var offset   = this.getOffset('dragTarget'),
84153             splitter = this.getSplitter(),
84154             orient   = splitter.orientation,
84155             prevCmp  = this.getPrevCmp(),
84156             nextCmp  = this.getNextCmp(),
84157             owner    = splitter.ownerCt,
84158             layout   = owner.getLayout();
84159
84160         
84161         owner.suspendLayout = true;
84162
84163         if (orient === 'vertical') {
84164             if (prevCmp) {
84165                 if (!prevCmp.maintainFlex) {
84166                     delete prevCmp.flex;
84167                     prevCmp.setSize(this.prevBox.width + offset[0], prevCmp.getHeight());
84168                 }
84169             }
84170             if (nextCmp) {
84171                 if (!nextCmp.maintainFlex) {
84172                     delete nextCmp.flex;
84173                     nextCmp.setSize(this.nextBox.width - offset[0], nextCmp.getHeight());
84174                 }
84175             }
84176         
84177         } else {
84178             if (prevCmp) {
84179                 if (!prevCmp.maintainFlex) {
84180                     delete prevCmp.flex;
84181                     prevCmp.setSize(prevCmp.getWidth(), this.prevBox.height + offset[1]);
84182                 }
84183             }
84184             if (nextCmp) {
84185                 if (!nextCmp.maintainFlex) {
84186                     delete nextCmp.flex;
84187                     nextCmp.setSize(prevCmp.getWidth(), this.nextBox.height - offset[1]);
84188                 }
84189             }
84190         }
84191         delete owner.suspendLayout;
84192         layout.onLayout();
84193     },
84194
84195     
84196     onEnd: function(e) {
84197         var splitter = this.getSplitter();
84198         splitter.removeCls(splitter.baseCls + '-active');
84199         this.performResize();
84200     },
84201
84202     
84203     
84204     onDrag: function(e) {
84205         var offset    = this.getOffset('dragTarget'),
84206             splitter  = this.getSplitter(),
84207             splitEl   = splitter.getEl(),
84208             orient    = splitter.orientation;
84209
84210         if (orient === "vertical") {
84211             splitEl.setX(this.startRegion.left + offset[0]);
84212         } else {
84213             splitEl.setY(this.startRegion.top + offset[1]);
84214         }
84215     },
84216
84217     getSplitter: function() {
84218         return Ext.getCmp(this.getDragCt().id);
84219     }
84220 });
84221
84222 Ext.define('Ext.selection.CellModel', {
84223     extend: 'Ext.selection.Model',
84224     alias: 'selection.cellmodel',
84225     requires: ['Ext.util.KeyNav'],
84226     
84227     
84228     enableKeyNav: true,
84229     
84230     
84231     preventWrap: false,
84232
84233     constructor: function(){
84234         this.addEvents(
84235             
84236             'deselect',
84237             
84238             
84239             'select'
84240         );
84241         this.callParent(arguments);    
84242     },
84243
84244     bindComponent: function(view) {
84245         var me = this;
84246         me.primaryView = view;
84247         me.views = me.views || [];
84248         me.views.push(view);
84249         me.bind(view.getStore(), true);
84250
84251         view.on({
84252             cellmousedown: me.onMouseDown,
84253             refresh: me.onViewRefresh,
84254             scope: me
84255         });
84256
84257         if (me.enableKeyNav) {
84258             me.initKeyNav(view);
84259         }
84260     },
84261
84262     initKeyNav: function(view) {
84263         var me = this;
84264         
84265         if (!view.rendered) {
84266             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
84267             return;
84268         }
84269
84270         view.el.set({
84271             tabIndex: -1
84272         });
84273
84274         
84275         
84276         me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
84277             up: me.onKeyUp,
84278             down: me.onKeyDown,
84279             right: me.onKeyRight,
84280             left: me.onKeyLeft,
84281             tab: me.onKeyTab,
84282             scope: me
84283         });
84284     },
84285     
84286     getHeaderCt: function() {
84287         return this.primaryView.headerCt;
84288     },
84289
84290     onKeyUp: function(e, t) {
84291         this.move('up', e);
84292     },
84293
84294     onKeyDown: function(e, t) {
84295         this.move('down', e);
84296     },
84297
84298     onKeyLeft: function(e, t) {
84299         this.move('left', e);
84300     },
84301     
84302     onKeyRight: function(e, t) {
84303         this.move('right', e);
84304     },
84305     
84306     move: function(dir, e) {
84307         var me = this,
84308             pos = me.primaryView.walkCells(me.getCurrentPosition(), dir, e, me.preventWrap);
84309         if (pos) {
84310             me.setCurrentPosition(pos);
84311         }
84312         return pos;
84313     },
84314
84315     
84316     getCurrentPosition: function() {
84317         return this.position;
84318     },
84319     
84320     
84321     setCurrentPosition: function(pos) {
84322         var me = this;
84323         
84324         if (me.position) {
84325             me.onCellDeselect(me.position);
84326         }
84327         if (pos) {
84328             me.onCellSelect(pos);
84329         }
84330         me.position = pos;
84331     },
84332
84333     
84334     onMouseDown: function(view, cell, cellIndex, record, row, rowIndex, e) {
84335         this.setCurrentPosition({
84336             row: rowIndex,
84337             column: cellIndex
84338         });
84339     },
84340
84341     
84342     
84343     onCellSelect: function(position) {
84344         var me = this,
84345             store = me.view.getStore(),
84346             record = store.getAt(position.row);
84347
84348         me.doSelect(record);
84349         me.primaryView.onCellSelect(position);
84350         
84351         me.primaryView.onCellFocus(position);
84352         me.fireEvent('select', me, record, position.row, position.column);
84353     },
84354
84355     
84356     
84357     onCellDeselect: function(position) {
84358         var me = this,
84359             store = me.view.getStore(),
84360             record = store.getAt(position.row);
84361
84362         me.doDeselect(record);
84363         me.primaryView.onCellDeselect(position);
84364         me.fireEvent('deselect', me, record, position.row, position.column);
84365     },
84366
84367     onKeyTab: function(e, t) {
84368         var me = this,
84369             direction = e.shiftKey ? 'left' : 'right',
84370             editingPlugin = me.view.editingPlugin,
84371             position = me.move(direction, e);
84372
84373         if (editingPlugin && position && me.wasEditing) {
84374             editingPlugin.startEditByPosition(position);
84375         }
84376         delete me.wasEditing;
84377     },
84378
84379     onEditorTab: function(editingPlugin, e) {
84380         var me = this,
84381             direction = e.shiftKey ? 'left' : 'right',
84382             position  = me.move(direction, e);
84383
84384         if (position) {
84385             editingPlugin.startEditByPosition(position);
84386             me.wasEditing = true;
84387         }
84388     },
84389
84390     refresh: function() {
84391         var pos = this.getCurrentPosition();
84392         if (pos) {
84393             this.onCellSelect(pos);
84394         }
84395     },
84396
84397     onViewRefresh: function() {
84398         var pos = this.getCurrentPosition();
84399         if (pos) {
84400             this.onCellDeselect(pos);
84401             this.setCurrentPosition(null);
84402         }
84403     },
84404
84405     selectByPosition: function(position) {
84406         this.setCurrentPosition(position);
84407     }
84408 });
84409
84410 Ext.define('Ext.selection.RowModel', {
84411     extend: 'Ext.selection.Model',
84412     alias: 'selection.rowmodel',
84413     requires: ['Ext.util.KeyNav'],
84414     
84415     
84416     deltaScroll: 5,
84417     
84418     
84419     enableKeyNav: true,
84420     
84421     constructor: function(){
84422         this.addEvents(
84423             
84424             'deselect',
84425             
84426             
84427             'select'
84428         );
84429         this.callParent(arguments);    
84430     },
84431
84432     bindComponent: function(view) {
84433         var me = this;
84434         
84435         me.views = me.views || [];
84436         me.views.push(view);
84437         me.bind(view.getStore(), true);
84438
84439         view.on({
84440             itemmousedown: me.onRowMouseDown,
84441             scope: me
84442         });
84443
84444         if (me.enableKeyNav) {
84445             me.initKeyNav(view);
84446         }
84447     },
84448
84449     initKeyNav: function(view) {
84450         var me = this;
84451         
84452         if (!view.rendered) {
84453             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
84454             return;
84455         }
84456
84457         view.el.set({
84458             tabIndex: -1
84459         });
84460
84461         
84462         
84463         me.keyNav = new Ext.util.KeyNav(view.el, {
84464             up: me.onKeyUp,
84465             down: me.onKeyDown,
84466             right: me.onKeyRight,
84467             left: me.onKeyLeft,
84468             pageDown: me.onKeyPageDown,
84469             pageUp: me.onKeyPageUp,
84470             home: me.onKeyHome,
84471             end: me.onKeyEnd,
84472             scope: me
84473         });
84474         view.el.on(Ext.EventManager.getKeyEvent(), me.onKeyPress, me);
84475     },
84476
84477     
84478     
84479     
84480     getRowsVisible: function() {
84481         var rowsVisible = false,
84482             view = this.views[0],
84483             row = view.getNode(0),
84484             rowHeight, gridViewHeight;
84485
84486         if (row) {
84487             rowHeight = Ext.fly(row).getHeight();
84488             gridViewHeight = view.el.getHeight();
84489             rowsVisible = Math.floor(gridViewHeight / rowHeight);
84490         }
84491
84492         return rowsVisible;
84493     },
84494
84495     
84496     onKeyEnd: function(e, t) {
84497         var me = this,
84498             last = me.store.getAt(me.store.getCount() - 1);
84499             
84500         if (last) {
84501             if (e.shiftKey) {
84502                 me.selectRange(last, me.lastFocused || 0);
84503                 me.setLastFocused(last);
84504             } else if (e.ctrlKey) {
84505                 me.setLastFocused(last);
84506             } else {
84507                 me.doSelect(last);
84508             }
84509         }
84510     },
84511
84512     
84513     onKeyHome: function(e, t) {
84514         var me = this,
84515             first = me.store.getAt(0);
84516             
84517         if (first) {
84518             if (e.shiftKey) {
84519                 me.selectRange(first, me.lastFocused || 0);
84520                 me.setLastFocused(first);
84521             } else if (e.ctrlKey) {
84522                 me.setLastFocused(first);
84523             } else {
84524                 me.doSelect(first, false);
84525             }
84526         }
84527     },
84528
84529     
84530     onKeyPageUp: function(e, t) {
84531         var me = this,
84532             rowsVisible = me.getRowsVisible(),
84533             selIdx,
84534             prevIdx,
84535             prevRecord,
84536             currRec;
84537             
84538         if (rowsVisible) {
84539             selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
84540             prevIdx = selIdx - rowsVisible;
84541             if (prevIdx < 0) {
84542                 prevIdx = 0;
84543             }
84544             prevRecord = me.store.getAt(prevIdx);
84545             if (e.shiftKey) {
84546                 currRec = me.store.getAt(selIdx);
84547                 me.selectRange(prevRecord, currRec, e.ctrlKey, 'up');
84548                 me.setLastFocused(prevRecord);
84549             } else if (e.ctrlKey) {
84550                 e.preventDefault();
84551                 me.setLastFocused(prevRecord);
84552             } else {
84553                 me.doSelect(prevRecord);
84554             }
84555
84556         }
84557     },
84558
84559     
84560     onKeyPageDown: function(e, t) {
84561         var me = this,
84562             rowsVisible = me.getRowsVisible(),
84563             selIdx,
84564             nextIdx,
84565             nextRecord,
84566             currRec;
84567             
84568         if (rowsVisible) {
84569             selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
84570             nextIdx = selIdx + rowsVisible;
84571             if (nextIdx >= me.store.getCount()) {
84572                 nextIdx = me.store.getCount() - 1;
84573             }
84574             nextRecord = me.store.getAt(nextIdx);
84575             if (e.shiftKey) {
84576                 currRec = me.store.getAt(selIdx);
84577                 me.selectRange(nextRecord, currRec, e.ctrlKey, 'down');
84578                 me.setLastFocused(nextRecord);
84579             } else if (e.ctrlKey) {
84580                 
84581                 
84582                 e.preventDefault();
84583                 me.setLastFocused(nextRecord);
84584             } else {
84585                 me.doSelect(nextRecord);
84586             }
84587         }
84588     },
84589
84590     
84591     
84592     onKeyPress: function(e, t) {
84593         if (e.getKey() === e.SPACE) {
84594             e.stopEvent();
84595             var me = this,
84596                 record = me.lastFocused;
84597                 
84598             if (record) {
84599                 if (me.isSelected(record)) {
84600                     me.doDeselect(record, false);
84601                 } else {
84602                     me.doSelect(record, true);
84603                 }
84604             }
84605         }
84606     },
84607
84608     
84609     
84610     
84611     onKeyUp: function(e, t) {
84612         var me = this,
84613             view = me.views[0],
84614             idx  = me.store.indexOf(me.lastFocused),
84615             record;
84616             
84617         if (idx > 0) {
84618             
84619             
84620             record = me.store.getAt(idx - 1);
84621             if (e.shiftKey && me.lastFocused) {
84622                 if (me.isSelected(me.lastFocused) && me.isSelected(record)) {
84623                     me.doDeselect(me.lastFocused, true);
84624                     me.setLastFocused(record);
84625                 } else if (!me.isSelected(me.lastFocused)) {
84626                     me.doSelect(me.lastFocused, true);
84627                     me.doSelect(record, true);
84628                 } else {
84629                     me.doSelect(record, true);
84630                 }
84631             } else if (e.ctrlKey) {
84632                 me.setLastFocused(record);
84633             } else {
84634                 me.doSelect(record);
84635                 
84636             }
84637         }
84638         
84639         
84640         
84641         
84642         
84643         
84644         
84645     },
84646
84647     
84648     
84649     
84650     onKeyDown: function(e, t) {
84651         var me = this,
84652             view = me.views[0],
84653             idx  = me.store.indexOf(me.lastFocused),
84654             record;
84655             
84656         
84657         
84658         if (idx + 1 < me.store.getCount()) {
84659             record = me.store.getAt(idx + 1);
84660             if (me.selected.getCount() === 0) {
84661                 me.doSelect(record);
84662                 
84663             } else if (e.shiftKey && me.lastFocused) {
84664                 if (me.isSelected(me.lastFocused) && me.isSelected(record)) {
84665                     me.doDeselect(me.lastFocused, true);
84666                     me.setLastFocused(record);
84667                 } else if (!me.isSelected(me.lastFocused)) {
84668                     me.doSelect(me.lastFocused, true);
84669                     me.doSelect(record, true);
84670                 } else {
84671                     me.doSelect(record, true);
84672                 }
84673             } else if (e.ctrlKey) {
84674                 me.setLastFocused(record);
84675             } else {
84676                 me.doSelect(record);
84677                 
84678             }
84679         }
84680     },
84681     
84682     scrollByDeltaX: function(delta) {
84683         var view    = this.views[0],
84684             section = view.up(),
84685             hScroll = section.horizontalScroller;
84686             
84687         if (hScroll) {
84688             hScroll.scrollByDeltaX(delta);
84689         }
84690     },
84691     
84692     onKeyLeft: function(e, t) {
84693         this.scrollByDeltaX(-this.deltaScroll);
84694     },
84695     
84696     onKeyRight: function(e, t) {
84697         this.scrollByDeltaX(this.deltaScroll);
84698     },
84699
84700     
84701     
84702     onRowMouseDown: function(view, record, item, index, e) {
84703         view.el.focus();
84704         this.selectWithEvent(record, e);
84705     },
84706
84707     
84708     
84709     onSelectChange: function(record, isSelected, suppressEvent) {
84710         var me      = this,
84711             views   = me.views,
84712             viewsLn = views.length,
84713             store   = me.store,
84714             rowIdx  = store.indexOf(record),
84715             i = 0;
84716             
84717         for (; i < viewsLn; i++) {
84718             if (isSelected) {
84719                 views[i].onRowSelect(rowIdx, suppressEvent);
84720                 if (!suppressEvent) {
84721                     me.fireEvent('select', me, record, rowIdx);
84722                 }
84723             } else {
84724                 views[i].onRowDeselect(rowIdx, suppressEvent);
84725                 if (!suppressEvent) {
84726                     me.fireEvent('deselect', me, record, rowIdx);
84727                 }
84728             }
84729         }
84730     },
84731
84732     
84733     
84734     onLastFocusChanged: function(oldFocused, newFocused, supressFocus) {
84735         var views   = this.views,
84736             viewsLn = views.length,
84737             store   = this.store,
84738             rowIdx,
84739             i = 0;
84740             
84741         if (oldFocused) {
84742             rowIdx = store.indexOf(oldFocused);
84743             if (rowIdx != -1) {
84744                 for (; i < viewsLn; i++) {
84745                     views[i].onRowFocus(rowIdx, false);
84746                 }
84747             }
84748         }
84749
84750         if (newFocused) {
84751             rowIdx = store.indexOf(newFocused);
84752             if (rowIdx != -1) {
84753                 for (i = 0; i < viewsLn; i++) {
84754                     views[i].onRowFocus(rowIdx, true, supressFocus);
84755                 }
84756             }
84757         }
84758     },
84759     
84760     onEditorTab: function(editingPlugin, e) {
84761         var me = this,
84762             view = me.views[0],
84763             record = editingPlugin.getActiveRecord(),
84764             header = editingPlugin.getActiveColumn(),
84765             position = view.getPosition(record, header),
84766             direction = e.shiftKey ? 'left' : 'right',
84767             newPosition  = view.walkCells(position, direction, e, this.preventWrap);
84768             
84769         if (newPosition) {
84770             editingPlugin.startEditByPosition(newPosition);
84771         }
84772     },
84773     
84774     selectByPosition: function(position) {
84775         var record = this.store.getAt(position.row);
84776         this.select(record);
84777     }
84778 });
84779
84780 Ext.define('Ext.selection.CheckboxModel', {
84781     extend: 'Ext.selection.RowModel',
84782
84783     
84784     mode: 'MULTI',
84785
84786     
84787     injectCheckbox: 0,
84788
84789     
84790     checkOnly: false,
84791
84792     
84793     checkerOnCls: Ext.baseCSSPrefix + 'grid-hd-checker-on',
84794
84795     bindComponent: function() {
84796         this.sortable = false;
84797         this.callParent(arguments);
84798
84799         var view     = this.views[0],
84800             headerCt = view.headerCt;
84801
84802         if (this.injectCheckbox !== false) {
84803             if (this.injectCheckbox == 'first') {
84804                 this.injectCheckbox = 0;
84805             } else if (this.injectCheckbox == 'last') {
84806                 this.injectCheckbox = headerCt.getColumnCount();
84807             }
84808             headerCt.add(this.injectCheckbox,  this.getHeaderConfig());
84809         }
84810         headerCt.on('headerclick', this.onHeaderClick, this);
84811     },
84812
84813     
84814     toggleUiHeader: function(isChecked) {
84815         var view     = this.views[0],
84816             headerCt = view.headerCt,
84817             checkHd  = headerCt.child('gridcolumn[isCheckerHd]');
84818
84819         if (checkHd) {
84820             if (isChecked) {
84821                 checkHd.el.addCls(this.checkerOnCls);
84822             } else {
84823                 checkHd.el.removeCls(this.checkerOnCls);
84824             }
84825         }
84826     },
84827
84828     
84829     onHeaderClick: function(headerCt, header, e) {
84830         if (header.isCheckerHd) {
84831             e.stopEvent();
84832             var isChecked = header.el.hasCls(Ext.baseCSSPrefix + 'grid-hd-checker-on');
84833             if (isChecked) {
84834                 
84835                 this.deselectAll(true);
84836             } else {
84837                 
84838                 this.selectAll(true);
84839             }
84840         }
84841     },
84842
84843     
84844     getHeaderConfig: function() {
84845         return {
84846             isCheckerHd: true,
84847             text : '&#160;',
84848             width: 24,
84849             sortable: false,
84850             fixed: true,
84851             hideable: false,
84852             menuDisabled: true,
84853             dataIndex: '',
84854             cls: Ext.baseCSSPrefix + 'column-header-checkbox ',
84855             renderer: Ext.Function.bind(this.renderer, this)
84856         };
84857     },
84858
84859     
84860     renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
84861         metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
84862         return '<div class="' + Ext.baseCSSPrefix + 'grid-row-checker">&#160;</div>';
84863     },
84864
84865     
84866     onRowMouseDown: function(view, record, item, index, e) {
84867         view.el.focus();
84868         var me = this,
84869             checker = e.getTarget('.' + Ext.baseCSSPrefix + 'grid-row-checker');
84870
84871         
84872         if (me.checkOnly && !checker) {
84873             return;
84874         }
84875
84876         if (checker) {
84877             var mode = me.getSelectionMode();
84878             
84879             
84880             if (mode !== 'SINGLE') {
84881                 me.setSelectionMode('SIMPLE');
84882             }
84883             me.selectWithEvent(record, e);
84884             me.setSelectionMode(mode);
84885         } else {
84886             me.selectWithEvent(record, e);
84887         }
84888     },
84889
84890     
84891     onSelectChange: function(record, isSelected) {
84892         this.callParent([record, isSelected]);
84893         
84894         var hdSelectStatus = this.selected.getCount() === this.store.getCount();
84895         this.toggleUiHeader(hdSelectStatus);
84896     }
84897 });
84898
84899
84900 Ext.define('Ext.selection.TreeModel', {
84901     extend: 'Ext.selection.RowModel',
84902     alias: 'selection.treemodel',
84903     
84904     
84905     
84906     
84907     pruneRemoved: false,
84908     
84909     onKeyRight: function(e, t) {
84910         var focused = this.getLastFocused(),
84911             view    = this.view;
84912             
84913         if (focused) {
84914             
84915             
84916             
84917             if (focused.isExpanded()) {
84918                 this.onKeyDown(e, t);
84919             
84920             } else if (!focused.isLeaf()) {
84921                 view.expand(focused);
84922             }
84923         }
84924     },
84925     
84926     onKeyLeft: function(e, t) {
84927         var focused = this.getLastFocused(),
84928             view    = this.view,
84929             viewSm  = view.getSelectionModel(),
84930             parentNode, parentRecord;
84931
84932         if (focused) {
84933             parentNode = focused.parentNode;
84934             
84935             if (focused.isExpanded()) {
84936                 view.collapse(focused);
84937             
84938             
84939             } else if (parentNode && !parentNode.isRoot()) {
84940                 
84941                 if (e.shiftKey) {
84942                     viewSm.selectRange(parentNode, focused, e.ctrlKey, 'up');
84943                     viewSm.setLastFocused(parentNode);
84944                 
84945                 } else if (e.ctrlKey) {
84946                     viewSm.setLastFocused(parentNode);
84947                 
84948                 } else {
84949                     viewSm.select(parentNode);
84950                 }
84951             }
84952         }
84953     },
84954     
84955     onKeyPress: function(e, t) {
84956         var selected, checked;
84957         
84958         if (e.getKey() === e.SPACE || e.getKey() === e.ENTER) {
84959             e.stopEvent();
84960             selected = this.getLastSelected();
84961             if (selected && selected.isLeaf()) {
84962                 checked = selected.get('checked');
84963                 if (Ext.isBoolean(checked)) {
84964                     selected.set('checked', !checked);
84965                 }
84966             }
84967         } else {
84968             this.callParent(arguments);
84969         }
84970     }
84971 });
84972
84973
84974 Ext.define('Ext.slider.Thumb', {
84975     requires: ['Ext.dd.DragTracker', 'Ext.util.Format'],
84976     
84977     topZIndex: 10000,
84978     
84979     constructor: function(config) {
84980         var me = this;
84981         
84982         
84983         Ext.apply(me, config || {}, {
84984             cls: Ext.baseCSSPrefix + 'slider-thumb',
84985
84986             
84987             constrain: false
84988         });
84989         me.callParent([config]);
84990
84991         if (me.slider.vertical) {
84992             Ext.apply(me, Ext.slider.Thumb.Vertical);
84993         }
84994     },
84995
84996     
84997     render: function() {
84998         var me = this;
84999         
85000         me.el = me.slider.innerEl.insertFirst({cls: me.cls});
85001         if (me.disabled) {
85002             me.disable();
85003         }
85004         me.initEvents();
85005     },
85006     
85007     
85008     move: function(v, animate){
85009         if(!animate){
85010             this.el.setLeft(v);
85011         }else{
85012             Ext.create('Ext.fx.Anim', {
85013                 target: this.el,
85014                 duration: 350,
85015                 to: {
85016                     left: v
85017                 }
85018             });
85019         }
85020     },
85021
85022     
85023     bringToFront: function() {
85024         this.el.setStyle('zIndex', this.topZIndex);
85025     },
85026     
85027     
85028     sendToBack: function() {
85029         this.el.setStyle('zIndex', '');
85030     },
85031     
85032     
85033     enable: function() {
85034         var me = this;
85035         
85036         me.disabled = false;
85037         if (me.el) {
85038             me.el.removeCls(me.slider.disabledCls);
85039         }
85040     },
85041
85042     
85043     disable: function() {
85044         var me = this;
85045         
85046         me.disabled = true;
85047         if (me.el) {
85048             me.el.addCls(me.slider.disabledCls);
85049         }
85050     },
85051
85052     
85053     initEvents: function() {
85054         var me = this,
85055             el = me.el;
85056
85057         me.tracker = Ext.create('Ext.dd.DragTracker', {
85058             onBeforeStart: Ext.Function.bind(me.onBeforeDragStart, me),
85059             onStart      : Ext.Function.bind(me.onDragStart, me),
85060             onDrag       : Ext.Function.bind(me.onDrag, me),
85061             onEnd        : Ext.Function.bind(me.onDragEnd, me),
85062             tolerance    : 3,
85063             autoStart    : 300,
85064             overCls      : Ext.baseCSSPrefix + 'slider-thumb-over'
85065         });
85066
85067         me.tracker.initEl(el);
85068     },
85069
85070     
85071     onBeforeDragStart : function(e) {
85072         if (this.disabled) {
85073             return false;
85074         } else {
85075             this.slider.promoteThumb(this);
85076             return true;
85077         }
85078     },
85079
85080     
85081     onDragStart: function(e){
85082         var me = this;
85083         
85084         me.el.addCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
85085         me.dragging = true;
85086         me.dragStartValue = me.value;
85087
85088         me.slider.fireEvent('dragstart', me.slider, e, me);
85089     },
85090
85091     
85092     onDrag: function(e) {
85093         var me       = this,
85094             slider   = me.slider,
85095             index    = me.index,
85096             newValue = me.getNewValue(),
85097             above,
85098             below;
85099
85100         if (me.constrain) {
85101             above = slider.thumbs[index + 1];
85102             below = slider.thumbs[index - 1];
85103
85104             if (below !== undefined && newValue <= below.value) {
85105                 newValue = below.value;
85106             }
85107             
85108             if (above !== undefined && newValue >= above.value) {
85109                 newValue = above.value;
85110             }
85111         }
85112
85113         slider.setValue(index, newValue, false);
85114         slider.fireEvent('drag', slider, e, me);
85115     },
85116
85117     getNewValue: function() {
85118         var slider = this.slider,
85119             pos = slider.innerEl.translatePoints(this.tracker.getXY());
85120
85121         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
85122     },
85123
85124     
85125     onDragEnd: function(e) {
85126         var me     = this,
85127             slider = me.slider,
85128             value  = me.value;
85129
85130         me.el.removeCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
85131
85132         me.dragging = false;
85133         slider.fireEvent('dragend', slider, e);
85134
85135         if (me.dragStartValue != value) {
85136             slider.fireEvent('changecomplete', slider, value, me);
85137         }
85138     },
85139
85140     destroy: function() {
85141         Ext.destroy(this.tracker);
85142     },
85143     statics: {
85144         
85145         Vertical: {
85146             getNewValue: function() {
85147                 var slider   = this.slider,
85148                     innerEl  = slider.innerEl,
85149                     pos      = innerEl.translatePoints(this.tracker.getXY()),
85150                     bottom   = innerEl.getHeight() - pos.top;
85151
85152                 return Ext.util.Format.round(slider.reverseValue(bottom), slider.decimalPrecision);
85153             },
85154             move: function(v, animate) {
85155                 if (!animate) {
85156                     this.el.setBottom(v);
85157                 } else {
85158                     Ext.create('Ext.fx.Anim', {
85159                         target: this.el,
85160                         duration: 350,
85161                         to: {
85162                             bottom: v
85163                         }
85164                     });
85165                 }
85166             }
85167         }
85168     }
85169 });
85170
85171
85172 Ext.define('Ext.slider.Tip', {
85173     extend: 'Ext.tip.Tip',
85174     minWidth: 10,
85175     alias: 'widget.slidertip',
85176     offsets : [0, -10],
85177     
85178     isSliderTip: true,
85179
85180     init: function(slider) {
85181         var me = this;
85182         
85183         slider.on({
85184             scope    : me,
85185             dragstart: me.onSlide,
85186             drag     : me.onSlide,
85187             dragend  : me.hide,
85188             destroy  : me.destroy
85189         });
85190     },
85191     
85192     onSlide : function(slider, e, thumb) {
85193         var me = this;
85194         me.show();
85195         me.update(me.getText(thumb));
85196         me.doComponentLayout();
85197         me.el.alignTo(thumb.el, 'b-t?', me.offsets);
85198     },
85199
85200     
85201     getText : function(thumb) {
85202         return String(thumb.value);
85203     }
85204 });
85205
85206 Ext.define('Ext.slider.Multi', {
85207     extend: 'Ext.form.field.Base',
85208     alias: 'widget.multislider',
85209     alternateClassName: 'Ext.slider.MultiSlider',
85210
85211     requires: [
85212         'Ext.slider.Thumb',
85213         'Ext.slider.Tip',
85214         'Ext.Number',
85215         'Ext.util.Format',
85216         'Ext.Template',
85217         'Ext.layout.component.field.Slider'
85218     ],
85219
85220     fieldSubTpl: [
85221         '<div class="' + Ext.baseCSSPrefix + 'slider {fieldCls} {vertical}" aria-valuemin="{minValue}" aria-valuemax="{maxValue}" aria-valuenow="{value}" aria-valuetext="{value}">',
85222             '<div class="' + Ext.baseCSSPrefix + 'slider-end" role="presentation">',
85223                 '<div class="' + Ext.baseCSSPrefix + 'slider-inner" role="presentation">',
85224                     '<a class="' + Ext.baseCSSPrefix + 'slider-focus" href="#" tabIndex="-1" hidefocus="on" role="presentation"></a>',
85225                 '</div>',
85226             '</div>',
85227         '</div>',
85228         {
85229             disableFormats: true,
85230             compiled: true
85231         }
85232     ],
85233
85234     
85235
85236     
85237
85238     
85239     vertical: false,
85240     
85241     minValue: 0,
85242     
85243     maxValue: 100,
85244     
85245     decimalPrecision: 0,
85246     
85247     keyIncrement: 1,
85248     
85249     increment: 0,
85250
85251     
85252     clickRange: [5,15],
85253
85254     
85255     clickToChange : true,
85256     
85257     animate: true,
85258
85259     
85260     dragging: false,
85261
85262     
85263     constrainThumbs: true,
85264
85265     componentLayout: 'sliderfield',
85266
85267     
85268     useTips : true,
85269
85270     
85271     tipText : null,
85272
85273     ariaRole: 'slider',
85274
85275     
85276     initValue: function() {
85277         var me = this,
85278             extValue = Ext.value,
85279             
85280             values = extValue(me.values, [extValue(me.value, extValue(me.minValue, 0))]),
85281             i = 0,
85282             len = values.length;
85283
85284         
85285         me.originalValue = values;
85286
85287         
85288         for (; i < len; i++) {
85289             me.addThumb(values[i]);
85290         }
85291     },
85292
85293     
85294     initComponent : function() {
85295         var me = this,
85296             tipPlug,
85297             hasTip;
85298         
85299         
85300         me.thumbs = [];
85301
85302         me.keyIncrement = Math.max(me.increment, me.keyIncrement);
85303
85304         me.addEvents(
85305             
85306             'beforechange',
85307
85308             
85309             'change',
85310
85311             
85312             'changecomplete',
85313
85314             
85315             'dragstart',
85316
85317             
85318             'drag',
85319
85320             
85321             'dragend'
85322         );
85323
85324         if (me.vertical) {
85325             Ext.apply(me, Ext.slider.Multi.Vertical);
85326         }
85327
85328         me.callParent();
85329
85330         
85331         if (me.useTips) {
85332             tipPlug = me.tipText ? {getText: me.tipText} : {};
85333             me.plugins = me.plugins || [];
85334             Ext.each(me.plugins, function(plug){
85335                 if (plug.isSliderTip) {
85336                     hasTip = true;
85337                     return false;
85338                 }
85339             });
85340             if (!hasTip) {
85341                 me.plugins.push(Ext.create('Ext.slider.Tip', tipPlug));
85342             }
85343         }
85344     },
85345
85346     
85347     addThumb: function(value) {
85348         var me = this,
85349             thumb = Ext.create('Ext.slider.Thumb', {
85350             value    : value,
85351             slider   : me,
85352             index    : me.thumbs.length,
85353             constrain: me.constrainThumbs
85354         });
85355         me.thumbs.push(thumb);
85356
85357         
85358         if (me.rendered) {
85359             thumb.render();
85360         }
85361
85362         return thumb;
85363     },
85364
85365     
85366     promoteThumb: function(topThumb) {
85367         var thumbs = this.thumbs,
85368             ln = thumbs.length,
85369             zIndex, thumb, i;
85370             
85371         for (i = 0; i < ln; i++) {
85372             thumb = thumbs[i];
85373
85374             if (thumb == topThumb) {
85375                 thumb.bringToFront();
85376             } else {
85377                 thumb.sendToBack();
85378             }
85379         }
85380     },
85381
85382     
85383     onRender : function() {
85384         var me = this,
85385             i = 0,
85386             thumbs = me.thumbs,
85387             len = thumbs.length,
85388             thumb;
85389
85390         Ext.applyIf(me.subTplData, {
85391             vertical: me.vertical ? Ext.baseCSSPrefix + 'slider-vert' : Ext.baseCSSPrefix + 'slider-horz',
85392             minValue: me.minValue,
85393             maxValue: me.maxValue,
85394             value: me.value
85395         });
85396
85397         Ext.applyIf(me.renderSelectors, {
85398             endEl: '.' + Ext.baseCSSPrefix + 'slider-end',
85399             innerEl: '.' + Ext.baseCSSPrefix + 'slider-inner',
85400             focusEl: '.' + Ext.baseCSSPrefix + 'slider-focus'
85401         });
85402
85403         me.callParent(arguments);
85404
85405         
85406         for (; i < len; i++) {
85407             thumbs[i].render();
85408         }
85409
85410         
85411         thumb = me.innerEl.down('.' + Ext.baseCSSPrefix + 'slider-thumb');
85412         me.halfThumb = (me.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
85413
85414     },
85415
85416     
85417     onChange : function(slider, v) {
85418         this.setValue(v, undefined, true);
85419     },
85420
85421     
85422     initEvents : function() {
85423         var me = this;
85424         
85425         me.mon(me.el, {
85426             scope    : me,
85427             mousedown: me.onMouseDown,
85428             keydown  : me.onKeyDown,
85429             change : me.onChange
85430         });
85431
85432         me.focusEl.swallowEvent("click", true);
85433     },
85434
85435     
85436     onMouseDown : function(e) {
85437         var me = this,
85438             thumbClicked = false,
85439             i = 0,
85440             thumbs = me.thumbs,
85441             len = thumbs.length,
85442             local;
85443             
85444         if (me.disabled) {
85445             return;
85446         }
85447
85448         
85449         for (; i < len; i++) {
85450             thumbClicked = thumbClicked || e.target == thumbs[i].el.dom;
85451         }
85452
85453         if (me.clickToChange && !thumbClicked) {
85454             local = me.innerEl.translatePoints(e.getXY());
85455             me.onClickChange(local);
85456         }
85457         me.focus();
85458     },
85459
85460     
85461     onClickChange : function(local) {
85462         var me = this,
85463             thumb, index;
85464             
85465         if (local.top > me.clickRange[0] && local.top < me.clickRange[1]) {
85466             
85467             thumb = me.getNearest(local, 'left');
85468             if (!thumb.disabled) {
85469                 index = thumb.index;
85470                 me.setValue(index, Ext.util.Format.round(me.reverseValue(local.left), me.decimalPrecision), undefined, true);
85471             }
85472         }
85473     },
85474
85475     
85476     getNearest: function(local, prop) {
85477         var me = this,
85478             localValue = prop == 'top' ? me.innerEl.getHeight() - local[prop] : local[prop],
85479             clickValue = me.reverseValue(localValue),
85480             nearestDistance = (me.maxValue - me.minValue) + 5, 
85481             index = 0,
85482             nearest = null,
85483             thumbs = me.thumbs,
85484             i = 0,
85485             len = thumbs.length,
85486             thumb,
85487             value,
85488             dist;
85489
85490         for (; i < len; i++) {
85491             thumb = me.thumbs[i];
85492             value = thumb.value;
85493             dist  = Math.abs(value - clickValue);
85494
85495             if (Math.abs(dist <= nearestDistance)) {
85496                 nearest = thumb;
85497                 index = i;
85498                 nearestDistance = dist;
85499             }
85500         }
85501         return nearest;
85502     },
85503
85504     
85505     onKeyDown : function(e) {
85506         
85507         var me = this,
85508             k,
85509             val;
85510         
85511         if(me.disabled || me.thumbs.length !== 1) {
85512             e.preventDefault();
85513             return;
85514         }
85515         k = e.getKey();
85516         
85517         switch(k) {
85518             case e.UP:
85519             case e.RIGHT:
85520                 e.stopEvent();
85521                 val = e.ctrlKey ? me.maxValue : me.getValue(0) + me.keyIncrement;
85522                 me.setValue(0, val, undefined, true);
85523             break;
85524             case e.DOWN:
85525             case e.LEFT:
85526                 e.stopEvent();
85527                 val = e.ctrlKey ? me.minValue : me.getValue(0) - me.keyIncrement;
85528                 me.setValue(0, val, undefined, true);
85529             break;
85530             default:
85531                 e.preventDefault();
85532         }
85533     },
85534
85535     
85536     doSnap : function(value) {
85537         var newValue = value,
85538             inc = this.increment,
85539             m;
85540             
85541         if (!(inc && value)) {
85542             return value;
85543         }
85544         m = value % inc;
85545         if (m !== 0) {
85546             newValue -= m;
85547             if (m * 2 >= inc) {
85548                 newValue += inc;
85549             } else if (m * 2 < -inc) {
85550                 newValue -= inc;
85551             }
85552         }
85553         return Ext.Number.constrain(newValue, this.minValue,  this.maxValue);
85554     },
85555
85556     
85557     afterRender : function() {
85558         var me = this,
85559             i = 0,
85560             thumbs = me.thumbs,
85561             len = thumbs.length,
85562             thumb,
85563             v;
85564             
85565         me.callParent(arguments);
85566
85567         for (; i < len; i++) {
85568             thumb = thumbs[i];
85569
85570             if (thumb.value !== undefined) {
85571                 v = me.normalizeValue(thumb.value);
85572                 if (v !== thumb.value) {
85573                     
85574                     me.setValue(i, v, false);
85575                 } else {
85576                     thumb.move(me.translateValue(v), false);
85577                 }
85578             }
85579         }
85580     },
85581
85582     
85583     getRatio : function() {
85584         var w = this.innerEl.getWidth(),
85585             v = this.maxValue - this.minValue;
85586         return v === 0 ? w : (w/v);
85587     },
85588
85589     
85590     normalizeValue : function(v) {
85591         var me = this;
85592         
85593         v = me.doSnap(v);
85594         v = Ext.util.Format.round(v, me.decimalPrecision);
85595         v = Ext.Number.constrain(v, me.minValue, me.maxValue);
85596         return v;
85597     },
85598
85599     
85600     setMinValue : function(val) {
85601         var me = this,
85602             i = 0,
85603             thumbs = me.thumbs,
85604             len = thumbs.length,
85605             t;
85606             
85607         me.minValue = val;
85608         me.inputEl.dom.setAttribute('aria-valuemin', val);
85609
85610         for (; i < len; ++i) {
85611             t = thumbs[i];
85612             t.value = t.value < val ? val : t.value;
85613         }
85614         me.syncThumbs();
85615     },
85616
85617     
85618     setMaxValue : function(val) {
85619         var me = this,
85620             i = 0,
85621             thumbs = me.thumbs,
85622             len = thumbs.length,
85623             t;
85624             
85625         me.maxValue = val;
85626         me.inputEl.dom.setAttribute('aria-valuemax', val);
85627
85628         for (; i < len; ++i) {
85629             t = thumbs[i];
85630             t.value = t.value > val ? val : t.value;
85631         }
85632         me.syncThumbs();
85633     },
85634
85635     
85636     setValue : function(index, value, animate, changeComplete) {
85637         var me = this,
85638             thumb = me.thumbs[index];
85639
85640         
85641         value = me.normalizeValue(value);
85642
85643         if (value !== thumb.value && me.fireEvent('beforechange', me, value, thumb.value, thumb) !== false) {
85644             thumb.value = value;
85645             if (me.rendered) {
85646                 
85647                 
85648                 me.inputEl.set({
85649                     'aria-valuenow': value,
85650                     'aria-valuetext': value
85651                 });
85652
85653                 thumb.move(me.translateValue(value), Ext.isDefined(animate) ? animate !== false : me.animate);
85654
85655                 me.fireEvent('change', me, value, thumb);
85656                 if (changeComplete) {
85657                     me.fireEvent('changecomplete', me, value, thumb);
85658                 }
85659             }
85660         }
85661     },
85662
85663     
85664     translateValue : function(v) {
85665         var ratio = this.getRatio();
85666         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
85667     },
85668
85669     
85670     reverseValue : function(pos) {
85671         var ratio = this.getRatio();
85672         return (pos + (this.minValue * ratio)) / ratio;
85673     },
85674
85675     
85676     focus : function() {
85677         this.focusEl.focus(10);
85678     },
85679
85680     
85681     onDisable: function() {
85682         var me = this,
85683             i = 0,
85684             thumbs = me.thumbs,
85685             len = thumbs.length,
85686             thumb,
85687             el,
85688             xy;
85689             
85690         me.callParent();
85691
85692         for (; i < len; i++) {
85693             thumb = thumbs[i];
85694             el = thumb.el;
85695
85696             thumb.disable();
85697
85698             if(Ext.isIE) {
85699                 
85700                 
85701                 xy = el.getXY();
85702                 el.hide();
85703
85704                 me.innerEl.addCls(me.disabledCls).dom.disabled = true;
85705
85706                 if (!me.thumbHolder) {
85707                     me.thumbHolder = me.endEl.createChild({cls: Ext.baseCSSPrefix + 'slider-thumb ' + me.disabledCls});
85708                 }
85709
85710                 me.thumbHolder.show().setXY(xy);
85711             }
85712         }
85713     },
85714
85715     
85716     onEnable: function() {
85717         var me = this,
85718             i = 0,
85719             thumbs = me.thumbs,
85720             len = thumbs.length,
85721             thumb,
85722             el;
85723             
85724         this.callParent();
85725
85726         for (; i < len; i++) {
85727             thumb = thumbs[i];
85728             el = thumb.el;
85729
85730             thumb.enable();
85731
85732             if (Ext.isIE) {
85733                 me.innerEl.removeCls(me.disabledCls).dom.disabled = false;
85734
85735                 if (me.thumbHolder) {
85736                     me.thumbHolder.hide();
85737                 }
85738
85739                 el.show();
85740                 me.syncThumbs();
85741             }
85742         }
85743     },
85744
85745     
85746     syncThumbs : function() {
85747         if (this.rendered) {
85748             var thumbs = this.thumbs,
85749                 length = thumbs.length,
85750                 i = 0;
85751
85752             for (; i < length; i++) {
85753                 thumbs[i].move(this.translateValue(thumbs[i].value));
85754             }
85755         }
85756     },
85757
85758     
85759     getValue : function(index) {
85760         return Ext.isNumber(index) ? this.thumbs[index].value : this.getValues();
85761     },
85762
85763     
85764     getValues: function() {
85765         var values = [],
85766             i = 0,
85767             thumbs = this.thumbs,
85768             len = thumbs.length;
85769
85770         for (; i < len; i++) {
85771             values.push(thumbs[i].value);
85772         }
85773
85774         return values;
85775     },
85776
85777     getSubmitValue: function() {
85778         var me = this;
85779         return (me.disabled || !me.submitValue) ? null : me.getValue();
85780     },
85781
85782     reset: function() {
85783         var me = this,
85784             Array = Ext.Array;
85785         Array.forEach(Array.from(me.originalValue), function(val, i) {
85786             me.setValue(i, val);
85787         });
85788         me.clearInvalid();
85789         
85790         delete me.wasValid;
85791     },
85792
85793     
85794     beforeDestroy : function() {
85795         var me = this;
85796         
85797         Ext.destroyMembers(me.innerEl, me.endEl, me.focusEl);
85798         Ext.each(me.thumbs, function(thumb) {
85799             Ext.destroy(thumb);
85800         }, me);
85801
85802         me.callParent();
85803     },
85804
85805     statics: {
85806         
85807         Vertical: {
85808             getRatio : function() {
85809                 var h = this.innerEl.getHeight(),
85810                     v = this.maxValue - this.minValue;
85811                 return h/v;
85812             },
85813
85814             onClickChange : function(local) {
85815                 var me = this,
85816                     thumb, index, bottom;
85817
85818                 if (local.left > me.clickRange[0] && local.left < me.clickRange[1]) {
85819                     thumb = me.getNearest(local, 'top');
85820                     if (!thumb.disabled) {
85821                         index = thumb.index;
85822                         bottom =  me.reverseValue(me.innerEl.getHeight() - local.top);
85823
85824                         me.setValue(index, Ext.util.Format.round(me.minValue + bottom, me.decimalPrecision), undefined, true);
85825                     }
85826                 }
85827             }
85828         }
85829     }
85830 });
85831
85832
85833 Ext.define('Ext.slider.Single', {
85834     extend: 'Ext.slider.Multi',
85835     alias: ['widget.slider', 'widget.sliderfield'],
85836     alternateClassName: ['Ext.Slider', 'Ext.form.SliderField', 'Ext.slider.SingleSlider', 'Ext.slider.Slider'],
85837
85838     
85839     getValue: function() {
85840         
85841         return this.callParent([0]);
85842     },
85843
85844     
85845     setValue: function(value, animate) {
85846         var args = Ext.toArray(arguments),
85847             len  = args.length;
85848
85849         
85850         
85851         
85852         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
85853             args.unshift(0);
85854         }
85855
85856         return this.callParent(args);
85857     },
85858
85859     
85860     getNearest : function(){
85861         
85862         return this.thumbs[0];
85863     }
85864 });
85865
85866
85867 Ext.define('Ext.tab.Tab', {
85868     extend: 'Ext.button.Button',
85869     alias: 'widget.tab',
85870     
85871     requires: [
85872         'Ext.layout.component.Tab',
85873         'Ext.util.KeyNav'
85874     ],
85875
85876     componentLayout: 'tab',
85877
85878     isTab: true,
85879
85880     baseCls: Ext.baseCSSPrefix + 'tab',
85881
85882     
85883     activeCls: 'active',
85884     
85885     
85886
85887     
85888     closableCls: 'closable',
85889
85890     
85891     closable: true,
85892
85893     
85894     closeText: 'Close Tab',
85895
85896     
85897     active: false,
85898
85899     
85900
85901     scale: false,
85902
85903     position: 'top',
85904     
85905     initComponent: function() {
85906         var me = this;
85907
85908         me.addEvents(
85909             
85910             'activate',
85911
85912             
85913             'deactivate',
85914
85915             
85916             'beforeclose',
85917
85918             
85919             'close'
85920         );
85921         
85922         me.callParent(arguments);
85923
85924         if (me.card) {
85925             me.setCard(me.card);
85926         }
85927     },
85928
85929     
85930     onRender: function() {
85931         var me = this;
85932         
85933         me.addClsWithUI(me.position);
85934         
85935         
85936         
85937
85938         me.syncClosableUI();
85939
85940         me.callParent(arguments);
85941         
85942         if (me.active) {
85943             me.activate(true);
85944         }
85945
85946         me.syncClosableElements();
85947         
85948         me.keyNav = Ext.create('Ext.util.KeyNav', me.el, {
85949             enter: me.onEnterKey,
85950             del: me.onDeleteKey,
85951             scope: me
85952         });
85953     },
85954     
85955     
85956     enable : function(silent) {
85957         var me = this;
85958
85959         me.callParent(arguments);
85960         
85961         me.removeClsWithUI(me.position + '-disabled');
85962
85963         return me;
85964     },
85965
85966     
85967     disable : function(silent) {
85968         var me = this;
85969         
85970         me.callParent(arguments);
85971         
85972         me.addClsWithUI(me.position + '-disabled');
85973
85974         return me;
85975     },
85976     
85977     
85978     onDestroy: function() {
85979         var me = this;
85980
85981         if (me.closeEl) {
85982             me.closeEl.un('click', Ext.EventManager.preventDefault);
85983             me.closeEl = null;
85984         }
85985
85986         Ext.destroy(me.keyNav);
85987         delete me.keyNav;
85988
85989         me.callParent(arguments);
85990     },
85991
85992     
85993     setClosable: function(closable) {
85994         var me = this;
85995
85996         
85997         closable = (!arguments.length || !!closable);
85998
85999         if (me.closable != closable) {
86000             me.closable = closable;
86001
86002             
86003             if (me.card) {
86004                 me.card.closable = closable;
86005             }
86006
86007             me.syncClosableUI();
86008
86009             if (me.rendered) {
86010                 me.syncClosableElements();
86011
86012                 
86013                 me.doComponentLayout();
86014                 if (me.ownerCt) {
86015                     me.ownerCt.doLayout();
86016                 }
86017             }
86018         }
86019     },
86020
86021     
86022     syncClosableElements: function () {
86023         var me = this;
86024
86025         if (me.closable) {
86026             if (!me.closeEl) {
86027                 me.closeEl = me.el.createChild({
86028                     tag: 'a',
86029                     cls: me.baseCls + '-close-btn',
86030                     href: '#',
86031                     html: me.closeText,
86032                     title: me.closeText
86033                 }).on('click', Ext.EventManager.preventDefault);  
86034             }
86035         } else {
86036             var closeEl = me.closeEl;
86037             if (closeEl) {
86038                 closeEl.un('click', Ext.EventManager.preventDefault);
86039                 closeEl.remove();
86040                 me.closeEl = null;
86041             }
86042         }
86043     },
86044
86045     
86046     syncClosableUI: function () {
86047         var me = this, classes = [me.closableCls, me.closableCls + '-' + me.position];
86048
86049         if (me.closable) {
86050             me.addClsWithUI(classes);
86051         } else {
86052             me.removeClsWithUI(classes);
86053         }
86054     },
86055
86056     
86057     setCard: function(card) {
86058         var me = this;
86059
86060         me.card = card;
86061         me.setText(me.title || card.title);
86062         me.setIconCls(me.iconCls || card.iconCls);
86063     },
86064
86065     
86066     onCloseClick: function() {
86067         var me = this;
86068
86069         if (me.fireEvent('beforeclose', me) !== false) {
86070             if (me.tabBar) {
86071                 me.tabBar.closeTab(me);
86072             }
86073
86074             me.fireEvent('close', me);
86075         }
86076     },
86077     
86078     
86079     onEnterKey: function(e) {
86080         var me = this;
86081         
86082         if (me.tabBar) {
86083             me.tabBar.onClick(e, me.el);
86084         }
86085     },
86086     
86087    
86088     onDeleteKey: function(e) {
86089         var me = this;
86090         
86091         if (me.closable) {
86092             me.onCloseClick();
86093         }
86094     },
86095     
86096     
86097     activate : function(supressEvent) {
86098         var me = this;
86099         
86100         me.active = true;
86101         me.addClsWithUI([me.activeCls, me.position + '-' + me.activeCls]);
86102
86103         if (supressEvent !== true) {
86104             me.fireEvent('activate', me);
86105         }
86106     },
86107
86108     
86109     deactivate : function(supressEvent) {
86110         var me = this;
86111         
86112         me.active = false;
86113         me.removeClsWithUI([me.activeCls, me.position + '-' + me.activeCls]);
86114         
86115         if (supressEvent !== true) {
86116             me.fireEvent('deactivate', me);
86117         }
86118     }
86119 });
86120
86121
86122 Ext.define('Ext.tab.Bar', {
86123     extend: 'Ext.panel.Header',
86124     alias: 'widget.tabbar',
86125     baseCls: Ext.baseCSSPrefix + 'tab-bar',
86126
86127     requires: [
86128         'Ext.tab.Tab',
86129         'Ext.FocusManager'
86130     ],
86131
86132     
86133     defaultType: 'tab',
86134
86135     
86136     plain: false,
86137
86138     
86139     renderTpl: [
86140         '<div class="{baseCls}-body<tpl if="ui"> {baseCls}-body-{ui}<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl></tpl>"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>',
86141         '<div class="{baseCls}-strip<tpl if="ui"> {baseCls}-strip-{ui}<tpl for="uiCls"> {parent.baseCls}-strip-{parent.ui}-{.}</tpl></tpl>"></div>'
86142     ],
86143
86144     
86145     minTabWidth: 30,
86146
86147     
86148     maxTabWidth: undefined,
86149
86150     
86151     initComponent: function() {
86152         var me = this,
86153             keys;
86154
86155         if (me.plain) {
86156             me.setUI(me.ui + '-plain');
86157         }
86158         
86159         me.addClsWithUI(me.dock);
86160
86161         me.addEvents(
86162             
86163             'change'
86164         );
86165
86166         Ext.applyIf(this.renderSelectors, {
86167             body : '.' + this.baseCls + '-body',
86168             strip: '.' + this.baseCls + '-strip'
86169         });
86170         me.callParent(arguments);
86171
86172         
86173         me.layout.align = (me.orientation == 'vertical') ? 'left' : 'top';
86174         me.layout.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.Scroller', me.layout);
86175         me.items.removeAt(me.items.getCount() - 1);
86176         me.items.removeAt(me.items.getCount() - 1);
86177         
86178         
86179         keys = me.orientation == 'vertical' ? ['up', 'down'] : ['left', 'right'];
86180         Ext.FocusManager.subscribe(me, {
86181             keys: keys
86182         });
86183     },
86184
86185     
86186     onAdd: function(tab) {
86187         var me = this,
86188             tabPanel = me.tabPanel,
86189             hasOwner = !!tabPanel;
86190
86191         me.callParent(arguments);
86192         tab.position = me.dock;
86193         if (hasOwner) {
86194             tab.minWidth = tabPanel.minTabWidth;
86195         }
86196         else {
86197             tab.minWidth = me.minTabWidth + (tab.iconCls ? 25 : 0);
86198         }
86199         tab.maxWidth = me.maxTabWidth || (hasOwner ? tabPanel.maxTabWidth : undefined);
86200     },
86201
86202     
86203     afterRender: function() {
86204         var me = this;
86205
86206         me.mon(me.el, {
86207             scope: me,
86208             click: me.onClick,
86209             delegate: '.' + Ext.baseCSSPrefix + 'tab'
86210         });
86211         me.callParent(arguments);
86212         
86213     },
86214
86215     afterComponentLayout : function() {
86216         var me = this;
86217         
86218         me.callParent(arguments);
86219         me.strip.setWidth(me.el.getWidth());
86220     },
86221
86222     
86223     onClick: function(e, target) {
86224         
86225         var tab = Ext.getCmp(target.id),
86226             tabPanel = this.tabPanel;
86227
86228         target = e.getTarget();
86229
86230         if (tab && tab.isDisabled && !tab.isDisabled()) {
86231             if (tab.closable && target === tab.closeEl.dom) {
86232                 tab.onCloseClick();
86233             } else {
86234                 this.setActiveTab(tab);
86235                 if (tabPanel) {
86236                     tabPanel.setActiveTab(tab.card);
86237                 }
86238                 tab.focus();
86239             }
86240         }
86241     },
86242
86243     
86244     closeTab: function(tab) {
86245         var card    = tab.card,
86246             tabPanel = this.tabPanel,
86247             nextTab;
86248
86249         if (tab.active && this.items.getCount() > 1) {
86250             nextTab = tab.next('tab') || this.items.items[0];
86251             this.setActiveTab(nextTab);
86252             if (tabPanel) {
86253                 tabPanel.setActiveTab(nextTab.card);
86254             }
86255         }
86256         this.remove(tab);
86257
86258         if (tabPanel && card) {
86259             tabPanel.remove(card);
86260         }
86261         
86262         if (nextTab) {
86263             nextTab.focus();
86264         }
86265     },
86266
86267     
86268     setActiveTab: function(tab) {
86269         if (tab.disabled) {
86270             return;
86271         }
86272         var me = this;
86273         if (me.activeTab) {
86274             me.activeTab.deactivate();
86275         }
86276         tab.activate();
86277         
86278         if (me.rendered) {
86279             me.layout.layout();
86280             tab.el.scrollIntoView(me.layout.getRenderTarget());
86281         }
86282         me.activeTab = tab;
86283         me.fireEvent('change', me, tab, tab.card);
86284     }
86285 });
86286
86287 Ext.define('Ext.tab.Panel', {
86288     extend: 'Ext.panel.Panel',
86289     alias: 'widget.tabpanel',
86290     alternateClassName: ['Ext.TabPanel'],
86291
86292     requires: ['Ext.layout.container.Card', 'Ext.tab.Bar'],
86293
86294     
86295     tabPosition : 'top',
86296     
86297     
86298
86299     
86300
86301     
86302     removePanelHeader: true,
86303
86304     
86305     plain: false,
86306
86307     
86308     itemCls: 'x-tabpanel-child',
86309
86310     
86311
86312     
86313     deferredRender : true,
86314
86315     
86316     initComponent: function() {
86317         var me = this,
86318             dockedItems = me.dockedItems || [],
86319             activeTab = me.activeTab || 0;
86320
86321         me.layout = Ext.create('Ext.layout.container.Card', Ext.apply({
86322             owner: me,
86323             deferredRender: me.deferredRender,
86324             itemCls: me.itemCls
86325         }, me.layout));
86326
86327         
86328         me.tabBar = Ext.create('Ext.tab.Bar', Ext.apply({}, me.tabBar, {
86329             dock: me.tabPosition,
86330             plain: me.plain,
86331             border: me.border,
86332             cardLayout: me.layout,
86333             tabPanel: me
86334         }));
86335
86336         if (dockedItems && !Ext.isArray(dockedItems)) {
86337             dockedItems = [dockedItems];
86338         }
86339
86340         dockedItems.push(me.tabBar);
86341         me.dockedItems = dockedItems;
86342
86343         me.addEvents(
86344             
86345             'beforetabchange',
86346
86347             
86348             'tabchange'
86349         );
86350         me.callParent(arguments);
86351
86352         
86353         me.setActiveTab(activeTab);
86354         
86355         me.on('afterlayout', me.afterInitialLayout, me, {single: true});
86356     },
86357
86358     
86359     afterInitialLayout: function() {
86360         var me = this,
86361             card = me.getComponent(me.activeTab);
86362             
86363         if (card) {
86364             me.layout.setActiveItem(card);
86365         }
86366     },
86367
86368     
86369     setActiveTab: function(card) {
86370         var me = this,
86371             previous;
86372
86373         card = me.getComponent(card);
86374         if (card) {
86375             previous = me.getActiveTab();
86376             
86377             if (previous && previous !== card && me.fireEvent('beforetabchange', me, card, previous) === false) {
86378                 return false;
86379             }
86380             
86381             me.tabBar.setActiveTab(card.tab);
86382             me.activeTab = card;
86383             if (me.rendered) {
86384                 me.layout.setActiveItem(card);
86385             }
86386             
86387             if (previous && previous !== card) {
86388                 me.fireEvent('tabchange', me, card, previous);
86389             }
86390         }
86391     },
86392
86393     
86394     getActiveTab: function() {
86395         return this.activeTab;
86396     },
86397
86398     
86399     getTabBar: function() {
86400         return this.tabBar;
86401     },
86402
86403     
86404     onAdd: function(item, index) {
86405         var me = this;
86406
86407         item.tab = me.tabBar.insert(index, {
86408             xtype: 'tab',
86409             card: item,
86410             disabled: item.disabled,
86411             closable: item.closable,
86412             hidden: item.hidden,
86413             tabBar: me.tabBar
86414         });
86415         
86416         item.on({
86417             scope : me,
86418             enable: me.onItemEnable,
86419             disable: me.onItemDisable,
86420             beforeshow: me.onItemBeforeShow,
86421             iconchange: me.onItemIconChange,
86422             titlechange: me.onItemTitleChange
86423         });
86424
86425         if (item.isPanel) {
86426             if (me.removePanelHeader) {
86427                 item.preventHeader = true;
86428                 if (item.rendered) {
86429                     item.updateHeader();
86430                 }
86431             }
86432             if (item.isPanel && me.border) {
86433                 item.setBorder(false);
86434             }
86435         }
86436
86437         
86438         if (this.rendered && me.items.getCount() === 1) {
86439             me.setActiveTab(0);
86440         }
86441     },
86442     
86443     
86444     onItemEnable: function(item){
86445         item.tab.enable();
86446     },
86447
86448         
86449     onItemDisable: function(item){
86450         item.tab.disable();
86451     },
86452     
86453     
86454     onItemBeforeShow: function(item) {
86455         if (item !== this.activeTab) {
86456             this.setActiveTab(item);
86457             return false;
86458         }    
86459     },
86460     
86461     
86462     onItemIconChange: function(item, newIconCls) {
86463         item.tab.setIconCls(newIconCls);
86464         this.getTabBar().doLayout();
86465     },
86466     
86467     
86468     onItemTitleChange: function(item, newTitle) {
86469         item.tab.setText(newTitle);
86470         this.getTabBar().doLayout();
86471     },
86472
86473
86474     
86475     doRemove: function(item, autoDestroy) {
86476         var me = this,
86477             items = me.items,
86478             
86479             hasItemsLeft = items.getCount() > 1;
86480
86481         if (me.destroying || !hasItemsLeft) {
86482             me.activeTab = null;
86483         } else if (item === me.activeTab) {
86484              me.setActiveTab(item.next() || items.getAt(0)); 
86485         }
86486         me.callParent(arguments);
86487
86488         
86489         delete item.tab.card;
86490         delete item.tab;
86491     },
86492
86493     
86494     onRemove: function(item, autoDestroy) {
86495         var me = this;
86496         
86497         item.un({
86498             scope : me,
86499             enable: me.onItemEnable,
86500             disable: me.onItemDisable,
86501             beforeshow: me.onItemBeforeShow
86502         });
86503         if (!me.destroying && item.tab.ownerCt == me.tabBar) {
86504             me.tabBar.remove(item.tab);
86505         }
86506     }
86507 });
86508
86509
86510 Ext.define('Ext.toolbar.Spacer', {
86511     extend: 'Ext.Component',
86512     alias: 'widget.tbspacer',
86513     alternateClassName: 'Ext.Toolbar.Spacer',
86514     baseCls: Ext.baseCSSPrefix + 'toolbar-spacer',
86515     focusable: false
86516 });
86517
86518 Ext.define('Ext.tree.Column', {
86519     extend: 'Ext.grid.column.Column',
86520     alias: 'widget.treecolumn',
86521
86522     initComponent: function() {
86523         var origRenderer = this.renderer || this.defaultRenderer,
86524             origScope    = this.scope || window;
86525
86526         this.renderer = function(value, metaData, record, rowIdx, colIdx, store, view) {
86527             var buf   = [],
86528                 format = Ext.String.format,
86529                 depth = record.getDepth(),
86530                 treePrefix  = Ext.baseCSSPrefix + 'tree-',
86531                 elbowPrefix = treePrefix + 'elbow-',
86532                 expanderCls = treePrefix + 'expander',
86533                 imgText     = '<img src="{1}" class="{0}" />',
86534                 checkboxText= '<input type="button" role="checkbox" class="{0}" {1} />',
86535                 formattedValue = origRenderer.apply(origScope, arguments),
86536                 href = record.get('href'),
86537                 target = record.get('hrefTarget');
86538
86539             while (record) {
86540                 if (!record.isRoot() || (record.isRoot() && view.rootVisible)) {
86541                     if (record.getDepth() === depth) {
86542                         buf.unshift(format(imgText,
86543                             treePrefix + 'icon ' + 
86544                             treePrefix + 'icon' + (record.get('icon') ? '-inline ' : (record.isLeaf() ? '-leaf ' : '-parent ')) +
86545                             (record.get('iconCls') || ''),
86546                             record.get('icon') || Ext.BLANK_IMAGE_URL
86547                         ));
86548                         if (record.get('checked') !== null) {
86549                             buf.unshift(format(
86550                                 checkboxText,
86551                                 (treePrefix + 'checkbox') + (record.get('checked') ? ' ' + treePrefix + 'checkbox-checked' : ''),
86552                                 record.get('checked') ? 'aria-checked="true"' : ''
86553                             ));
86554                             if (record.get('checked')) {
86555                                 metaData.tdCls += (' ' + Ext.baseCSSPrefix + 'tree-checked');
86556                             }
86557                         }
86558                         if (record.isLast()) {
86559                             if (record.isLeaf() || (record.isLoaded() && !record.hasChildNodes())) {
86560                                 buf.unshift(format(imgText, (elbowPrefix + 'end'), Ext.BLANK_IMAGE_URL));
86561                             } else {
86562                                 buf.unshift(format(imgText, (elbowPrefix + 'end-plus ' + expanderCls), Ext.BLANK_IMAGE_URL));
86563                             }
86564                             
86565                         } else {
86566                             if (record.isLeaf() || (record.isLoaded() && !record.hasChildNodes())) {
86567                                 buf.unshift(format(imgText, (treePrefix + 'elbow'), Ext.BLANK_IMAGE_URL));
86568                             } else {
86569                                 buf.unshift(format(imgText, (elbowPrefix + 'plus ' + expanderCls), Ext.BLANK_IMAGE_URL));
86570                             }
86571                         }
86572                     } else {
86573                         if (record.isLast() || record.getDepth() === 0) {
86574                             buf.unshift(format(imgText, (elbowPrefix + 'empty'), Ext.BLANK_IMAGE_URL));
86575                         } else if (record.getDepth() !== 0) {
86576                             buf.unshift(format(imgText, (elbowPrefix + 'line'), Ext.BLANK_IMAGE_URL));
86577                         }                      
86578                     }
86579                 }
86580                 record = record.parentNode;
86581             }
86582             if (href) {
86583                 formattedValue = format('<a href="{0}" target="{1}">{2}</a>', href, target, formattedValue);
86584             }
86585             return buf.join("") + formattedValue;
86586         };
86587         this.callParent(arguments);
86588     },
86589
86590     defaultRenderer: function(value) {
86591         return value;
86592     }
86593 });
86594
86595 Ext.define('Ext.tree.View', {
86596     extend: 'Ext.view.Table',
86597     alias: 'widget.treeview',
86598
86599     loadingCls: Ext.baseCSSPrefix + 'grid-tree-loading',
86600     expandedCls: Ext.baseCSSPrefix + 'grid-tree-node-expanded',
86601
86602     expanderSelector: '.' + Ext.baseCSSPrefix + 'tree-expander',
86603     checkboxSelector: '.' + Ext.baseCSSPrefix + 'tree-checkbox',
86604     expanderIconOverCls: Ext.baseCSSPrefix + 'tree-expander-over',
86605
86606     blockRefresh: true,
86607
86608     
86609     rootVisible: true,
86610
86611     
86612
86613     expandDuration: 250,
86614     collapseDuration: 250,
86615     
86616     toggleOnDblClick: true,
86617
86618     initComponent: function() {
86619         var me = this;
86620         
86621         if (me.initialConfig.animate === undefined) {
86622             me.animate = Ext.enableFx;
86623         }
86624         
86625         me.store = Ext.create('Ext.data.NodeStore', {
86626             recursive: true,
86627             rootVisible: me.rootVisible,
86628             listeners: {
86629                 beforeexpand: me.onBeforeExpand,
86630                 expand: me.onExpand,
86631                 beforecollapse: me.onBeforeCollapse,
86632                 collapse: me.onCollapse,
86633                 scope: me
86634             }
86635         });
86636         
86637         if (me.node) {
86638             me.setRootNode(me.node);
86639         }
86640         me.animQueue = {};
86641         me.callParent(arguments);
86642     },
86643     
86644     onClear: function(){
86645         this.store.removeAll();    
86646     },
86647
86648     setRootNode: function(node) {
86649         var me = this;        
86650         me.store.setNode(node);
86651         me.node = node;
86652         if (!me.rootVisible) {
86653             node.expand();
86654         }
86655     },
86656     
86657     onRender: function() {
86658         var me = this,
86659             opts = {delegate: me.expanderSelector},
86660             el;
86661
86662         me.callParent(arguments);
86663
86664         el = me.el;
86665         el.on({
86666             scope: me,
86667             delegate: me.expanderSelector,
86668             mouseover: me.onExpanderMouseOver,
86669             mouseout: me.onExpanderMouseOut
86670         });
86671         el.on({
86672             scope: me,
86673             delegate: me.checkboxSelector,
86674             click: me.onCheckboxChange
86675         });
86676     },
86677
86678     onCheckboxChange: function(e, t) {
86679         var item = e.getTarget(this.getItemSelector(), this.getTargetEl()),
86680             record, value;
86681             
86682         if (item) {
86683             record = this.getRecord(item);
86684             value = !record.get('checked');
86685             record.set('checked', value);
86686             this.fireEvent('checkchange', record, value);
86687         }
86688     },
86689
86690     getChecked: function() {
86691         var checked = [];
86692         this.node.cascadeBy(function(rec){
86693             if (rec.get('checked')) {
86694                 checked.push(rec);
86695             }
86696         });
86697         return checked;
86698     },
86699     
86700     isItemChecked: function(rec){
86701         return rec.get('checked');
86702     },
86703
86704     createAnimWrap: function(record, index) {
86705         var thHtml = '',
86706             headerCt = this.panel.headerCt,
86707             headers = headerCt.getGridColumns(),
86708             i = 0, len = headers.length, item,
86709             node = this.getNode(record),
86710             tmpEl, nodeEl;
86711
86712         for (; i < len; i++) {
86713             item = headers[i];
86714             thHtml += '<th style="width: ' + (item.hidden ? 0 : item.getDesiredWidth()) + 'px; height: 0px;"></th>';
86715         }
86716
86717         nodeEl = Ext.get(node);        
86718         tmpEl = nodeEl.insertSibling({
86719             tag: 'tr',
86720             html: [
86721                 '<td colspan="' + headerCt.getColumnCount() + '">',
86722                     '<div class="' + Ext.baseCSSPrefix + 'tree-animator-wrap' + '">',
86723                         '<table class="' + Ext.baseCSSPrefix + 'grid-table" style="width: ' + headerCt.getFullWidth() + 'px;"><tbody>',
86724                             thHtml,
86725                         '</tbody></table>',
86726                     '</div>',
86727                 '</td>'
86728             ].join('')
86729         }, 'after');
86730
86731         return {
86732             record: record,
86733             node: node,
86734             el: tmpEl,
86735             expanding: false,
86736             collapsing: false,
86737             animating: false,
86738             animateEl: tmpEl.down('div'),
86739             targetEl: tmpEl.down('tbody')
86740         };
86741     },
86742
86743     getAnimWrap: function(parent) {
86744         if (!this.animate) {
86745             return null;
86746         }
86747
86748         
86749         while (parent) {
86750             if (parent.animWrap) {
86751                 return parent.animWrap;
86752             }
86753             parent = parent.parentNode;
86754         }
86755         return null;
86756     },
86757
86758     doAdd: function(nodes, records, index) {
86759         
86760         
86761         var me = this,
86762             record = records[0],
86763             parent = record.parentNode,
86764             a = me.all.elements,
86765             relativeIndex = 0,
86766             animWrap = me.getAnimWrap(parent),
86767             targetEl, children, len;
86768
86769         if (!animWrap || !animWrap.expanding) {
86770             me.resetScrollers();
86771             return me.callParent(arguments);
86772         }
86773
86774         
86775         parent = animWrap.record;
86776         
86777         
86778         targetEl = animWrap.targetEl;
86779         children = targetEl.dom.childNodes;
86780         
86781         
86782         len = children.length - 1;
86783         
86784         
86785         relativeIndex = index - me.indexOf(parent) - 1;
86786         
86787         
86788         
86789         if (!len || relativeIndex >= len) {
86790             targetEl.appendChild(nodes);
86791         }
86792         
86793         
86794         else {
86795             
86796             Ext.fly(children[relativeIndex + 1]).insertSibling(nodes, 'before', true);
86797         }
86798         
86799         
86800         if (index < a.length) {
86801             a.splice.apply(a, [index, 0].concat(nodes));
86802         }
86803         else {            
86804             a.push.apply(a, nodes);
86805         }
86806         
86807         
86808         
86809         if (animWrap.isAnimating) {
86810             me.onExpand(parent);
86811         }
86812     },
86813     
86814     doRemove: function(record, index) {
86815         
86816         
86817         var me = this,
86818             parent = record.parentNode,
86819             all = me.all,
86820             animWrap = me.getAnimWrap(record),
86821             node = all.item(index).dom;
86822
86823         if (!animWrap || !animWrap.collapsing) {
86824             me.resetScrollers();
86825             return me.callParent(arguments);
86826         }
86827
86828         animWrap.targetEl.appendChild(node);
86829         all.removeElement(index);
86830     },
86831
86832     onBeforeExpand: function(parent, records, index) {
86833         var me = this,
86834             animWrap;
86835             
86836         if (!me.animate) {
86837             return;
86838         }
86839
86840         if (me.getNode(parent)) {
86841             animWrap = me.getAnimWrap(parent);
86842             if (!animWrap) {
86843                 animWrap = parent.animWrap = me.createAnimWrap(parent);
86844                 animWrap.animateEl.setHeight(0);
86845             }
86846             else if (animWrap.collapsing) {
86847                 
86848                 
86849                 animWrap.targetEl.select(me.itemSelector).remove();
86850             } 
86851             animWrap.expanding = true;
86852             animWrap.collapsing = false;
86853         }
86854     },
86855
86856     onExpand: function(parent) {
86857         var me = this,
86858             queue = me.animQueue,
86859             id = parent.getId(),
86860             animWrap,
86861             animateEl, 
86862             targetEl,
86863             queueItem;        
86864         
86865         if (me.singleExpand) {
86866             me.ensureSingleExpand(parent);
86867         }
86868         
86869         animWrap = me.getAnimWrap(parent);
86870
86871         if (!animWrap) {
86872             me.resetScrollers();
86873             return;
86874         }
86875         
86876         animateEl = animWrap.animateEl;
86877         targetEl = animWrap.targetEl;
86878
86879         animateEl.stopAnimation();
86880         
86881         queue[id] = true;
86882         animateEl.slideIn('t', {
86883             duration: me.expandDuration,
86884             listeners: {
86885                 scope: me,
86886                 lastframe: function() {
86887                     
86888                     animWrap.el.insertSibling(targetEl.query(me.itemSelector), 'before');
86889                     animWrap.el.remove();
86890                     me.resetScrollers();
86891                     delete animWrap.record.animWrap;
86892                     delete queue[id];
86893                 }
86894             }
86895         });
86896         
86897         animWrap.isAnimating = true;
86898     },
86899     
86900     resetScrollers: function(){
86901         var panel = this.panel;
86902         
86903         panel.determineScrollbars();
86904         panel.invalidateScroller();
86905     },
86906
86907     onBeforeCollapse: function(parent, records, index) {
86908         var me = this,
86909             animWrap;
86910             
86911         if (!me.animate) {
86912             return;
86913         }
86914
86915         if (me.getNode(parent)) {
86916             animWrap = me.getAnimWrap(parent);
86917             if (!animWrap) {
86918                 animWrap = parent.animWrap = me.createAnimWrap(parent, index);
86919             }
86920             else if (animWrap.expanding) {
86921                 
86922                 
86923                 animWrap.targetEl.select(this.itemSelector).remove();
86924             }
86925             animWrap.expanding = false;
86926             animWrap.collapsing = true;
86927         }
86928     },
86929     
86930     onCollapse: function(parent) {
86931         var me = this,
86932             queue = me.animQueue,
86933             id = parent.getId(),
86934             animWrap = me.getAnimWrap(parent),
86935             animateEl, targetEl;
86936
86937         if (!animWrap) {
86938             me.resetScrollers();
86939             return;
86940         }
86941         
86942         animateEl = animWrap.animateEl;
86943         targetEl = animWrap.targetEl;
86944
86945         queue[id] = true;
86946         
86947         
86948         animateEl.stopAnimation();
86949         animateEl.slideOut('t', {
86950             duration: me.collapseDuration,
86951             listeners: {
86952                 scope: me,
86953                 lastframe: function() {
86954                     animWrap.el.remove();
86955                     delete animWrap.record.animWrap;
86956                     me.resetScrollers();
86957                     delete queue[id];
86958                 }             
86959             }
86960         });
86961         animWrap.isAnimating = true;
86962     },
86963     
86964     
86965     isAnimating: function(node) {
86966         return !!this.animQueue[node.getId()];    
86967     },
86968     
86969     collectData: function(records) {
86970         var data = this.callParent(arguments),
86971             rows = data.rows,
86972             len = rows.length,
86973             i = 0,
86974             row, record;
86975             
86976         for (; i < len; i++) {
86977             row = rows[i];
86978             record = records[i];
86979             if (record.get('qtip')) {
86980                 row.rowAttr = 'data-qtip="' + record.get('qtip') + '"';
86981                 if (record.get('qtitle')) {
86982                     row.rowAttr += ' ' + 'data-qtitle="' + record.get('qtitle') + '"';
86983                 }
86984             }
86985             if (record.isExpanded()) {
86986                 row.rowCls = (row.rowCls || '') + ' ' + this.expandedCls;
86987             }
86988             if (record.isLoading()) {
86989                 row.rowCls = (row.rowCls || '') + ' ' + this.loadingCls;
86990             }
86991         }
86992         
86993         return data;
86994     },
86995     
86996     
86997     expand: function(record, deep, callback, scope) {
86998         return record.expand(deep, callback, scope);
86999     },
87000     
87001     
87002     collapse: function(record, deep, callback, scope) {
87003         return record.collapse(deep, callback, scope);
87004     },
87005     
87006     
87007     toggle: function(record) {
87008         this[record.isExpanded() ? 'collapse' : 'expand'](record);
87009     },
87010     
87011     onItemDblClick: function(record, item, index) {
87012         this.callParent(arguments);
87013         if (this.toggleOnDblClick) {
87014             this.toggle(record);
87015         }
87016     },
87017     
87018     onBeforeItemMouseDown: function(record, item, index, e) {
87019         if (e.getTarget(this.expanderSelector, item)) {
87020             return false;
87021         }
87022         return this.callParent(arguments);
87023     },
87024     
87025     onItemClick: function(record, item, index, e) {
87026         if (e.getTarget(this.expanderSelector, item)) {
87027             this.toggle(record);
87028             return false;
87029         }
87030         return this.callParent(arguments);
87031     },
87032     
87033     onExpanderMouseOver: function(e, t) {
87034         e.getTarget(this.cellSelector, 10, true).addCls(this.expanderIconOverCls);
87035     },
87036     
87037     onExpanderMouseOut: function(e, t) {
87038         e.getTarget(this.cellSelector, 10, true).removeCls(this.expanderIconOverCls);
87039     },
87040     
87041     
87042     getTreeStore: function() {
87043         return this.panel.store;
87044     },    
87045     
87046     ensureSingleExpand: function(node) {
87047         var parent = node.parentNode;
87048         if (parent) {
87049             parent.eachChild(function(child) {
87050                 if (child !== node && child.isExpanded()) {
87051                     child.collapse();
87052                 }
87053             });
87054         }
87055     }
87056 });
87057
87058 Ext.define('Ext.tree.Panel', {
87059     extend: 'Ext.panel.Table',
87060     alias: 'widget.treepanel',
87061     alternateClassName: ['Ext.tree.TreePanel', 'Ext.TreePanel'],
87062     requires: ['Ext.tree.View', 'Ext.selection.TreeModel', 'Ext.tree.Column'],
87063     viewType: 'treeview',
87064     selType: 'treemodel',
87065     
87066     treeCls: Ext.baseCSSPrefix + 'tree-panel',
87067     
87068     
87069     lines: true,
87070     
87071     
87072     useArrows: false,
87073     
87074     
87075     singleExpand: false,
87076     
87077     ddConfig: {
87078         enableDrag: true,
87079         enableDrop: true
87080     },
87081     
87082     
87083             
87084     
87085     rootVisible: true,
87086     
87087         
87088     displayField: 'text',
87089
87090     
87091     root: null,
87092     
87093     
87094     
87095     normalCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible', 'scroll'],
87096     lockedCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible'],
87097
87098     
87099     
87100      
87101     
87102     constructor: function(config) {
87103         config = config || {};
87104         if (config.animate === undefined) {
87105             config.animate = Ext.enableFx;
87106         }
87107         this.enableAnimations = config.animate;
87108         delete config.animate;
87109         
87110         this.callParent([config]);
87111     },
87112     
87113     initComponent: function() {
87114         var me = this,
87115             cls = [me.treeCls];
87116
87117         if (me.useArrows) {
87118             cls.push(Ext.baseCSSPrefix + 'tree-arrows');
87119             me.lines = false;
87120         }
87121         
87122         if (me.lines) {
87123             cls.push(Ext.baseCSSPrefix + 'tree-lines');
87124         } else if (!me.useArrows) {
87125             cls.push(Ext.baseCSSPrefix + 'tree-no-lines');
87126         }
87127
87128         if (!me.store || Ext.isObject(me.store) && !me.store.isStore) {
87129             me.store = Ext.create('Ext.data.TreeStore', Ext.apply({}, me.store || {}, {
87130                 root: me.root,
87131                 fields: me.fields,
87132                 model: me.model,
87133                 folderSort: me.folderSort
87134             }));
87135         }
87136         else if (me.root) {
87137             me.store = Ext.data.StoreManager.lookup(me.store);
87138             me.store.setRootNode(me.root);
87139             if (me.folderSort !== undefined) {
87140                 me.store.folderSort = me.folderSort;
87141                 me.store.sort();
87142             }            
87143         }
87144         
87145         
87146         
87147         
87148         
87149         
87150         me.viewConfig = Ext.applyIf(me.viewConfig || {}, {
87151             rootVisible: me.rootVisible,
87152             animate: me.enableAnimations,
87153             singleExpand: me.singleExpand,
87154             node: me.store.getRootNode(),
87155             hideHeaders: me.hideHeaders
87156         });
87157         
87158         me.mon(me.store, {
87159             scope: me,
87160             rootchange: me.onRootChange,
87161             clear: me.onClear
87162         });
87163     
87164         me.relayEvents(me.store, [
87165             
87166             'beforeload',
87167
87168             
87169             'load'   
87170         ]);
87171         
87172         me.store.on({
87173             
87174             append: me.createRelayer('itemappend'),
87175             
87176             
87177             remove: me.createRelayer('itemremove'),
87178             
87179             
87180             move: me.createRelayer('itemmove'),
87181             
87182             
87183             insert: me.createRelayer('iteminsert'),
87184             
87185             
87186             beforeappend: me.createRelayer('beforeitemappend'),
87187             
87188             
87189             beforeremove: me.createRelayer('beforeitemremove'),
87190             
87191             
87192             beforemove: me.createRelayer('beforeitemmove'),
87193             
87194             
87195             beforeinsert: me.createRelayer('beforeiteminsert'),
87196              
87197             
87198             expand: me.createRelayer('itemexpand'),
87199              
87200             
87201             collapse: me.createRelayer('itemcollapse'),
87202              
87203             
87204             beforeexpand: me.createRelayer('beforeitemexpand'),
87205              
87206             
87207             beforecollapse: me.createRelayer('beforeitemcollapse')
87208         });
87209         
87210         
87211         if (!me.columns) {
87212             if (me.initialConfig.hideHeaders === undefined) {
87213                 me.hideHeaders = true;
87214             }
87215             me.columns = [{
87216                 xtype    : 'treecolumn',
87217                 text     : 'Name',
87218                 flex     : 1,
87219                 dataIndex: me.displayField         
87220             }];
87221         }
87222         
87223         if (me.cls) {
87224             cls.push(me.cls);
87225         }
87226         me.cls = cls.join(' ');
87227         me.callParent();
87228         
87229         me.relayEvents(me.getView(), [
87230             
87231             'checkchange'
87232         ]);
87233             
87234         
87235         if (!me.getView().rootVisible && !me.getRootNode()) {
87236             me.setRootNode({
87237                 expanded: true
87238             });
87239         }
87240     },
87241     
87242     onClear: function(){
87243         this.view.onClear();
87244     },
87245     
87246     setRootNode: function() {
87247         return this.store.setRootNode.apply(this.store, arguments);
87248     },
87249     
87250     getRootNode: function() {
87251         return this.store.getRootNode();
87252     },
87253     
87254     onRootChange: function(root) {
87255         this.view.setRootNode(root);
87256     },
87257
87258     
87259     getChecked: function() {
87260         return this.getView().getChecked();
87261     },
87262     
87263     isItemChecked: function(rec) {
87264         return rec.get('checked');
87265     },
87266         
87267     
87268     expandAll : function(callback, scope) {
87269         var root = this.getRootNode();
87270         if (root) {
87271             root.expand(true, callback, scope);
87272         }
87273     },
87274
87275     
87276     collapseAll : function(callback, scope) {
87277         var root = this.getRootNode();
87278         if (root) {
87279             if (this.getView().rootVisible) {
87280                 root.collapse(true, callback, scope);
87281             }
87282             else {
87283                 root.collapseChildren(true, callback, scope);
87284             }
87285         }
87286     },
87287
87288     
87289     expandPath: function(path, field, separator, callback, scope) {
87290         var me = this,
87291             current = me.getRootNode(),
87292             index = 1,
87293             view = me.getView(),
87294             keys,
87295             expander;
87296         
87297         field = field || me.getRootNode().idProperty;
87298         separator = separator || '/';
87299         
87300         if (Ext.isEmpty(path)) {
87301             Ext.callback(callback, scope || me, [false, null]);
87302             return;
87303         }
87304         
87305         keys = path.split(separator);
87306         if (current.get(field) != keys[1]) {
87307             
87308             Ext.callback(callback, scope || me, [false, current]);
87309             return;
87310         }
87311         
87312         expander = function(){
87313             if (++index === keys.length) {
87314                 Ext.callback(callback, scope || me, [true, current]);
87315                 return;
87316             }
87317             var node = current.findChild(field, keys[index]);
87318             if (!node) {
87319                 Ext.callback(callback, scope || me, [false, current]);
87320                 return;
87321             }
87322             current = node;
87323             current.expand(false, expander);
87324         };
87325         current.expand(false, expander);
87326     },
87327     
87328     
87329     selectPath: function(path, field, separator, callback, scope) {
87330         var me = this,
87331             keys,
87332             last;
87333         
87334         field = field || me.getRootNode().idProperty;
87335         separator = separator || '/';
87336         
87337         keys = path.split(separator);
87338         last = keys.pop();
87339         
87340         me.expandPath(keys.join('/'), field, separator, function(success, node){
87341             var doSuccess = false;
87342             if (success && node) {
87343                 node = node.findChild(field, last);
87344                 if (node) {
87345                     me.getSelectionModel().select(node);
87346                     Ext.callback(callback, scope || me, [true, node]);
87347                     doSuccess = true;
87348                 }
87349             } else if (node === me.getRootNode()) {
87350                 doSuccess = true;
87351             }
87352             Ext.callback(callback, scope || me, [doSuccess, node]);
87353         }, me);
87354     }
87355 });
87356
87357 Ext.define('Ext.view.DragZone', {
87358     extend: 'Ext.dd.DragZone',
87359     containerScroll: false,
87360
87361     constructor: function(config) {
87362         var me = this;
87363
87364         Ext.apply(me, config);
87365
87366         
87367         
87368         
87369         
87370         
87371         if (!me.ddGroup) {
87372             me.ddGroup = 'view-dd-zone-' + me.view.id;
87373         }
87374
87375         
87376         
87377         
87378         
87379         
87380         
87381         
87382         me.callParent([me.view.el.dom.parentNode]);
87383
87384         me.ddel = Ext.get(document.createElement('div'));
87385         me.ddel.addCls(Ext.baseCSSPrefix + 'grid-dd-wrap');
87386     },
87387
87388     init: function(id, sGroup, config) {
87389         this.initTarget(id, sGroup, config);
87390         this.view.mon(this.view, {
87391             itemmousedown: this.onItemMouseDown,
87392             scope: this
87393         });
87394     },
87395
87396     onItemMouseDown: function(view, record, item, index, e) {
87397         if (!this.isPreventDrag(e, record, item, index)) {
87398             this.handleMouseDown(e);
87399         }
87400     },
87401
87402     
87403     isPreventDrag: function(e) {
87404         return false;
87405     },
87406
87407     getDragData: function(e) {
87408         var view = this.view,
87409             item = e.getTarget(view.getItemSelector()),
87410             record, selectionModel, records;
87411
87412         if (item) {
87413             record = view.getRecord(item);
87414             selectionModel = view.getSelectionModel();
87415             records = selectionModel.getSelection();
87416             return {
87417                 copy: this.view.copy || (this.view.allowCopy && e.ctrlKey),
87418                 event: new Ext.EventObjectImpl(e),
87419                 view: view,
87420                 ddel: this.ddel,
87421                 item: item,
87422                 records: records,
87423                 fromPosition: Ext.fly(item).getXY()
87424             };
87425         }
87426     },
87427
87428     onInitDrag: function(x, y) {
87429         var me = this,
87430             data = me.dragData,
87431             view = data.view,
87432             selectionModel = view.getSelectionModel(),
87433             record = view.getRecord(data.item),
87434             e = data.event;
87435
87436         
87437         
87438         if (!selectionModel.isSelected(record) || e.hasModifier()) {
87439             selectionModel.selectWithEvent(record, e);
87440         }
87441         data.records = selectionModel.getSelection();
87442
87443         me.ddel.update(me.getDragText());
87444         me.proxy.update(me.ddel.dom);
87445         me.onStartDrag(x, y);
87446         return true;
87447     },
87448
87449     getDragText: function() {
87450         var count = this.dragData.records.length;
87451         return Ext.String.format(this.dragText, count, count == 1 ? '' : 's');
87452     },
87453
87454     getRepairXY : function(e, data){
87455         return data ? data.fromPosition : false;
87456     }
87457 });
87458 Ext.define('Ext.tree.ViewDragZone', {
87459     extend: 'Ext.view.DragZone',
87460
87461     isPreventDrag: function(e, record) {
87462         return (record.get('allowDrag') === false) || !!e.getTarget(this.view.expanderSelector);
87463     },
87464     
87465     afterRepair: function() {
87466         var me = this,
87467             view = me.view,
87468             selectedRowCls = view.selectedItemCls,
87469             records = me.dragData.records,
87470             fly = Ext.fly;
87471         
87472         if (Ext.enableFx && me.repairHighlight) {
87473             
87474             Ext.Array.forEach(records, function(record) {
87475                 
87476                 
87477                 var item = view.getNode(record);
87478                 
87479                 
87480                 
87481                 fly(item.firstChild).highlight(me.repairHighlightColor, {
87482                     listeners: {
87483                         beforeanimate: function() {
87484                             if (view.isSelected(item)) {
87485                                 fly(item).removeCls(selectedRowCls);
87486                             }
87487                         },
87488                         afteranimate: function() {
87489                             if (view.isSelected(item)) {
87490                                 fly(item).addCls(selectedRowCls);
87491                             }
87492                         }
87493                     }
87494                 });
87495             });
87496         }
87497         me.dragging = false;
87498     }
87499 });
87500
87501 Ext.define('Ext.tree.ViewDropZone', {
87502     extend: 'Ext.view.DropZone',
87503
87504     
87505     allowParentInserts: false,
87506  
87507     
87508     allowContainerDrops: false,
87509
87510     
87511     appendOnly: false,
87512
87513     
87514     expandDelay : 500,
87515
87516     indicatorCls: 'x-tree-ddindicator',
87517
87518     
87519     expandNode : function(node) {
87520         var view = this.view;
87521         if (!node.isLeaf() && !node.isExpanded()) {
87522             view.expand(node);
87523             this.expandProcId = false;
87524         }
87525     },
87526
87527     
87528     queueExpand : function(node) {
87529         this.expandProcId = Ext.Function.defer(this.expandNode, this.expandDelay, this, [node]);
87530     },
87531
87532     
87533     cancelExpand : function() {
87534         if (this.expandProcId) {
87535             clearTimeout(this.expandProcId);
87536             this.expandProcId = false;
87537         }
87538     },
87539
87540     getPosition: function(e, node) {
87541         var view = this.view,
87542             record = view.getRecord(node),
87543             y = e.getPageY(),
87544             noAppend = record.isLeaf(),
87545             noBelow = false,
87546             region = Ext.fly(node).getRegion(),
87547             fragment;
87548
87549         
87550         if (record.isRoot()) {
87551             return 'append';
87552         }
87553
87554         
87555         if (this.appendOnly) {
87556             return noAppend ? false : 'append';
87557         }
87558
87559         if (!this.allowParentInsert) {
87560             noBelow = record.hasChildNodes() && record.isExpanded();
87561         }
87562
87563         fragment = (region.bottom - region.top) / (noAppend ? 2 : 3);
87564         if (y >= region.top && y < (region.top + fragment)) {
87565             return 'before';
87566         }
87567         else if (!noBelow && (noAppend || (y >= (region.bottom - fragment) && y <= region.bottom))) {
87568             return 'after';
87569         }
87570         else {
87571             return 'append';
87572         }
87573     },
87574
87575     isValidDropPoint : function(node, position, dragZone, e, data) {
87576         if (!node || !data.item) {
87577             return false;
87578         }
87579
87580         var view = this.view,
87581             targetNode = view.getRecord(node),
87582             draggedRecords = data.records,
87583             dataLength = draggedRecords.length,
87584             ln = draggedRecords.length,
87585             i, record;
87586
87587         
87588         if (!(targetNode && position && dataLength)) {
87589             return false;
87590         }
87591
87592         
87593         for (i = 0; i < ln; i++) {
87594             record = draggedRecords[i];
87595             if (record.isNode && record.contains(targetNode)) {
87596                 return false;
87597             }
87598         }
87599         
87600         
87601         if (position === 'append' && targetNode.get('allowDrop') == false) {
87602             return false;
87603         }
87604         else if (position != 'append' && targetNode.parentNode.get('allowDrop') == false) {
87605             return false;
87606         }
87607
87608         
87609         if (Ext.Array.contains(draggedRecords, targetNode)) {
87610              return false;
87611         }
87612
87613         
87614         
87615         return true;
87616     },
87617
87618     onNodeOver : function(node, dragZone, e, data) {
87619         var position = this.getPosition(e, node),
87620             returnCls = this.dropNotAllowed,
87621             view = this.view,
87622             targetNode = view.getRecord(node),
87623             indicator = this.getIndicator(),
87624             indicatorX = 0,
87625             indicatorY = 0;
87626
87627         
87628         this.cancelExpand();
87629         if (position == 'append' && !this.expandProcId && !Ext.Array.contains(data.records, targetNode) && !targetNode.isLeaf() && !targetNode.isExpanded()) {
87630             this.queueExpand(targetNode);
87631         }
87632             
87633         if (this.isValidDropPoint(node, position, dragZone, e, data)) {
87634             this.valid = true;
87635             this.currentPosition = position;
87636             this.overRecord = targetNode;
87637
87638             indicator.setWidth(Ext.fly(node).getWidth());
87639             indicatorY = Ext.fly(node).getY() - Ext.fly(view.el).getY() - 1;
87640
87641             if (position == 'before') {
87642                 returnCls = targetNode.isFirst() ? Ext.baseCSSPrefix + 'tree-drop-ok-above' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
87643                 indicator.showAt(0, indicatorY);
87644                 indicator.toFront();
87645             }
87646             else if (position == 'after') {
87647                 returnCls = targetNode.isLast() ? Ext.baseCSSPrefix + 'tree-drop-ok-below' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
87648                 indicatorY += Ext.fly(node).getHeight();
87649                 indicator.showAt(0, indicatorY);
87650                 indicator.toFront();
87651             }
87652             else {
87653                 returnCls = Ext.baseCSSPrefix + 'tree-drop-ok-append';
87654                 
87655                 indicator.hide();
87656             }
87657         }
87658         else {
87659             this.valid = false;
87660         }
87661
87662         this.currentCls = returnCls;
87663         return returnCls;
87664     },
87665
87666     onContainerOver : function(dd, e, data) {
87667         return e.getTarget('.' + this.indicatorCls) ? this.currentCls : this.dropNotAllowed;
87668     },
87669     
87670     notifyOut: function() {
87671         this.callParent(arguments);
87672         this.cancelExpand();
87673     },
87674
87675     handleNodeDrop : function(data, targetNode, position) {
87676         var me = this,
87677             view = me.view,
87678             parentNode = targetNode.parentNode,
87679             store = view.getStore(),
87680             recordDomNodes = [],
87681             records, i, len,
87682             insertionMethod, argList,
87683             needTargetExpand,
87684             transferData,
87685             processDrop;
87686
87687         
87688         if (data.copy) {
87689             records = data.records;
87690             data.records = [];
87691             for (i = 0, len = records.length; i < len; i++) {
87692                 data.records.push(Ext.apply({}, records[i].data));
87693             }
87694         }
87695
87696         
87697         me.cancelExpand();
87698
87699         
87700         
87701         
87702         
87703         if (position == 'before') {
87704             insertionMethod = parentNode.insertBefore;
87705             argList = [null, targetNode];
87706             targetNode = parentNode;
87707         }
87708         else if (position == 'after') {
87709             if (targetNode.nextSibling) {
87710                 insertionMethod = parentNode.insertBefore;
87711                 argList = [null, targetNode.nextSibling];
87712             }
87713             else {
87714                 insertionMethod = parentNode.appendChild;
87715                 argList = [null];
87716             }
87717             targetNode = parentNode;
87718         }
87719         else {
87720             if (!targetNode.isExpanded()) {
87721                 needTargetExpand = true;
87722             }
87723             insertionMethod = targetNode.appendChild;
87724             argList = [null];
87725         }
87726
87727         
87728         transferData = function() {
87729             var node;
87730             for (i = 0, len = data.records.length; i < len; i++) {
87731                 argList[0] = data.records[i];
87732                 node = insertionMethod.apply(targetNode, argList);
87733                 
87734                 if (Ext.enableFx && me.dropHighlight) {
87735                     recordDomNodes.push(view.getNode(node));
87736                 }
87737             }
87738             
87739             
87740             
87741             if (Ext.enableFx && me.dropHighlight) {
87742                 
87743                 
87744                 Ext.Array.forEach(recordDomNodes, function(n) {
87745                     Ext.fly(n.firstChild ? n.firstChild : n).highlight(me.dropHighlightColor);
87746                 });
87747             }
87748         };
87749
87750         
87751         if (needTargetExpand) {
87752             targetNode.expand(false, transferData);
87753         }
87754         
87755         else {
87756             transferData();
87757         }
87758     }
87759 });
87760
87761 Ext.define('Ext.tree.plugin.TreeViewDragDrop', {
87762     extend: 'Ext.AbstractPlugin',
87763     alias: 'plugin.treeviewdragdrop',
87764
87765     uses: [
87766         'Ext.tree.ViewDragZone',
87767         'Ext.tree.ViewDropZone'
87768     ],
87769
87770     
87771
87772     
87773
87774     dragText : '{0} selected node{1}',
87775
87776     
87777     allowParentInserts: false,
87778
87779     
87780     allowContainerDrops: false,
87781
87782     
87783     appendOnly: false,
87784
87785     
87786     ddGroup : "TreeDD",
87787
87788     
87789
87790     
87791
87792     
87793     expandDelay : 1000,
87794
87795     
87796     enableDrop: true,
87797
87798     
87799     enableDrag: true,
87800     
87801     
87802     nodeHighlightColor: 'c3daf9',
87803     
87804     
87805     nodeHighlightOnDrop: Ext.enableFx,
87806     
87807     
87808     nodeHighlightOnRepair: Ext.enableFx,
87809
87810     init : function(view) {
87811         view.on('render', this.onViewRender, this, {single: true});
87812     },
87813
87814     
87815     destroy: function() {
87816         Ext.destroy(this.dragZone, this.dropZone);
87817     },
87818
87819     onViewRender : function(view) {
87820         var me = this;
87821
87822         if (me.enableDrag) {
87823             me.dragZone = Ext.create('Ext.tree.ViewDragZone', {
87824                 view: view,
87825                 ddGroup: me.dragGroup || me.ddGroup,
87826                 dragText: me.dragText,
87827                 repairHighlightColor: me.nodeHighlightColor,
87828                 repairHighlight: me.nodeHighlightOnRepair
87829             });
87830         }
87831
87832         if (me.enableDrop) {
87833             me.dropZone = Ext.create('Ext.tree.ViewDropZone', {
87834                 view: view,
87835                 ddGroup: me.dropGroup || me.ddGroup,
87836                 allowContainerDrops: me.allowContainerDrops,
87837                 appendOnly: me.appendOnly,
87838                 allowParentInserts: me.allowParentInserts,
87839                 expandDelay: me.expandDelay,
87840                 dropHighlightColor: me.nodeHighlightColor,
87841                 dropHighlight: me.nodeHighlightOnDrop
87842             });
87843         }
87844     }
87845 });
87846
87847 Ext.define('Ext.util.Cookies', {
87848     singleton: true,
87849     
87850     
87851     set : function(name, value){
87852         var argv = arguments,
87853             argc = arguments.length,
87854             expires = (argc > 2) ? argv[2] : null,
87855             path = (argc > 3) ? argv[3] : '/',
87856             domain = (argc > 4) ? argv[4] : null,
87857             secure = (argc > 5) ? argv[5] : false;
87858             
87859         document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
87860     },
87861
87862     
87863     get : function(name){
87864         var arg = name + "=",
87865             alen = arg.length,
87866             clen = document.cookie.length,
87867             i = 0,
87868             j = 0;
87869             
87870         while(i < clen){
87871             j = i + alen;
87872             if(document.cookie.substring(i, j) == arg){
87873                 return this.getCookieVal(j);
87874             }
87875             i = document.cookie.indexOf(" ", i) + 1;
87876             if(i === 0){
87877                 break;
87878             }
87879         }
87880         return null;
87881     },
87882
87883     
87884     clear : function(name, path){
87885         if(this.get(name)){
87886             path = path || '/';
87887             document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT; path=' + path;
87888         }
87889     },
87890     
87891     
87892     getCookieVal : function(offset){
87893         var endstr = document.cookie.indexOf(";", offset);
87894         if(endstr == -1){
87895             endstr = document.cookie.length;
87896         }
87897         return unescape(document.cookie.substring(offset, endstr));
87898     }
87899 });
87900
87901
87902 Ext.define('Ext.util.CSS', function() {
87903     var rules = null;
87904     var doc = document;
87905
87906     var camelRe = /(-[a-z])/gi;
87907     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
87908
87909     return {
87910
87911         singleton: true,
87912
87913         constructor: function() {
87914             this.rules = {};
87915             this.initialized = false;
87916         },
87917  
87918         
87919         createStyleSheet : function(cssText, id) {
87920             var ss,
87921                 head = doc.getElementsByTagName("head")[0],
87922                 styleEl = doc.createElement("style");
87923
87924             styleEl.setAttribute("type", "text/css");
87925             if (id) {
87926                styleEl.setAttribute("id", id);
87927             }
87928
87929             if (Ext.isIE) {
87930                head.appendChild(styleEl);
87931                ss = styleEl.styleSheet;
87932                ss.cssText = cssText;
87933             } else {
87934                 try{
87935                     styleEl.appendChild(doc.createTextNode(cssText));
87936                 } catch(e) {
87937                    styleEl.cssText = cssText;
87938                 }
87939                 head.appendChild(styleEl);
87940                 ss = styleEl.styleSheet ? styleEl.styleSheet : (styleEl.sheet || doc.styleSheets[doc.styleSheets.length-1]);
87941             }
87942             this.cacheStyleSheet(ss);
87943             return ss;
87944         },
87945
87946         
87947         removeStyleSheet : function(id) {
87948             var existing = document.getElementById(id);
87949             if (existing) {
87950                 existing.parentNode.removeChild(existing);
87951             }
87952         },
87953
87954         
87955         swapStyleSheet : function(id, url) {
87956             var doc = document;
87957             this.removeStyleSheet(id);
87958             var ss = doc.createElement("link");
87959             ss.setAttribute("rel", "stylesheet");
87960             ss.setAttribute("type", "text/css");
87961             ss.setAttribute("id", id);
87962             ss.setAttribute("href", url);
87963             doc.getElementsByTagName("head")[0].appendChild(ss);
87964         },
87965
87966         
87967         refreshCache : function() {
87968             return this.getRules(true);
87969         },
87970
87971         
87972         cacheStyleSheet : function(ss) {
87973             if(!rules){
87974                 rules = {};
87975             }
87976             try {
87977                 var ssRules = ss.cssRules || ss.rules,
87978                     selectorText,
87979                     i = ssRules.length - 1,
87980                     j,
87981                     selectors;
87982
87983                 for (; i >= 0; --i) {
87984                     selectorText = ssRules[i].selectorText;
87985                     if (selectorText) {
87986  
87987                         
87988                         selectorText = selectorText.split(',');
87989                         selectors = selectorText.length;
87990                         for (j = 0; j < selectors; j++) {
87991                             rules[Ext.String.trim(selectorText[j]).toLowerCase()] = ssRules[i];
87992                         }
87993                     }
87994                 }
87995             } catch(e) {}
87996         },
87997
87998         
87999         getRules : function(refreshCache) {
88000             if (rules === null || refreshCache) {
88001                 rules = {};
88002                 var ds = doc.styleSheets,
88003                     i = 0,
88004                     len = ds.length;
88005
88006                 for (; i < len; i++) {
88007                     try {
88008                         if (!ds[i].disabled) {
88009                             this.cacheStyleSheet(ds[i]);
88010                         }
88011                     } catch(e) {} 
88012                 }
88013             }
88014             return rules;
88015         },
88016
88017         
88018         getRule: function(selector, refreshCache) {
88019             var rs = this.getRules(refreshCache);
88020             if (!Ext.isArray(selector)) {
88021                 return rs[selector.toLowerCase()];
88022             }
88023             for (var i = 0; i < selector.length; i++) {
88024                 if (rs[selector[i]]) {
88025                     return rs[selector[i].toLowerCase()];
88026                 }
88027             }
88028             return null;
88029         },
88030
88031         
88032         updateRule : function(selector, property, value){
88033             if (!Ext.isArray(selector)) {
88034                 var rule = this.getRule(selector);
88035                 if (rule) {
88036                     rule.style[property.replace(camelRe, camelFn)] = value;
88037                     return true;
88038                 }
88039             } else {
88040                 for (var i = 0; i < selector.length; i++) {
88041                     if (this.updateRule(selector[i], property, value)) {
88042                         return true;
88043                     }
88044                 }
88045             }
88046             return false;
88047         }
88048     };
88049 }());
88050
88051 Ext.define('Ext.util.History', {
88052     singleton: true,
88053     alternateClassName: 'Ext.History',
88054     mixins: {
88055         observable: 'Ext.util.Observable'
88056     },
88057     
88058     constructor: function() {
88059         var me = this;
88060         me.oldIEMode = Ext.isIE6 || Ext.isIE7 || !Ext.isStrict && Ext.isIE8;
88061         me.iframe = null;
88062         me.hiddenField = null;
88063         me.ready = false;
88064         me.currentToken = null;
88065     },
88066     
88067     getHash: function() {
88068         var href = window.location.href,
88069             i = href.indexOf("#");
88070             
88071         return i >= 0 ? href.substr(i + 1) : null;
88072     },
88073
88074     doSave: function() {
88075         this.hiddenField.value = this.currentToken;
88076     },
88077     
88078
88079     handleStateChange: function(token) {
88080         this.currentToken = token;
88081         this.fireEvent('change', token);
88082     },
88083
88084     updateIFrame: function(token) {
88085         var html = '<html><body><div id="state">' + 
88086                     Ext.util.Format.htmlEncode(token) + 
88087                     '</div></body></html>';
88088
88089         try {
88090             var doc = this.iframe.contentWindow.document;
88091             doc.open();
88092             doc.write(html);
88093             doc.close();
88094             return true;
88095         } catch (e) {
88096             return false;
88097         }
88098     },
88099
88100     checkIFrame: function () {
88101         var me = this,
88102             contentWindow = me.iframe.contentWindow;
88103             
88104         if (!contentWindow || !contentWindow.document) {
88105             Ext.Function.defer(this.checkIFrame, 10, this);
88106             return;
88107         }
88108        
88109         var doc = contentWindow.document,
88110             elem = doc.getElementById("state"),
88111             oldToken = elem ? elem.innerText : null,
88112             oldHash = me.getHash();
88113            
88114         Ext.TaskManager.start({
88115             run: function () {
88116                 var doc = contentWindow.document,
88117                     elem = doc.getElementById("state"),
88118                     newToken = elem ? elem.innerText : null,
88119                     newHash = me.getHash();
88120
88121                 if (newToken !== oldToken) {
88122                     oldToken = newToken;
88123                     me.handleStateChange(newToken);
88124                     window.top.location.hash = newToken;
88125                     oldHash = newToken;
88126                     me.doSave();
88127                 } else if (newHash !== oldHash) {
88128                     oldHash = newHash;
88129                     me.updateIFrame(newHash);
88130                 }
88131             }, 
88132             interval: 50,
88133             scope: me
88134         });
88135         me.ready = true;
88136         me.fireEvent('ready', me);            
88137     },
88138
88139     startUp: function () {
88140         var me = this;
88141         
88142         me.currentToken = me.hiddenField.value || this.getHash();
88143
88144         if (me.oldIEMode) {
88145             me.checkIFrame();
88146         } else {
88147             var hash = me.getHash();
88148             Ext.TaskManager.start({
88149                 run: function () {
88150                     var newHash = me.getHash();
88151                     if (newHash !== hash) {
88152                         hash = newHash;
88153                         me.handleStateChange(hash);
88154                         me.doSave();
88155                     }
88156                 },
88157                 interval: 50,
88158                 scope: me
88159             });
88160             me.ready = true;
88161             me.fireEvent('ready', me);
88162         }
88163         
88164     },
88165
88166     
88167     fieldId: Ext.baseCSSPrefix + 'history-field',
88168     
88169     iframeId: Ext.baseCSSPrefix + 'history-frame',
88170
88171     
88172     init: function (onReady, scope) {
88173         var me = this;
88174         
88175         if (me.ready) {
88176             Ext.callback(onReady, scope, [me]);
88177             return;
88178         }
88179         
88180         if (!Ext.isReady) {
88181             Ext.onReady(function() {
88182                 me.init(onReady, scope);
88183             });
88184             return;
88185         }
88186         
88187         me.hiddenField = Ext.getDom(me.fieldId);
88188         
88189         if (me.oldIEMode) {
88190             me.iframe = Ext.getDom(me.iframeId);
88191         }
88192         
88193         me.addEvents(
88194             
88195             'ready',
88196             
88197             'change'
88198         );
88199         
88200         if (onReady) {
88201             me.on('ready', onReady, scope, {single: true});
88202         }
88203         me.startUp();
88204     },
88205
88206     
88207     add: function (token, preventDup) {
88208         var me = this;
88209         
88210         if (preventDup !== false) {
88211             if (me.getToken() === token) {
88212                 return true;
88213             }
88214         }
88215         
88216         if (me.oldIEMode) {
88217             return me.updateIFrame(token);
88218         } else {
88219             window.top.location.hash = token;
88220             return true;
88221         }
88222     },
88223
88224     
88225     back: function() {
88226         window.history.go(-1);
88227     },
88228
88229     
88230     forward: function(){
88231         window.history.go(1);
88232     },
88233
88234     
88235     getToken: function() {
88236         return this.ready ? this.currentToken : this.getHash();
88237     }
88238 });
88239
88240 Ext.define('Ext.view.TableChunker', {
88241     singleton: true,
88242     requires: ['Ext.XTemplate'],
88243     metaTableTpl: [
88244         '{[this.openTableWrap()]}',
88245         '<table class="' + Ext.baseCSSPrefix + 'grid-table ' + Ext.baseCSSPrefix + 'grid-table-resizer" border="0" cellspacing="0" cellpadding="0" {[this.embedFullWidth()]}>',
88246             '<tbody>',
88247             '<tr>',
88248             '<tpl for="columns">',
88249                 '<th class="' + Ext.baseCSSPrefix + 'grid-col-resizer-{id}" style="width: {width}px; height: 0px;"></th>',
88250             '</tpl>',
88251             '</tr>',
88252             '{[this.openRows()]}',
88253                 '{row}',
88254                 '<tpl for="features">',
88255                     '{[this.embedFeature(values, parent, xindex, xcount)]}',
88256                 '</tpl>',
88257             '{[this.closeRows()]}',
88258             '</tbody>',
88259         '</table>',
88260         '{[this.closeTableWrap()]}'
88261     ],
88262
88263     constructor: function() {
88264         Ext.XTemplate.prototype.recurse = function(values, reference) {
88265             return this.apply(reference ? values[reference] : values);
88266         };
88267     },
88268
88269     embedFeature: function(values, parent, x, xcount) {
88270         var tpl = '';
88271         if (!values.disabled) {
88272             tpl = values.getFeatureTpl(values, parent, x, xcount);
88273         }
88274         return tpl;
88275     },
88276
88277     embedFullWidth: function() {
88278         return 'style="width: {fullWidth}px;"';
88279     },
88280
88281     openRows: function() {
88282         return '<tpl for="rows">';
88283     },
88284
88285     closeRows: function() {
88286         return '</tpl>';
88287     },
88288
88289     metaRowTpl: [
88290         '<tr class="' + Ext.baseCSSPrefix + 'grid-row {addlSelector} {[this.embedRowCls()]}" {[this.embedRowAttr()]}>',
88291             '<tpl for="columns">',
88292                 '<td class="{cls} ' + Ext.baseCSSPrefix + 'grid-cell ' + Ext.baseCSSPrefix + 'grid-cell-{columnId} {{id}-modified} {{id}-tdCls} {[this.firstOrLastCls(xindex, xcount)]}" {{id}-tdAttr}><div unselectable="on" class="' + Ext.baseCSSPrefix + 'grid-cell-inner ' + Ext.baseCSSPrefix + 'unselectable" style="{{id}-style}; text-align: {align};">{{id}}</div></td>',
88293             '</tpl>',
88294         '</tr>'
88295     ],
88296     
88297     firstOrLastCls: function(xindex, xcount) {
88298         var cssCls = '';
88299         if (xindex === 1) {
88300             cssCls = Ext.baseCSSPrefix + 'grid-cell-first';
88301         } else if (xindex === xcount) {
88302             cssCls = Ext.baseCSSPrefix + 'grid-cell-last';
88303         }
88304         return cssCls;
88305     },
88306     
88307     embedRowCls: function() {
88308         return '{rowCls}';
88309     },
88310     
88311     embedRowAttr: function() {
88312         return '{rowAttr}';
88313     },
88314     
88315     openTableWrap: function() {
88316         return '';
88317     },
88318     
88319     closeTableWrap: function() {
88320         return '';
88321     },
88322
88323     getTableTpl: function(cfg, textOnly) {
88324         var tpl,
88325             tableTplMemberFns = {
88326                 openRows: this.openRows,
88327                 closeRows: this.closeRows,
88328                 embedFeature: this.embedFeature,
88329                 embedFullWidth: this.embedFullWidth,
88330                 openTableWrap: this.openTableWrap,
88331                 closeTableWrap: this.closeTableWrap
88332             },
88333             tplMemberFns = {},
88334             features = cfg.features || [],
88335             ln = features.length,
88336             i  = 0,
88337             memberFns = {
88338                 embedRowCls: this.embedRowCls,
88339                 embedRowAttr: this.embedRowAttr,
88340                 firstOrLastCls: this.firstOrLastCls
88341             },
88342             
88343             metaRowTpl = Array.prototype.slice.call(this.metaRowTpl, 0),
88344             metaTableTpl;
88345             
88346         for (; i < ln; i++) {
88347             if (!features[i].disabled) {
88348                 features[i].mutateMetaRowTpl(metaRowTpl);
88349                 Ext.apply(memberFns, features[i].getMetaRowTplFragments());
88350                 Ext.apply(tplMemberFns, features[i].getFragmentTpl());
88351                 Ext.apply(tableTplMemberFns, features[i].getTableFragments());
88352             }
88353         }
88354         
88355         metaRowTpl = Ext.create('Ext.XTemplate', metaRowTpl.join(''), memberFns);
88356         cfg.row = metaRowTpl.applyTemplate(cfg);
88357         
88358         metaTableTpl = Ext.create('Ext.XTemplate', this.metaTableTpl.join(''), tableTplMemberFns);
88359         
88360         tpl = metaTableTpl.applyTemplate(cfg);
88361         
88362         
88363         if (!textOnly) {
88364             tpl = Ext.create('Ext.XTemplate', tpl, tplMemberFns);
88365         }
88366         return tpl;
88367         
88368     }
88369 });
88370
88371
88372
88373