Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / ext-all-debug.js
1 /*
2 Ext JS - JavaScript Library
3 Copyright (c) 2006-2011, Sencha Inc.
4 All rights reserved.
5 licensing@sencha.com
6 */
7
8
9 (function() {
10     var global = this,
11         objectPrototype = Object.prototype,
12         toString = Object.prototype.toString,
13         enumerables = true,
14         enumerablesTest = { toString: 1 },
15         i;
16
17     if (typeof Ext === 'undefined') {
18         global.Ext = {};
19     }
20
21     Ext.global = global;
22
23     for (i in enumerablesTest) {
24         enumerables = null;
25     }
26
27     if (enumerables) {
28         enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable',
29                        'toLocaleString', 'toString', 'constructor'];
30     }
31
32     
33     Ext.enumerables = enumerables;
34
35     
36     Ext.apply = function(object, config, defaults) {
37         if (defaults) {
38             Ext.apply(object, defaults);
39         }
40
41         if (object && config && typeof config === 'object') {
42             var i, j, k;
43
44             for (i in config) {
45                 object[i] = config[i];
46             }
47
48             if (enumerables) {
49                 for (j = enumerables.length; j--;) {
50                     k = enumerables[j];
51                     if (config.hasOwnProperty(k)) {
52                         object[k] = config[k];
53                     }
54                 }
55             }
56         }
57
58         return object;
59     };
60
61     Ext.buildSettings = Ext.apply({
62         baseCSSPrefix: 'x-',
63         scopeResetCSS: false
64     }, Ext.buildSettings || {});
65
66     Ext.apply(Ext, {
67         
68         emptyFn: function() {},
69
70         baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,
71
72         
73         applyIf: function(object, config) {
74             var property;
75
76             if (object) {
77                 for (property in config) {
78                     if (object[property] === undefined) {
79                         object[property] = config[property];
80                     }
81                 }
82             }
83
84             return object;
85         },
86
87         
88         iterate: function(object, fn, scope) {
89             if (Ext.isEmpty(object)) {
90                 return;
91             }
92
93             if (scope === undefined) {
94                 scope = object;
95             }
96
97             if (Ext.isIterable(object)) {
98                 Ext.Array.each.call(Ext.Array, object, fn, scope);
99             }
100             else {
101                 Ext.Object.each.call(Ext.Object, object, fn, scope);
102             }
103         }
104     });
105
106     Ext.apply(Ext, {
107
108         
109         extend: function() {
110             
111             var objectConstructor = objectPrototype.constructor,
112                 inlineOverrides = function(o) {
113                 for (var m in o) {
114                     if (!o.hasOwnProperty(m)) {
115                         continue;
116                     }
117                     this[m] = o[m];
118                 }
119             };
120
121             return function(subclass, superclass, overrides) {
122                 
123                 if (Ext.isObject(superclass)) {
124                     overrides = superclass;
125                     superclass = subclass;
126                     subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
127                         superclass.apply(this, arguments);
128                     };
129                 }
130
131                 if (!superclass) {
132                     Ext.Error.raise({
133                         sourceClass: 'Ext',
134                         sourceMethod: 'extend',
135                         msg: 'Attempting to extend from a class which has not been loaded on the page.'
136                     });
137                 }
138
139                 
140                 var F = function() {},
141                     subclassProto, superclassProto = superclass.prototype;
142
143                 F.prototype = superclassProto;
144                 subclassProto = subclass.prototype = new F();
145                 subclassProto.constructor = subclass;
146                 subclass.superclass = superclassProto;
147
148                 if (superclassProto.constructor === objectConstructor) {
149                     superclassProto.constructor = superclass;
150                 }
151
152                 subclass.override = function(overrides) {
153                     Ext.override(subclass, overrides);
154                 };
155
156                 subclassProto.override = inlineOverrides;
157                 subclassProto.proto = subclassProto;
158
159                 subclass.override(overrides);
160                 subclass.extend = function(o) {
161                     return Ext.extend(subclass, o);
162                 };
163
164                 return subclass;
165             };
166         }(),
167
168         
169         override: function(cls, overrides) {
170             if (cls.prototype.$className) {
171                 return cls.override(overrides);
172             }
173             else {
174                 Ext.apply(cls.prototype, overrides);
175             }
176         }
177     });
178
179     
180     Ext.apply(Ext, {
181
182         
183         valueFrom: function(value, defaultValue, allowBlank){
184             return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
185         },
186
187         
188         typeOf: function(value) {
189             if (value === null) {
190                 return 'null';
191             }
192
193             var type = typeof value;
194
195             if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') {
196                 return type;
197             }
198
199             var typeToString = toString.call(value);
200
201             switch(typeToString) {
202                 case '[object Array]':
203                     return 'array';
204                 case '[object Date]':
205                     return 'date';
206                 case '[object Boolean]':
207                     return 'boolean';
208                 case '[object Number]':
209                     return 'number';
210                 case '[object RegExp]':
211                     return 'regexp';
212             }
213
214             if (type === 'function') {
215                 return 'function';
216             }
217
218             if (type === 'object') {
219                 if (value.nodeType !== undefined) {
220                     if (value.nodeType === 3) {
221                         return (/\S/).test(value.nodeValue) ? 'textnode' : 'whitespace';
222                     }
223                     else {
224                         return 'element';
225                     }
226                 }
227
228                 return 'object';
229             }
230
231             Ext.Error.raise({
232                 sourceClass: 'Ext',
233                 sourceMethod: 'typeOf',
234                 msg: 'Failed to determine the type of the specified value "' + value + '". This is most likely a bug.'
235             });
236         },
237
238         
239         isEmpty: function(value, allowEmptyString) {
240             return (value === null) || (value === undefined) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);
241         },
242
243         
244         isArray: ('isArray' in Array) ? Array.isArray : function(value) {
245             return toString.call(value) === '[object Array]';
246         },
247
248         
249         isDate: function(value) {
250             return toString.call(value) === '[object Date]';
251         },
252
253         
254         isObject: (toString.call(null) === '[object Object]') ?
255         function(value) {
256             return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.nodeType === undefined;
257         } :
258         function(value) {
259             return toString.call(value) === '[object Object]';
260         },
261
262         
263         isPrimitive: function(value) {
264             var type = typeof value;
265
266             return type === 'string' || type === 'number' || type === 'boolean';
267         },
268
269         
270         isFunction:
271         
272         
273         (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) {
274             return toString.call(value) === '[object Function]';
275         } : function(value) {
276             return typeof value === 'function';
277         },
278
279         
280         isNumber: function(value) {
281             return typeof value === 'number' && isFinite(value);
282         },
283
284         
285         isNumeric: function(value) {
286             return !isNaN(parseFloat(value)) && isFinite(value);
287         },
288
289         
290         isString: function(value) {
291             return typeof value === 'string';
292         },
293
294         
295         isBoolean: function(value) {
296             return typeof value === 'boolean';
297         },
298
299         
300         isElement: function(value) {
301             return value ? value.nodeType === 1 : false;
302         },
303
304         
305         isTextNode: function(value) {
306             return value ? value.nodeName === "#text" : false;
307         },
308
309         
310         isDefined: function(value) {
311             return typeof value !== 'undefined';
312         },
313
314         
315         isIterable: function(value) {
316             return (value && typeof value !== 'string') ? value.length !== undefined : false;
317         }
318     });
319
320     Ext.apply(Ext, {
321
322         
323         clone: function(item) {
324             if (item === null || item === undefined) {
325                 return item;
326             }
327
328             
329             
330             
331             if (item.nodeType && item.cloneNode) {
332                 return item.cloneNode(true);
333             }
334
335             var type = toString.call(item);
336
337             
338             if (type === '[object Date]') {
339                 return new Date(item.getTime());
340             }
341
342             var i, j, k, clone, key;
343
344             
345             if (type === '[object Array]') {
346                 i = item.length;
347
348                 clone = [];
349
350                 while (i--) {
351                     clone[i] = Ext.clone(item[i]);
352                 }
353             }
354             
355             else if (type === '[object Object]' && item.constructor === Object) {
356                 clone = {};
357
358                 for (key in item) {
359                     clone[key] = Ext.clone(item[key]);
360                 }
361
362                 if (enumerables) {
363                     for (j = enumerables.length; j--;) {
364                         k = enumerables[j];
365                         clone[k] = item[k];
366                     }
367                 }
368             }
369
370             return clone || item;
371         },
372
373         
374         getUniqueGlobalNamespace: function() {
375             var uniqueGlobalNamespace = this.uniqueGlobalNamespace;
376
377             if (uniqueGlobalNamespace === undefined) {
378                 var i = 0;
379
380                 do {
381                     uniqueGlobalNamespace = 'ExtSandbox' + (++i);
382                 } while (Ext.global[uniqueGlobalNamespace] !== undefined);
383
384                 Ext.global[uniqueGlobalNamespace] = Ext;
385                 this.uniqueGlobalNamespace = uniqueGlobalNamespace;
386             }
387
388             return uniqueGlobalNamespace;
389         },
390
391         
392         functionFactory: function() {
393             var args = Array.prototype.slice.call(arguments);
394
395             if (args.length > 0) {
396                 args[args.length - 1] = 'var Ext=window.' + this.getUniqueGlobalNamespace() + ';' +
397                     args[args.length - 1];
398             }
399
400             return Function.prototype.constructor.apply(Function.prototype, args);
401         }
402     });
403
404     
405     Ext.type = Ext.typeOf;
406
407 })();
408
409
410 (function() {
411
412
413 var version = '4.0.1', Version;
414     Ext.Version = Version = Ext.extend(Object, {
415
416         
417         constructor: function(version) {
418             var parts, releaseStartIndex;
419
420             if (version instanceof Version) {
421                 return version;
422             }
423
424             this.version = this.shortVersion = String(version).toLowerCase().replace(/_/g, '.').replace(/[\-+]/g, '');
425
426             releaseStartIndex = this.version.search(/([^\d\.])/);
427
428             if (releaseStartIndex !== -1) {
429                 this.release = this.version.substr(releaseStartIndex, version.length);
430                 this.shortVersion = this.version.substr(0, releaseStartIndex);
431             }
432
433             this.shortVersion = this.shortVersion.replace(/[^\d]/g, '');
434
435             parts = this.version.split('.');
436
437             this.major = parseInt(parts.shift() || 0, 10);
438             this.minor = parseInt(parts.shift() || 0, 10);
439             this.patch = parseInt(parts.shift() || 0, 10);
440             this.build = parseInt(parts.shift() || 0, 10);
441
442             return this;
443         },
444
445         
446         toString: function() {
447             return this.version;
448         },
449
450         
451         valueOf: function() {
452             return this.version;
453         },
454
455         
456         getMajor: function() {
457             return this.major || 0;
458         },
459
460         
461         getMinor: function() {
462             return this.minor || 0;
463         },
464
465         
466         getPatch: function() {
467             return this.patch || 0;
468         },
469
470         
471         getBuild: function() {
472             return this.build || 0;
473         },
474
475         
476         getRelease: function() {
477             return this.release || '';
478         },
479
480         
481         isGreaterThan: function(target) {
482             return Version.compare(this.version, target) === 1;
483         },
484
485         
486         isLessThan: function(target) {
487             return Version.compare(this.version, target) === -1;
488         },
489
490         
491         equals: function(target) {
492             return Version.compare(this.version, target) === 0;
493         },
494
495         
496         match: function(target) {
497             target = String(target);
498             return this.version.substr(0, target.length) === target;
499         },
500
501         
502         toArray: function() {
503             return [this.getMajor(), this.getMinor(), this.getPatch(), this.getBuild(), this.getRelease()];
504         },
505
506         
507         getShortVersion: function() {
508             return this.shortVersion;
509         }
510     });
511
512     Ext.apply(Version, {
513         
514         releaseValueMap: {
515             'dev': -6,
516             'alpha': -5,
517             'a': -5,
518             'beta': -4,
519             'b': -4,
520             'rc': -3,
521             '#': -2,
522             'p': -1,
523             'pl': -1
524         },
525
526         
527         getComponentValue: function(value) {
528             return !value ? 0 : (isNaN(value) ? this.releaseValueMap[value] || value : parseInt(value, 10));
529         },
530
531         
532         compare: function(current, target) {
533             var currentValue, targetValue, i;
534
535             current = new Version(current).toArray();
536             target = new Version(target).toArray();
537
538             for (i = 0; i < Math.max(current.length, target.length); i++) {
539                 currentValue = this.getComponentValue(current[i]);
540                 targetValue = this.getComponentValue(target[i]);
541
542                 if (currentValue < targetValue) {
543                     return -1;
544                 } else if (currentValue > targetValue) {
545                     return 1;
546                 }
547             }
548
549             return 0;
550         }
551     });
552
553     Ext.apply(Ext, {
554         
555         versions: {},
556
557         
558         lastRegisteredVersion: null,
559
560         
561         setVersion: function(packageName, version) {
562             Ext.versions[packageName] = new Version(version);
563             Ext.lastRegisteredVersion = Ext.versions[packageName];
564
565             return this;
566         },
567
568         
569         getVersion: function(packageName) {
570             if (packageName === undefined) {
571                 return Ext.lastRegisteredVersion;
572             }
573
574             return Ext.versions[packageName];
575         },
576
577         
578         deprecate: function(packageName, since, closure, scope) {
579             if (Version.compare(Ext.getVersion(packageName), since) < 1) {
580                 closure.call(scope);
581             }
582         }
583     }); 
584
585     Ext.setVersion('core', version);
586
587 })();
588
589
590
591 Ext.String = {
592     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,
593     escapeRe: /('|\\)/g,
594     formatRe: /\{(\d+)\}/g,
595     escapeRegexRe: /([-.*+?^${}()|[\]\/\\])/g,
596
597     /**
598      * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
599      * @param {String} value The string to encode
600      * @return {String} The encoded text
601      * @method
602      */
603     htmlEncode: (function() {
604         var entities = {
605             '&': '&amp;',
606             '>': '&gt;',
607             '<': '&lt;',
608             '"': '&quot;'
609         }, keys = [], p, regex;
610         
611         for (p in entities) {
612             keys.push(p);
613         }
614         
615         regex = new RegExp('(' + keys.join('|') + ')', 'g');
616         
617         return function(value) {
618             return (!value) ? value : String(value).replace(regex, function(match, capture) {
619                 return entities[capture];    
620             });
621         };
622     })(),
623
624     
625     htmlDecode: (function() {
626         var entities = {
627             '&amp;': '&',
628             '&gt;': '>',
629             '&lt;': '<',
630             '&quot;': '"'
631         }, keys = [], p, regex;
632         
633         for (p in entities) {
634             keys.push(p);
635         }
636         
637         regex = new RegExp('(' + keys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
638         
639         return function(value) {
640             return (!value) ? value : String(value).replace(regex, function(match, capture) {
641                 if (capture in entities) {
642                     return entities[capture];
643                 } else {
644                     return String.fromCharCode(parseInt(capture.substr(2), 10));
645                 }
646             });
647         };
648     })(),
649
650     
651     urlAppend : function(url, string) {
652         if (!Ext.isEmpty(string)) {
653             return url + (url.indexOf('?') === -1 ? '?' : '&') + string;
654         }
655
656         return url;
657     },
658
659     
660     trim: function(string) {
661         return string.replace(Ext.String.trimRegex, "");
662     },
663
664     
665     capitalize: function(string) {
666         return string.charAt(0).toUpperCase() + string.substr(1);
667     },
668
669     
670     ellipsis: function(value, len, word) {
671         if (value && value.length > len) {
672             if (word) {
673                 var vs = value.substr(0, len - 2),
674                 index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
675                 if (index !== -1 && index >= (len - 15)) {
676                     return vs.substr(0, index) + "...";
677                 }
678             }
679             return value.substr(0, len - 3) + "...";
680         }
681         return value;
682     },
683
684     
685     escapeRegex: function(string) {
686         return string.replace(Ext.String.escapeRegexRe, "\\$1");
687     },
688
689     
690     escape: function(string) {
691         return string.replace(Ext.String.escapeRe, "\\$1");
692     },
693
694     
695     toggle: function(string, value, other) {
696         return string === value ? other : value;
697     },
698
699     
700     leftPad: function(string, size, character) {
701         var result = String(string);
702         character = character || " ";
703         while (result.length < size) {
704             result = character + result;
705         }
706         return result;
707     },
708
709     
710     format: function(format) {
711         var args = Ext.Array.toArray(arguments, 1);
712         return format.replace(Ext.String.formatRe, function(m, i) {
713             return args[i];
714         });
715     }
716 };
717
718
719
720 (function() {
721
722 var isToFixedBroken = (0.9).toFixed() !== '1';
723
724 Ext.Number = {
725     
726     constrain: function(number, min, max) {
727         number = parseFloat(number);
728
729         if (!isNaN(min)) {
730             number = Math.max(number, min);
731         }
732         if (!isNaN(max)) {
733             number = Math.min(number, max);
734         }
735         return number;
736     },
737
738     
739     toFixed: function(value, precision) {
740         if (isToFixedBroken) {
741             precision = precision || 0;
742             var pow = Math.pow(10, precision);
743             return (Math.round(value * pow) / pow).toFixed(precision);
744         }
745
746         return value.toFixed(precision);
747     },
748
749     
750     from: function(value, defaultValue) {
751         if (isFinite(value)) {
752             value = parseFloat(value);
753         }
754
755         return !isNaN(value) ? value : defaultValue;
756     }
757 };
758
759 })();
760
761
762 Ext.num = function() {
763     return Ext.Number.from.apply(this, arguments);
764 };
765
766 (function() {
767
768     var arrayPrototype = Array.prototype,
769         slice = arrayPrototype.slice,
770         supportsForEach = 'forEach' in arrayPrototype,
771         supportsMap = 'map' in arrayPrototype,
772         supportsIndexOf = 'indexOf' in arrayPrototype,
773         supportsEvery = 'every' in arrayPrototype,
774         supportsSome = 'some' in arrayPrototype,
775         supportsFilter = 'filter' in arrayPrototype,
776         supportsSort = function() {
777             var a = [1,2,3,4,5].sort(function(){ return 0; });
778             return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
779         }(),
780         supportsSliceOnNodeList = true,
781         ExtArray;
782     try {
783         
784         if (typeof document !== 'undefined') {
785             slice.call(document.getElementsByTagName('body'));
786         }
787     } catch (e) {
788         supportsSliceOnNodeList = false;
789     }
790
791     ExtArray = Ext.Array = {
792         
793         each: function(array, fn, scope, reverse) {
794             array = ExtArray.from(array);
795
796             var i,
797                 ln = array.length;
798
799             if (reverse !== true) {
800                 for (i = 0; i < ln; i++) {
801                     if (fn.call(scope || array[i], array[i], i, array) === false) {
802                         return i;
803                     }
804                 }
805             }
806             else {
807                 for (i = ln - 1; i > -1; i--) {
808                     if (fn.call(scope || array[i], array[i], i, array) === false) {
809                         return i;
810                     }
811                 }
812             }
813
814             return true;
815         },
816
817         
818         forEach: function(array, fn, scope) {
819             if (supportsForEach) {
820                 return array.forEach(fn, scope);
821             }
822
823             var i = 0,
824                 ln = array.length;
825
826             for (; i < ln; i++) {
827                 fn.call(scope, array[i], i, array);
828             }
829         },
830
831         
832         indexOf: function(array, item, from) {
833             if (supportsIndexOf) {
834                 return array.indexOf(item, from);
835             }
836
837             var i, length = array.length;
838
839             for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {
840                 if (array[i] === item) {
841                     return i;
842                 }
843             }
844
845             return -1;
846         },
847
848         
849         contains: function(array, item) {
850             if (supportsIndexOf) {
851                 return array.indexOf(item) !== -1;
852             }
853
854             var i, ln;
855
856             for (i = 0, ln = array.length; i < ln; i++) {
857                 if (array[i] === item) {
858                     return true;
859                 }
860             }
861
862             return false;
863         },
864
865         
866         toArray: function(iterable, start, end){
867             if (!iterable || !iterable.length) {
868                 return [];
869             }
870
871             if (typeof iterable === 'string') {
872                 iterable = iterable.split('');
873             }
874
875             if (supportsSliceOnNodeList) {
876                 return slice.call(iterable, start || 0, end || iterable.length);
877             }
878
879             var array = [],
880                 i;
881
882             start = start || 0;
883             end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;
884
885             for (i = start; i < end; i++) {
886                 array.push(iterable[i]);
887             }
888
889             return array;
890         },
891
892         
893         pluck: function(array, propertyName) {
894             var ret = [],
895                 i, ln, item;
896
897             for (i = 0, ln = array.length; i < ln; i++) {
898                 item = array[i];
899
900                 ret.push(item[propertyName]);
901             }
902
903             return ret;
904         },
905
906         
907         map: function(array, fn, scope) {
908             if (supportsMap) {
909                 return array.map(fn, scope);
910             }
911
912             var results = [],
913                 i = 0,
914                 len = array.length;
915
916             for (; i < len; i++) {
917                 results[i] = fn.call(scope, array[i], i, array);
918             }
919
920             return results;
921         },
922
923         
924         every: function(array, fn, scope) {
925             if (!fn) {
926                 Ext.Error.raise('Ext.Array.every must have a callback function passed as second argument.');
927             }
928             if (supportsEvery) {
929                 return array.every(fn, scope);
930             }
931
932             var i = 0,
933                 ln = array.length;
934
935             for (; i < ln; ++i) {
936                 if (!fn.call(scope, array[i], i, array)) {
937                     return false;
938                 }
939             }
940
941             return true;
942         },
943
944         
945         some: function(array, fn, scope) {
946             if (!fn) {
947                 Ext.Error.raise('Ext.Array.some must have a callback function passed as second argument.');
948             }
949             if (supportsSome) {
950                 return array.some(fn, scope);
951             }
952
953             var i = 0,
954                 ln = array.length;
955
956             for (; i < ln; ++i) {
957                 if (fn.call(scope, array[i], i, array)) {
958                     return true;
959                 }
960             }
961
962             return false;
963         },
964
965         
966         clean: function(array) {
967             var results = [],
968                 i = 0,
969                 ln = array.length,
970                 item;
971
972             for (; i < ln; i++) {
973                 item = array[i];
974
975                 if (!Ext.isEmpty(item)) {
976                     results.push(item);
977                 }
978             }
979
980             return results;
981         },
982
983         
984         unique: function(array) {
985             var clone = [],
986                 i = 0,
987                 ln = array.length,
988                 item;
989
990             for (; i < ln; i++) {
991                 item = array[i];
992
993                 if (ExtArray.indexOf(clone, item) === -1) {
994                     clone.push(item);
995                 }
996             }
997
998             return clone;
999         },
1000
1001         
1002         filter: function(array, fn, scope) {
1003             if (supportsFilter) {
1004                 return array.filter(fn, scope);
1005             }
1006
1007             var results = [],
1008                 i = 0,
1009                 ln = array.length;
1010
1011             for (; i < ln; i++) {
1012                 if (fn.call(scope, array[i], i, array)) {
1013                     results.push(array[i]);
1014                 }
1015             }
1016
1017             return results;
1018         },
1019
1020         
1021         from: function(value, newReference) {
1022             if (value === undefined || value === null) {
1023                 return [];
1024             }
1025
1026             if (Ext.isArray(value)) {
1027                 return (newReference) ? slice.call(value) : value;
1028             }
1029
1030             if (value && value.length !== undefined && typeof value !== 'string') {
1031                 return Ext.toArray(value);
1032             }
1033
1034             return [value];
1035         },
1036
1037         
1038         remove: function(array, item) {
1039             var index = ExtArray.indexOf(array, item);
1040
1041             if (index !== -1) {
1042                 array.splice(index, 1);
1043             }
1044
1045             return array;
1046         },
1047
1048         
1049         include: function(array, item) {
1050             if (!ExtArray.contains(array, item)) {
1051                 array.push(item);
1052             }
1053         },
1054
1055         
1056         clone: function(array) {
1057             return slice.call(array);
1058         },
1059
1060         
1061         merge: function() {
1062             var args = slice.call(arguments),
1063                 array = [],
1064                 i, ln;
1065
1066             for (i = 0, ln = args.length; i < ln; i++) {
1067                 array = array.concat(args[i]);
1068             }
1069
1070             return ExtArray.unique(array);
1071         },
1072
1073         
1074         intersect: function() {
1075             var intersect = [],
1076                 arrays = slice.call(arguments),
1077                 i, j, k, minArray, array, x, y, ln, arraysLn, arrayLn;
1078
1079             if (!arrays.length) {
1080                 return intersect;
1081             }
1082
1083             
1084             for (i = x = 0,ln = arrays.length; i < ln,array = arrays[i]; i++) {
1085                 if (!minArray || array.length < minArray.length) {
1086                     minArray = array;
1087                     x = i;
1088                 }
1089             }
1090
1091             minArray = Ext.Array.unique(minArray);
1092             arrays.splice(x, 1);
1093
1094             
1095             
1096             
1097             for (i = 0,ln = minArray.length; i < ln,x = minArray[i]; i++) {
1098                 var count = 0;
1099
1100                 for (j = 0,arraysLn = arrays.length; j < arraysLn,array = arrays[j]; j++) {
1101                     for (k = 0,arrayLn = array.length; k < arrayLn,y = array[k]; k++) {
1102                         if (x === y) {
1103                             count++;
1104                             break;
1105                         }
1106                     }
1107                 }
1108
1109                 if (count === arraysLn) {
1110                     intersect.push(x);
1111                 }
1112             }
1113
1114             return intersect;
1115         },
1116
1117         
1118         difference: function(arrayA, arrayB) {
1119             var clone = slice.call(arrayA),
1120                 ln = clone.length,
1121                 i, j, lnB;
1122
1123             for (i = 0,lnB = arrayB.length; i < lnB; i++) {
1124                 for (j = 0; j < ln; j++) {
1125                     if (clone[j] === arrayB[i]) {
1126                         clone.splice(j, 1);
1127                         j--;
1128                         ln--;
1129                     }
1130                 }
1131             }
1132
1133             return clone;
1134         },
1135
1136         
1137         sort: function(array, sortFn) {
1138             if (supportsSort) {
1139                 if (sortFn) {
1140                     return array.sort(sortFn);
1141                 } else {
1142                     return array.sort();
1143                 }
1144             }
1145
1146             var length = array.length,
1147                 i = 0,
1148                 comparison,
1149                 j, min, tmp;
1150
1151             for (; i < length; i++) {
1152                 min = i;
1153                 for (j = i + 1; j < length; j++) {
1154                     if (sortFn) {
1155                         comparison = sortFn(array[j], array[min]);
1156                         if (comparison < 0) {
1157                             min = j;
1158                         }
1159                     } else if (array[j] < array[min]) {
1160                         min = j;
1161                     }
1162                 }
1163                 if (min !== i) {
1164                     tmp = array[i];
1165                     array[i] = array[min];
1166                     array[min] = tmp;
1167                 }
1168             }
1169
1170             return array;
1171         },
1172
1173         
1174         flatten: function(array) {
1175             var worker = [];
1176
1177             function rFlatten(a) {
1178                 var i, ln, v;
1179
1180                 for (i = 0, ln = a.length; i < ln; i++) {
1181                     v = a[i];
1182
1183                     if (Ext.isArray(v)) {
1184                         rFlatten(v);
1185                     } else {
1186                         worker.push(v);
1187                     }
1188                 }
1189
1190                 return worker;
1191             }
1192
1193             return rFlatten(array);
1194         },
1195
1196         
1197         min: function(array, comparisonFn) {
1198             var min = array[0],
1199                 i, ln, item;
1200
1201             for (i = 0, ln = array.length; i < ln; i++) {
1202                 item = array[i];
1203
1204                 if (comparisonFn) {
1205                     if (comparisonFn(min, item) === 1) {
1206                         min = item;
1207                     }
1208                 }
1209                 else {
1210                     if (item < min) {
1211                         min = item;
1212                     }
1213                 }
1214             }
1215
1216             return min;
1217         },
1218
1219         
1220         max: function(array, comparisonFn) {
1221             var max = array[0],
1222                 i, ln, item;
1223
1224             for (i = 0, ln = array.length; i < ln; i++) {
1225                 item = array[i];
1226
1227                 if (comparisonFn) {
1228                     if (comparisonFn(max, item) === -1) {
1229                         max = item;
1230                     }
1231                 }
1232                 else {
1233                     if (item > max) {
1234                         max = item;
1235                     }
1236                 }
1237             }
1238
1239             return max;
1240         },
1241
1242         
1243         mean: function(array) {
1244             return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;
1245         },
1246
1247         
1248         sum: function(array) {
1249             var sum = 0,
1250                 i, ln, item;
1251
1252             for (i = 0,ln = array.length; i < ln; i++) {
1253                 item = array[i];
1254
1255                 sum += item;
1256             }
1257
1258             return sum;
1259         }
1260
1261     };
1262
1263     
1264     Ext.each = Ext.Array.each;
1265
1266     
1267     Ext.Array.union = Ext.Array.merge;
1268
1269     
1270     Ext.min = Ext.Array.min;
1271
1272     
1273     Ext.max = Ext.Array.max;
1274
1275     
1276     Ext.sum = Ext.Array.sum;
1277
1278     
1279     Ext.mean = Ext.Array.mean;
1280
1281     
1282     Ext.flatten = Ext.Array.flatten;
1283
1284     
1285     Ext.clean = Ext.Array.clean;
1286
1287     
1288     Ext.unique = Ext.Array.unique;
1289
1290     
1291     Ext.pluck = Ext.Array.pluck;
1292
1293     
1294     Ext.toArray = function() {
1295         return ExtArray.toArray.apply(ExtArray, arguments);
1296     }
1297 })();
1298
1299
1300
1301 Ext.Function = {
1302
1303     
1304     flexSetter: function(fn) {
1305         return function(a, b) {
1306             var k, i;
1307
1308             if (a === null) {
1309                 return this;
1310             }
1311
1312             if (typeof a !== 'string') {
1313                 for (k in a) {
1314                     if (a.hasOwnProperty(k)) {
1315                         fn.call(this, k, a[k]);
1316                     }
1317                 }
1318
1319                 if (Ext.enumerables) {
1320                     for (i = Ext.enumerables.length; i--;) {
1321                         k = Ext.enumerables[i];
1322                         if (a.hasOwnProperty(k)) {
1323                             fn.call(this, k, a[k]);
1324                         }
1325                     }
1326                 }
1327             } else {
1328                 fn.call(this, a, b);
1329             }
1330
1331             return this;
1332         };
1333     },
1334
1335    
1336     bind: function(fn, scope, args, appendArgs) {
1337         var method = fn,
1338             applyArgs;
1339
1340         return function() {
1341             var callArgs = args || arguments;
1342
1343             if (appendArgs === true) {
1344                 callArgs = Array.prototype.slice.call(arguments, 0);
1345                 callArgs = callArgs.concat(args);
1346             }
1347             else if (Ext.isNumber(appendArgs)) {
1348                 callArgs = Array.prototype.slice.call(arguments, 0); 
1349                 applyArgs = [appendArgs, 0].concat(args); 
1350                 Array.prototype.splice.apply(callArgs, applyArgs); 
1351             }
1352
1353             return method.apply(scope || window, callArgs);
1354         };
1355     },
1356
1357     
1358     pass: function(fn, args, scope) {
1359         if (args) {
1360             args = Ext.Array.from(args);
1361         }
1362
1363         return function() {
1364             return fn.apply(scope, args.concat(Ext.Array.toArray(arguments)));
1365         };
1366     },
1367
1368     
1369     alias: function(object, methodName) {
1370         return function() {
1371             return object[methodName].apply(object, arguments);
1372         };
1373     },
1374
1375     
1376     createInterceptor: function(origFn, newFn, scope, returnValue) {
1377         var method = origFn;
1378         if (!Ext.isFunction(newFn)) {
1379             return origFn;
1380         }
1381         else {
1382             return function() {
1383                 var me = this,
1384                     args = arguments;
1385                 newFn.target = me;
1386                 newFn.method = origFn;
1387                 return (newFn.apply(scope || me || window, args) !== false) ? origFn.apply(me || window, args) : returnValue || null;
1388             };
1389         }
1390     },
1391
1392     
1393     createDelayed: function(fn, delay, scope, args, appendArgs) {
1394         if (scope || args) {
1395             fn = Ext.Function.bind(fn, scope, args, appendArgs);
1396         }
1397         return function() {
1398             var me = this;
1399             setTimeout(function() {
1400                 fn.apply(me, arguments);
1401             }, delay);
1402         };
1403     },
1404
1405     
1406     defer: function(fn, millis, obj, args, appendArgs) {
1407         fn = Ext.Function.bind(fn, obj, args, appendArgs);
1408         if (millis > 0) {
1409             return setTimeout(fn, millis);
1410         }
1411         fn();
1412         return 0;
1413     },
1414
1415     
1416     createSequence: function(origFn, newFn, scope) {
1417         if (!Ext.isFunction(newFn)) {
1418             return origFn;
1419         }
1420         else {
1421             return function() {
1422                 var retval = origFn.apply(this || window, arguments);
1423                 newFn.apply(scope || this || window, arguments);
1424                 return retval;
1425             };
1426         }
1427     },
1428
1429     
1430     createBuffered: function(fn, buffer, scope, args) {
1431         return function(){
1432             var timerId;
1433             return function() {
1434                 var me = this;
1435                 if (timerId) {
1436                     clearInterval(timerId);
1437                     timerId = null;
1438                 }
1439                 timerId = setTimeout(function(){
1440                     fn.apply(scope || me, args || arguments);
1441                 }, buffer);
1442             };
1443         }();
1444     },
1445
1446     
1447     createThrottled: function(fn, interval, scope) {
1448         var lastCallTime, elapsed, lastArgs, timer, execute = function() {
1449             fn.apply(scope || this, lastArgs);
1450             lastCallTime = new Date().getTime();
1451         };
1452
1453         return function() {
1454             elapsed = new Date().getTime() - lastCallTime;
1455             lastArgs = arguments;
1456
1457             clearTimeout(timer);
1458             if (!lastCallTime || (elapsed >= interval)) {
1459                 execute();
1460             } else {
1461                 timer = setTimeout(execute, interval - elapsed);
1462             }
1463         };
1464     }
1465 };
1466
1467
1468 Ext.defer = Ext.Function.alias(Ext.Function, 'defer');
1469
1470
1471 Ext.pass = Ext.Function.alias(Ext.Function, 'pass');
1472
1473
1474 Ext.bind = Ext.Function.alias(Ext.Function, 'bind');
1475
1476
1477
1478 (function() {
1479
1480 var ExtObject = Ext.Object = {
1481
1482     
1483     toQueryObjects: function(name, value, recursive) {
1484         var self = ExtObject.toQueryObjects,
1485             objects = [],
1486             i, ln;
1487
1488         if (Ext.isArray(value)) {
1489             for (i = 0, ln = value.length; i < ln; i++) {
1490                 if (recursive) {
1491                     objects = objects.concat(self(name + '[' + i + ']', value[i], true));
1492                 }
1493                 else {
1494                     objects.push({
1495                         name: name,
1496                         value: value[i]
1497                     });
1498                 }
1499             }
1500         }
1501         else if (Ext.isObject(value)) {
1502             for (i in value) {
1503                 if (value.hasOwnProperty(i)) {
1504                     if (recursive) {
1505                         objects = objects.concat(self(name + '[' + i + ']', value[i], true));
1506                     }
1507                     else {
1508                         objects.push({
1509                             name: name,
1510                             value: value[i]
1511                         });
1512                     }
1513                 }
1514             }
1515         }
1516         else {
1517             objects.push({
1518                 name: name,
1519                 value: value
1520             });
1521         }
1522
1523         return objects;
1524     },
1525
1526     
1527     toQueryString: function(object, recursive) {
1528         var paramObjects = [],
1529             params = [],
1530             i, j, ln, paramObject, value;
1531
1532         for (i in object) {
1533             if (object.hasOwnProperty(i)) {
1534                 paramObjects = paramObjects.concat(ExtObject.toQueryObjects(i, object[i], recursive));
1535             }
1536         }
1537
1538         for (j = 0, ln = paramObjects.length; j < ln; j++) {
1539             paramObject = paramObjects[j];
1540             value = paramObject.value;
1541
1542             if (Ext.isEmpty(value)) {
1543                 value = '';
1544             }
1545             else if (Ext.isDate(value)) {
1546                 value = Ext.Date.toString(value);
1547             }
1548
1549             params.push(encodeURIComponent(paramObject.name) + '=' + encodeURIComponent(String(value)));
1550         }
1551
1552         return params.join('&');
1553     },
1554
1555     
1556     fromQueryString: function(queryString, recursive) {
1557         var parts = queryString.replace(/^\?/, '').split('&'),
1558             object = {},
1559             temp, components, name, value, i, ln,
1560             part, j, subLn, matchedKeys, matchedName,
1561             keys, key, nextKey;
1562
1563         for (i = 0, ln = parts.length; i < ln; i++) {
1564             part = parts[i];
1565
1566             if (part.length > 0) {
1567                 components = part.split('=');
1568                 name = decodeURIComponent(components[0]);
1569                 value = (components[1] !== undefined) ? decodeURIComponent(components[1]) : '';
1570
1571                 if (!recursive) {
1572                     if (object.hasOwnProperty(name)) {
1573                         if (!Ext.isArray(object[name])) {
1574                             object[name] = [object[name]];
1575                         }
1576
1577                         object[name].push(value);
1578                     }
1579                     else {
1580                         object[name] = value;
1581                     }
1582                 }
1583                 else {
1584                     matchedKeys = name.match(/(\[):?([^\]]*)\]/g);
1585                     matchedName = name.match(/^([^\[]+)/);
1586
1587                     if (!matchedName) {
1588                         Ext.Error.raise({
1589                             sourceClass: "Ext.Object",
1590                             sourceMethod: "fromQueryString",
1591                             queryString: queryString,
1592                             recursive: recursive,
1593                             msg: 'Malformed query string given, failed parsing name from "' + part + '"'
1594                         });
1595                     }
1596
1597                     name = matchedName[0];
1598                     keys = [];
1599
1600                     if (matchedKeys === null) {
1601                         object[name] = value;
1602                         continue;
1603                     }
1604
1605                     for (j = 0, subLn = matchedKeys.length; j < subLn; j++) {
1606                         key = matchedKeys[j];
1607                         key = (key.length === 2) ? '' : key.substring(1, key.length - 1);
1608                         keys.push(key);
1609                     }
1610
1611                     keys.unshift(name);
1612
1613                     temp = object;
1614
1615                     for (j = 0, subLn = keys.length; j < subLn; j++) {
1616                         key = keys[j];
1617
1618                         if (j === subLn - 1) {
1619                             if (Ext.isArray(temp) && key === '') {
1620                                 temp.push(value);
1621                             }
1622                             else {
1623                                 temp[key] = value;
1624                             }
1625                         }
1626                         else {
1627                             if (temp[key] === undefined || typeof temp[key] === 'string') {
1628                                 nextKey = keys[j+1];
1629
1630                                 temp[key] = (Ext.isNumeric(nextKey) || nextKey === '') ? [] : {};
1631                             }
1632
1633                             temp = temp[key];
1634                         }
1635                     }
1636                 }
1637             }
1638         }
1639
1640         return object;
1641     },
1642
1643     
1644     each: function(object, fn, scope) {
1645         for (var property in object) {
1646             if (object.hasOwnProperty(property)) {
1647                 if (fn.call(scope || object, property, object[property], object) === false) {
1648                     return;
1649                 }
1650             }
1651         }
1652     },
1653
1654     
1655     merge: function(source, key, value) {
1656         if (typeof key === 'string') {
1657             if (value && value.constructor === Object) {
1658                 if (source[key] && source[key].constructor === Object) {
1659                     ExtObject.merge(source[key], value);
1660                 }
1661                 else {
1662                     source[key] = Ext.clone(value);
1663                 }
1664             }
1665             else {
1666                 source[key] = value;
1667             }
1668
1669             return source;
1670         }
1671
1672         var i = 1,
1673             ln = arguments.length,
1674             object, property;
1675
1676         for (; i < ln; i++) {
1677             object = arguments[i];
1678
1679             for (property in object) {
1680                 if (object.hasOwnProperty(property)) {
1681                     ExtObject.merge(source, property, object[property]);
1682                 }
1683             }
1684         }
1685
1686         return source;
1687     },
1688
1689     
1690     getKey: function(object, value) {
1691         for (var property in object) {
1692             if (object.hasOwnProperty(property) && object[property] === value) {
1693                 return property;
1694             }
1695         }
1696
1697         return null;
1698     },
1699
1700     
1701     getValues: function(object) {
1702         var values = [],
1703             property;
1704
1705         for (property in object) {
1706             if (object.hasOwnProperty(property)) {
1707                 values.push(object[property]);
1708             }
1709         }
1710
1711         return values;
1712     },
1713
1714     
1715     getKeys: ('keys' in Object.prototype) ? Object.keys : function(object) {
1716         var keys = [],
1717             property;
1718
1719         for (property in object) {
1720             if (object.hasOwnProperty(property)) {
1721                 keys.push(property);
1722             }
1723         }
1724
1725         return keys;
1726     },
1727
1728     
1729     getSize: function(object) {
1730         var size = 0,
1731             property;
1732
1733         for (property in object) {
1734             if (object.hasOwnProperty(property)) {
1735                 size++;
1736             }
1737         }
1738
1739         return size;
1740     }
1741 };
1742
1743
1744
1745 Ext.merge = Ext.Object.merge;
1746
1747
1748 Ext.urlEncode = function() {
1749     var args = Ext.Array.from(arguments),
1750         prefix = '';
1751
1752     
1753     if ((typeof args[1] === 'string')) {
1754         prefix = args[1] + '&';
1755         args[1] = false;
1756     }
1757
1758     return prefix + Ext.Object.toQueryString.apply(Ext.Object, args);
1759 };
1760
1761
1762 Ext.urlDecode = function() {
1763     return Ext.Object.fromQueryString.apply(Ext.Object, arguments);
1764 };
1765
1766 })();
1767
1768
1769
1770
1771
1772 (function() {
1773
1774
1775
1776
1777 function xf(format) {
1778     var args = Array.prototype.slice.call(arguments, 1);
1779     return format.replace(/\{(\d+)\}/g, function(m, i) {
1780         return args[i];
1781     });
1782 }
1783
1784 Ext.Date = {
1785     
1786     now: Date.now || function() {
1787         return +new Date();
1788     },
1789
1790     
1791     toString: function(date) {
1792         var pad = Ext.String.leftPad;
1793
1794         return date.getFullYear() + "-"
1795             + pad(date.getMonth() + 1, 2, '0') + "-"
1796             + pad(date.getDate(), 2, '0') + "T"
1797             + pad(date.getHours(), 2, '0') + ":"
1798             + pad(date.getMinutes(), 2, '0') + ":"
1799             + pad(date.getSeconds(), 2, '0');
1800     },
1801
1802     
1803     getElapsed: function(dateA, dateB) {
1804         return Math.abs(dateA - (dateB || new Date()));
1805     },
1806
1807     
1808     useStrict: false,
1809
1810     
1811     formatCodeToRegex: function(character, currentGroup) {
1812         
1813         var p = utilDate.parseCodes[character];
1814
1815         if (p) {
1816           p = typeof p == 'function'? p() : p;
1817           utilDate.parseCodes[character] = p; 
1818         }
1819
1820         return p ? Ext.applyIf({
1821           c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
1822         }, p) : {
1823             g: 0,
1824             c: null,
1825             s: Ext.String.escapeRegex(character) 
1826         };
1827     },
1828
1829     
1830     parseFunctions: {
1831         "MS": function(input, strict) {
1832             
1833             
1834             var re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
1835             var r = (input || '').match(re);
1836             return r? new Date(((r[1] || '') + r[2]) * 1) : null;
1837         }
1838     },
1839     parseRegexes: [],
1840
1841     
1842     formatFunctions: {
1843         "MS": function() {
1844             
1845             return '\\/Date(' + this.getTime() + ')\\/';
1846         }
1847     },
1848
1849     y2kYear : 50,
1850
1851     
1852     MILLI : "ms",
1853
1854     
1855     SECOND : "s",
1856
1857     
1858     MINUTE : "mi",
1859
1860     
1861     HOUR : "h",
1862
1863     
1864     DAY : "d",
1865
1866     
1867     MONTH : "mo",
1868
1869     
1870     YEAR : "y",
1871
1872     
1873     defaults: {},
1874
1875     
1876     dayNames : [
1877         "Sunday",
1878         "Monday",
1879         "Tuesday",
1880         "Wednesday",
1881         "Thursday",
1882         "Friday",
1883         "Saturday"
1884     ],
1885
1886     
1887     monthNames : [
1888         "January",
1889         "February",
1890         "March",
1891         "April",
1892         "May",
1893         "June",
1894         "July",
1895         "August",
1896         "September",
1897         "October",
1898         "November",
1899         "December"
1900     ],
1901
1902     
1903     monthNumbers : {
1904         Jan:0,
1905         Feb:1,
1906         Mar:2,
1907         Apr:3,
1908         May:4,
1909         Jun:5,
1910         Jul:6,
1911         Aug:7,
1912         Sep:8,
1913         Oct:9,
1914         Nov:10,
1915         Dec:11
1916     },
1917     
1918     defaultFormat : "m/d/Y",
1919     
1920     getShortMonthName : function(month) {
1921         return utilDate.monthNames[month].substring(0, 3);
1922     },
1923
1924     
1925     getShortDayName : function(day) {
1926         return utilDate.dayNames[day].substring(0, 3);
1927     },
1928
1929     
1930     getMonthNumber : function(name) {
1931         
1932         return utilDate.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
1933     },
1934
1935     
1936     formatContainsHourInfo : (function(){
1937         var stripEscapeRe = /(\\.)/g,
1938             hourInfoRe = /([gGhHisucUOPZ]|MS)/;
1939         return function(format){
1940             return hourInfoRe.test(format.replace(stripEscapeRe, ''));
1941         };
1942     })(),
1943
1944     
1945     formatContainsDateInfo : (function(){
1946         var stripEscapeRe = /(\\.)/g,
1947             dateInfoRe = /([djzmnYycU]|MS)/;
1948
1949         return function(format){
1950             return dateInfoRe.test(format.replace(stripEscapeRe, ''));
1951         };
1952     })(),
1953
1954     
1955     formatCodes : {
1956         d: "Ext.String.leftPad(this.getDate(), 2, '0')",
1957         D: "Ext.Date.getShortDayName(this.getDay())", 
1958         j: "this.getDate()",
1959         l: "Ext.Date.dayNames[this.getDay()]",
1960         N: "(this.getDay() ? this.getDay() : 7)",
1961         S: "Ext.Date.getSuffix(this)",
1962         w: "this.getDay()",
1963         z: "Ext.Date.getDayOfYear(this)",
1964         W: "Ext.String.leftPad(Ext.Date.getWeekOfYear(this), 2, '0')",
1965         F: "Ext.Date.monthNames[this.getMonth()]",
1966         m: "Ext.String.leftPad(this.getMonth() + 1, 2, '0')",
1967         M: "Ext.Date.getShortMonthName(this.getMonth())", 
1968         n: "(this.getMonth() + 1)",
1969         t: "Ext.Date.getDaysInMonth(this)",
1970         L: "(Ext.Date.isLeapYear(this) ? 1 : 0)",
1971         o: "(this.getFullYear() + (Ext.Date.getWeekOfYear(this) == 1 && this.getMonth() > 0 ? +1 : (Ext.Date.getWeekOfYear(this) >= 52 && this.getMonth() < 11 ? -1 : 0)))",
1972         Y: "Ext.String.leftPad(this.getFullYear(), 4, '0')",
1973         y: "('' + this.getFullYear()).substring(2, 4)",
1974         a: "(this.getHours() < 12 ? 'am' : 'pm')",
1975         A: "(this.getHours() < 12 ? 'AM' : 'PM')",
1976         g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
1977         G: "this.getHours()",
1978         h: "Ext.String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
1979         H: "Ext.String.leftPad(this.getHours(), 2, '0')",
1980         i: "Ext.String.leftPad(this.getMinutes(), 2, '0')",
1981         s: "Ext.String.leftPad(this.getSeconds(), 2, '0')",
1982         u: "Ext.String.leftPad(this.getMilliseconds(), 3, '0')",
1983         O: "Ext.Date.getGMTOffset(this)",
1984         P: "Ext.Date.getGMTOffset(this, true)",
1985         T: "Ext.Date.getTimezone(this)",
1986         Z: "(this.getTimezoneOffset() * -60)",
1987
1988         c: function() { 
1989             for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
1990                 var e = c.charAt(i);
1991                 code.push(e == "T" ? "'T'" : utilDate.getFormatCode(e)); 
1992             }
1993             return code.join(" + ");
1994         },
1995         
1996
1997         U: "Math.round(this.getTime() / 1000)"
1998     },
1999
2000     
2001     isValid : function(y, m, d, h, i, s, ms) {
2002         
2003         h = h || 0;
2004         i = i || 0;
2005         s = s || 0;
2006         ms = ms || 0;
2007
2008         
2009         var dt = utilDate.add(new Date(y < 100 ? 100 : y, m - 1, d, h, i, s, ms), utilDate.YEAR, y < 100 ? y - 100 : 0);
2010
2011         return y == dt.getFullYear() &&
2012             m == dt.getMonth() + 1 &&
2013             d == dt.getDate() &&
2014             h == dt.getHours() &&
2015             i == dt.getMinutes() &&
2016             s == dt.getSeconds() &&
2017             ms == dt.getMilliseconds();
2018     },
2019
2020     
2021     parse : function(input, format, strict) {
2022         var p = utilDate.parseFunctions;
2023         if (p[format] == null) {
2024             utilDate.createParser(format);
2025         }
2026         return p[format](input, Ext.isDefined(strict) ? strict : utilDate.useStrict);
2027     },
2028
2029     
2030     parseDate: function(input, format, strict){
2031         return utilDate.parse(input, format, strict);
2032     },
2033
2034
2035     
2036     getFormatCode : function(character) {
2037         var f = utilDate.formatCodes[character];
2038
2039         if (f) {
2040           f = typeof f == 'function'? f() : f;
2041           utilDate.formatCodes[character] = f; 
2042         }
2043
2044         
2045         return f || ("'" + Ext.String.escape(character) + "'");
2046     },
2047
2048     
2049     createFormat : function(format) {
2050         var code = [],
2051             special = false,
2052             ch = '';
2053
2054         for (var i = 0; i < format.length; ++i) {
2055             ch = format.charAt(i);
2056             if (!special && ch == "\\") {
2057                 special = true;
2058             } else if (special) {
2059                 special = false;
2060                 code.push("'" + Ext.String.escape(ch) + "'");
2061             } else {
2062                 code.push(utilDate.getFormatCode(ch));
2063             }
2064         }
2065         utilDate.formatFunctions[format] = Ext.functionFactory("return " + code.join('+'));
2066     },
2067
2068     
2069     createParser : (function() {
2070         var code = [
2071             "var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
2072                 "def = Ext.Date.defaults,",
2073                 "results = String(input).match(Ext.Date.parseRegexes[{0}]);", 
2074
2075             "if(results){",
2076                 "{1}",
2077
2078                 "if(u != null){", 
2079                     "v = new Date(u * 1000);", 
2080                 "}else{",
2081                     
2082                     
2083                     
2084                     "dt = Ext.Date.clearTime(new Date);",
2085
2086                     
2087                     "y = Ext.Number.from(y, Ext.Number.from(def.y, dt.getFullYear()));",
2088                     "m = Ext.Number.from(m, Ext.Number.from(def.m - 1, dt.getMonth()));",
2089                     "d = Ext.Number.from(d, Ext.Number.from(def.d, dt.getDate()));",
2090
2091                     
2092                     "h  = Ext.Number.from(h, Ext.Number.from(def.h, dt.getHours()));",
2093                     "i  = Ext.Number.from(i, Ext.Number.from(def.i, dt.getMinutes()));",
2094                     "s  = Ext.Number.from(s, Ext.Number.from(def.s, dt.getSeconds()));",
2095                     "ms = Ext.Number.from(ms, Ext.Number.from(def.ms, dt.getMilliseconds()));",
2096
2097                     "if(z >= 0 && y >= 0){",
2098                         
2099                         
2100
2101                         
2102                         
2103                         "v = Ext.Date.add(new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);",
2104
2105                         
2106                         "v = !strict? v : (strict === true && (z <= 364 || (Ext.Date.isLeapYear(v) && z <= 365))? Ext.Date.add(v, Ext.Date.DAY, z) : null);",
2107                     "}else if(strict === true && !Ext.Date.isValid(y, m + 1, d, h, i, s, ms)){", 
2108                         "v = null;", 
2109                     "}else{",
2110                         
2111                         
2112                         "v = Ext.Date.add(new Date(y < 100 ? 100 : y, m, d, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);",
2113                     "}",
2114                 "}",
2115             "}",
2116
2117             "if(v){",
2118                 
2119                 "if(zz != null){",
2120                     
2121                     "v = Ext.Date.add(v, Ext.Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
2122                 "}else if(o){",
2123                     
2124                     "v = Ext.Date.add(v, Ext.Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
2125                 "}",
2126             "}",
2127
2128             "return v;"
2129         ].join('\n');
2130
2131         return function(format) {
2132             var regexNum = utilDate.parseRegexes.length,
2133                 currentGroup = 1,
2134                 calc = [],
2135                 regex = [],
2136                 special = false,
2137                 ch = "";
2138
2139             for (var i = 0; i < format.length; ++i) {
2140                 ch = format.charAt(i);
2141                 if (!special && ch == "\\") {
2142                     special = true;
2143                 } else if (special) {
2144                     special = false;
2145                     regex.push(Ext.String.escape(ch));
2146                 } else {
2147                     var obj = utilDate.formatCodeToRegex(ch, currentGroup);
2148                     currentGroup += obj.g;
2149                     regex.push(obj.s);
2150                     if (obj.g && obj.c) {
2151                         calc.push(obj.c);
2152                     }
2153                 }
2154             }
2155
2156             utilDate.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", 'i');
2157             utilDate.parseFunctions[format] = Ext.functionFactory("input", "strict", xf(code, regexNum, calc.join('')));
2158         };
2159     })(),
2160
2161     
2162     parseCodes : {
2163         
2164         d: {
2165             g:1,
2166             c:"d = parseInt(results[{0}], 10);\n",
2167             s:"(\\d{2})" 
2168         },
2169         j: {
2170             g:1,
2171             c:"d = parseInt(results[{0}], 10);\n",
2172             s:"(\\d{1,2})" 
2173         },
2174         D: function() {
2175             for (var a = [], i = 0; i < 7; a.push(utilDate.getShortDayName(i)), ++i); 
2176             return {
2177                 g:0,
2178                 c:null,
2179                 s:"(?:" + a.join("|") +")"
2180             };
2181         },
2182         l: function() {
2183             return {
2184                 g:0,
2185                 c:null,
2186                 s:"(?:" + utilDate.dayNames.join("|") + ")"
2187             };
2188         },
2189         N: {
2190             g:0,
2191             c:null,
2192             s:"[1-7]" 
2193         },
2194         S: {
2195             g:0,
2196             c:null,
2197             s:"(?:st|nd|rd|th)"
2198         },
2199         w: {
2200             g:0,
2201             c:null,
2202             s:"[0-6]" 
2203         },
2204         z: {
2205             g:1,
2206             c:"z = parseInt(results[{0}], 10);\n",
2207             s:"(\\d{1,3})" 
2208         },
2209         W: {
2210             g:0,
2211             c:null,
2212             s:"(?:\\d{2})" 
2213         },
2214         F: function() {
2215             return {
2216                 g:1,
2217                 c:"m = parseInt(Ext.Date.getMonthNumber(results[{0}]), 10);\n", 
2218                 s:"(" + utilDate.monthNames.join("|") + ")"
2219             };
2220         },
2221         M: function() {
2222             for (var a = [], i = 0; i < 12; a.push(utilDate.getShortMonthName(i)), ++i); 
2223             return Ext.applyIf({
2224                 s:"(" + a.join("|") + ")"
2225             }, utilDate.formatCodeToRegex("F"));
2226         },
2227         m: {
2228             g:1,
2229             c:"m = parseInt(results[{0}], 10) - 1;\n",
2230             s:"(\\d{2})" 
2231         },
2232         n: {
2233             g:1,
2234             c:"m = parseInt(results[{0}], 10) - 1;\n",
2235             s:"(\\d{1,2})" 
2236         },
2237         t: {
2238             g:0,
2239             c:null,
2240             s:"(?:\\d{2})" 
2241         },
2242         L: {
2243             g:0,
2244             c:null,
2245             s:"(?:1|0)"
2246         },
2247         o: function() {
2248             return utilDate.formatCodeToRegex("Y");
2249         },
2250         Y: {
2251             g:1,
2252             c:"y = parseInt(results[{0}], 10);\n",
2253             s:"(\\d{4})" 
2254         },
2255         y: {
2256             g:1,
2257             c:"var ty = parseInt(results[{0}], 10);\n"
2258                 + "y = ty > Ext.Date.y2kYear ? 1900 + ty : 2000 + ty;\n", 
2259             s:"(\\d{1,2})"
2260         },
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         A: {
2270             g:1,
2271             c:"if (/(am)/i.test(results[{0}])) {\n"
2272                 + "if (!h || h == 12) { h = 0; }\n"
2273                 + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
2274             s:"(AM|PM|am|pm)"
2275         },
2276         g: function() {
2277             return utilDate.formatCodeToRegex("G");
2278         },
2279         G: {
2280             g:1,
2281             c:"h = parseInt(results[{0}], 10);\n",
2282             s:"(\\d{1,2})" 
2283         },
2284         h: function() {
2285             return utilDate.formatCodeToRegex("H");
2286         },
2287         H: {
2288             g:1,
2289             c:"h = parseInt(results[{0}], 10);\n",
2290             s:"(\\d{2})" 
2291         },
2292         i: {
2293             g:1,
2294             c:"i = parseInt(results[{0}], 10);\n",
2295             s:"(\\d{2})" 
2296         },
2297         s: {
2298             g:1,
2299             c:"s = parseInt(results[{0}], 10);\n",
2300             s:"(\\d{2})" 
2301         },
2302         u: {
2303             g:1,
2304             c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
2305             s:"(\\d+)" 
2306         },
2307         O: {
2308             g:1,
2309             c:[
2310                 "o = results[{0}];",
2311                 "var sn = o.substring(0,1),", 
2312                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
2313                     "mn = o.substring(3,5) % 60;", 
2314                 "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" 
2315             ].join("\n"),
2316             s: "([+\-]\\d{4})" 
2317         },
2318         P: {
2319             g:1,
2320             c:[
2321                 "o = results[{0}];",
2322                 "var sn = o.substring(0,1),", 
2323                     "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
2324                     "mn = o.substring(4,6) % 60;", 
2325                 "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" 
2326             ].join("\n"),
2327             s: "([+\-]\\d{2}:\\d{2})" 
2328         },
2329         T: {
2330             g:0,
2331             c:null,
2332             s:"[A-Z]{1,4}" 
2333         },
2334         Z: {
2335             g:1,
2336             c:"zz = results[{0}] * 1;\n" 
2337                   + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
2338             s:"([+\-]?\\d{1,5})" 
2339         },
2340         c: function() {
2341             var calc = [],
2342                 arr = [
2343                     utilDate.formatCodeToRegex("Y", 1), 
2344                     utilDate.formatCodeToRegex("m", 2), 
2345                     utilDate.formatCodeToRegex("d", 3), 
2346                     utilDate.formatCodeToRegex("h", 4), 
2347                     utilDate.formatCodeToRegex("i", 5), 
2348                     utilDate.formatCodeToRegex("s", 6), 
2349                     {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
2350                     {c:[ 
2351                         "if(results[8]) {", 
2352                             "if(results[8] == 'Z'){",
2353                                 "zz = 0;", 
2354                             "}else if (results[8].indexOf(':') > -1){",
2355                                 utilDate.formatCodeToRegex("P", 8).c, 
2356                             "}else{",
2357                                 utilDate.formatCodeToRegex("O", 8).c, 
2358                             "}",
2359                         "}"
2360                     ].join('\n')}
2361                 ];
2362
2363             for (var i = 0, l = arr.length; i < l; ++i) {
2364                 calc.push(arr[i].c);
2365             }
2366
2367             return {
2368                 g:1,
2369                 c:calc.join(""),
2370                 s:[
2371                     arr[0].s, 
2372                     "(?:", "-", arr[1].s, 
2373                         "(?:", "-", arr[2].s, 
2374                             "(?:",
2375                                 "(?:T| )?", 
2376                                 arr[3].s, ":", arr[4].s,  
2377                                 "(?::", arr[5].s, ")?", 
2378                                 "(?:(?:\\.|,)(\\d+))?", 
2379                                 "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
2380                             ")?",
2381                         ")?",
2382                     ")?"
2383                 ].join("")
2384             };
2385         },
2386         U: {
2387             g:1,
2388             c:"u = parseInt(results[{0}], 10);\n",
2389             s:"(-?\\d+)" 
2390         }
2391     },
2392
2393     
2394     
2395     dateFormat: function(date, format) {
2396         return utilDate.format(date, format);
2397     },
2398
2399     
2400     format: function(date, format) {
2401         if (utilDate.formatFunctions[format] == null) {
2402             utilDate.createFormat(format);
2403         }
2404         var result = utilDate.formatFunctions[format].call(date);
2405         return result + '';
2406     },
2407
2408     
2409     getTimezone : function(date) {
2410         
2411         
2412         
2413         
2414         
2415         
2416         
2417         
2418         
2419         
2420         
2421         
2422         return date.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
2423     },
2424
2425     
2426     getGMTOffset : function(date, colon) {
2427         var offset = date.getTimezoneOffset();
2428         return (offset > 0 ? "-" : "+")
2429             + Ext.String.leftPad(Math.floor(Math.abs(offset) / 60), 2, "0")
2430             + (colon ? ":" : "")
2431             + Ext.String.leftPad(Math.abs(offset % 60), 2, "0");
2432     },
2433
2434     
2435     getDayOfYear: function(date) {
2436         var num = 0,
2437             d = Ext.Date.clone(date),
2438             m = date.getMonth(),
2439             i;
2440
2441         for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
2442             num += utilDate.getDaysInMonth(d);
2443         }
2444         return num + date.getDate() - 1;
2445     },
2446
2447     
2448     getWeekOfYear : (function() {
2449         
2450         var ms1d = 864e5, 
2451             ms7d = 7 * ms1d; 
2452
2453         return function(date) { 
2454             var DC3 = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate() + 3) / ms1d, 
2455                 AWN = Math.floor(DC3 / 7), 
2456                 Wyr = new Date(AWN * ms7d).getUTCFullYear();
2457
2458             return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
2459         };
2460     })(),
2461
2462     
2463     isLeapYear : function(date) {
2464         var year = date.getFullYear();
2465         return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
2466     },
2467
2468     
2469     getFirstDayOfMonth : function(date) {
2470         var day = (date.getDay() - (date.getDate() - 1)) % 7;
2471         return (day < 0) ? (day + 7) : day;
2472     },
2473
2474     
2475     getLastDayOfMonth : function(date) {
2476         return utilDate.getLastDateOfMonth(date).getDay();
2477     },
2478
2479
2480     
2481     getFirstDateOfMonth : function(date) {
2482         return new Date(date.getFullYear(), date.getMonth(), 1);
2483     },
2484
2485     
2486     getLastDateOfMonth : function(date) {
2487         return new Date(date.getFullYear(), date.getMonth(), utilDate.getDaysInMonth(date));
2488     },
2489
2490     
2491     getDaysInMonth: (function() {
2492         var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
2493
2494         return function(date) { 
2495             var m = date.getMonth();
2496
2497             return m == 1 && utilDate.isLeapYear(date) ? 29 : daysInMonth[m];
2498         };
2499     })(),
2500
2501     
2502     getSuffix : function(date) {
2503         switch (date.getDate()) {
2504             case 1:
2505             case 21:
2506             case 31:
2507                 return "st";
2508             case 2:
2509             case 22:
2510                 return "nd";
2511             case 3:
2512             case 23:
2513                 return "rd";
2514             default:
2515                 return "th";
2516         }
2517     },
2518
2519     
2520     clone : function(date) {
2521         return new Date(date.getTime());
2522     },
2523
2524     
2525     isDST : function(date) {
2526         
2527         
2528         return new Date(date.getFullYear(), 0, 1).getTimezoneOffset() != date.getTimezoneOffset();
2529     },
2530
2531     
2532     clearTime : function(date, clone) {
2533         if (clone) {
2534             return Ext.Date.clearTime(Ext.Date.clone(date));
2535         }
2536
2537         
2538         var d = date.getDate();
2539
2540         
2541         date.setHours(0);
2542         date.setMinutes(0);
2543         date.setSeconds(0);
2544         date.setMilliseconds(0);
2545
2546         if (date.getDate() != d) { 
2547             
2548             
2549
2550             
2551             for (var hr = 1, c = utilDate.add(date, Ext.Date.HOUR, hr); c.getDate() != d; hr++, c = utilDate.add(date, Ext.Date.HOUR, hr));
2552
2553             date.setDate(d);
2554             date.setHours(c.getHours());
2555         }
2556
2557         return date;
2558     },
2559
2560     
2561     add : function(date, interval, value) {
2562         var d = Ext.Date.clone(date),
2563             Date = Ext.Date;
2564         if (!interval || value === 0) return d;
2565
2566         switch(interval.toLowerCase()) {
2567             case Ext.Date.MILLI:
2568                 d.setMilliseconds(d.getMilliseconds() + value);
2569                 break;
2570             case Ext.Date.SECOND:
2571                 d.setSeconds(d.getSeconds() + value);
2572                 break;
2573             case Ext.Date.MINUTE:
2574                 d.setMinutes(d.getMinutes() + value);
2575                 break;
2576             case Ext.Date.HOUR:
2577                 d.setHours(d.getHours() + value);
2578                 break;
2579             case Ext.Date.DAY:
2580                 d.setDate(d.getDate() + value);
2581                 break;
2582             case Ext.Date.MONTH:
2583                 var day = date.getDate();
2584                 if (day > 28) {
2585                     day = Math.min(day, Ext.Date.getLastDateOfMonth(Ext.Date.add(Ext.Date.getFirstDateOfMonth(date), 'mo', value)).getDate());
2586                 }
2587                 d.setDate(day);
2588                 d.setMonth(date.getMonth() + value);
2589                 break;
2590             case Ext.Date.YEAR:
2591                 d.setFullYear(date.getFullYear() + value);
2592                 break;
2593         }
2594         return d;
2595     },
2596
2597     
2598     between : function(date, start, end) {
2599         var t = date.getTime();
2600         return start.getTime() <= t && t <= end.getTime();
2601     },
2602
2603     
2604     compat: function() {
2605         var nativeDate = window.Date,
2606             p, u,
2607             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'],
2608             proto = ['dateFormat', 'format', 'getTimezone', 'getGMTOffset', 'getDayOfYear', 'getWeekOfYear', 'isLeapYear', 'getFirstDayOfMonth', 'getLastDayOfMonth', 'getDaysInMonth', 'getSuffix', 'clone', 'isDST', 'clearTime', 'add', 'between'];
2609
2610         
2611         Ext.Array.forEach(statics, function(s) {
2612             nativeDate[s] = utilDate[s];
2613         });
2614
2615         
2616         Ext.Array.forEach(proto, function(s) {
2617             nativeDate.prototype[s] = function() {
2618                 var args = Array.prototype.slice.call(arguments);
2619                 args.unshift(this);
2620                 return utilDate[s].apply(utilDate, args);
2621             };
2622         });
2623     }
2624 };
2625
2626 var utilDate = Ext.Date;
2627
2628 })();
2629
2630
2631 (function(flexSetter) {
2632
2633 var Base = Ext.Base = function() {};
2634     Base.prototype = {
2635         $className: 'Ext.Base',
2636
2637         $class: Base,
2638
2639         
2640         self: Base,
2641
2642         
2643         constructor: function() {
2644             return this;
2645         },
2646
2647         
2648         initConfig: function(config) {
2649             if (!this.$configInited) {
2650                 this.config = Ext.Object.merge({}, this.config || {}, config || {});
2651
2652                 this.applyConfig(this.config);
2653
2654                 this.$configInited = true;
2655             }
2656
2657             return this;
2658         },
2659
2660         
2661         setConfig: function(config) {
2662             this.applyConfig(config || {});
2663
2664             return this;
2665         },
2666
2667         
2668         applyConfig: flexSetter(function(name, value) {
2669             var setter = 'set' + Ext.String.capitalize(name);
2670
2671             if (typeof this[setter] === 'function') {
2672                 this[setter].call(this, value);
2673             }
2674
2675             return this;
2676         }),
2677
2678         
2679         callParent: function(args) {
2680             var method = this.callParent.caller,
2681                 parentClass, methodName;
2682
2683             if (!method.$owner) {
2684                 if (!method.caller) {
2685                     Ext.Error.raise({
2686                         sourceClass: Ext.getClassName(this),
2687                         sourceMethod: "callParent",
2688                         msg: "Attempting to call a protected method from the public scope, which is not allowed"
2689                     });
2690                 }
2691
2692                 method = method.caller;
2693             }
2694
2695             parentClass = method.$owner.superclass;
2696             methodName = method.$name;
2697
2698             if (!(methodName in parentClass)) {
2699                 Ext.Error.raise({
2700                     sourceClass: Ext.getClassName(this),
2701                     sourceMethod: methodName,
2702                     msg: "this.callParent() was called but there's no such method (" + methodName +
2703                          ") found in the parent class (" + (Ext.getClassName(parentClass) || 'Object') + ")"
2704                  });
2705             }
2706
2707             return parentClass[methodName].apply(this, args || []);
2708         },
2709
2710
2711         
2712         statics: function() {
2713             var method = this.statics.caller,
2714                 self = this.self;
2715
2716             if (!method) {
2717                 return self;
2718             }
2719
2720             return method.$owner;
2721         },
2722
2723         
2724         callOverridden: function(args) {
2725             var method = this.callOverridden.caller;
2726
2727             if (!method.$owner) {
2728                 Ext.Error.raise({
2729                     sourceClass: Ext.getClassName(this),
2730                     sourceMethod: "callOverridden",
2731                     msg: "Attempting to call a protected method from the public scope, which is not allowed"
2732                 });
2733             }
2734
2735             if (!method.$previous) {
2736                 Ext.Error.raise({
2737                     sourceClass: Ext.getClassName(this),
2738                     sourceMethod: "callOverridden",
2739                     msg: "this.callOverridden was called in '" + method.$name +
2740                          "' but this method has never been overridden"
2741                  });
2742             }
2743
2744             return method.$previous.apply(this, args || []);
2745         },
2746
2747         destroy: function() {}
2748     };
2749
2750     
2751     Ext.apply(Ext.Base, {
2752         
2753         create: function() {
2754             return Ext.create.apply(Ext, [this].concat(Array.prototype.slice.call(arguments, 0)));
2755         },
2756
2757         
2758         own: flexSetter(function(name, value) {
2759             if (typeof value === 'function') {
2760                 this.ownMethod(name, value);
2761             }
2762             else {
2763                 this.prototype[name] = value;
2764             }
2765         }),
2766
2767         
2768         ownMethod: function(name, fn) {
2769             var originalFn;
2770
2771             if (fn.$owner !== undefined && fn !== Ext.emptyFn) {
2772                 originalFn = fn;
2773
2774                 fn = function() {
2775                     return originalFn.apply(this, arguments);
2776                 };
2777             }
2778
2779             var className;
2780             className = Ext.getClassName(this);
2781             if (className) {
2782                 fn.displayName = className + '#' + name;
2783             }
2784             fn.$owner = this;
2785             fn.$name = name;
2786
2787             this.prototype[name] = fn;
2788         },
2789
2790         
2791         addStatics: function(members) {
2792             for (var name in members) {
2793                 if (members.hasOwnProperty(name)) {
2794                     this[name] = members[name];
2795                 }
2796             }
2797
2798             return this;
2799         },
2800
2801         
2802         implement: function(members) {
2803             var prototype = this.prototype,
2804                 name, i, member, previous;
2805             var className = Ext.getClassName(this);
2806             for (name in members) {
2807                 if (members.hasOwnProperty(name)) {
2808                     member = members[name];
2809
2810                     if (typeof member === 'function') {
2811                         member.$owner = this;
2812                         member.$name = name;
2813                         if (className) {
2814                             member.displayName = className + '#' + name;
2815                         }
2816                     }
2817
2818                     prototype[name] = member;
2819                 }
2820             }
2821
2822             if (Ext.enumerables) {
2823                 var enumerables = Ext.enumerables;
2824
2825                 for (i = enumerables.length; i--;) {
2826                     name = enumerables[i];
2827
2828                     if (members.hasOwnProperty(name)) {
2829                         member = members[name];
2830                         member.$owner = this;
2831                         member.$name = name;
2832                         prototype[name] = member;
2833                     }
2834                 }
2835             }
2836         },
2837
2838         
2839         borrow: function(fromClass, members) {
2840             var fromPrototype = fromClass.prototype,
2841                 i, ln, member;
2842
2843             members = Ext.Array.from(members);
2844
2845             for (i = 0, ln = members.length; i < ln; i++) {
2846                 member = members[i];
2847
2848                 this.own(member, fromPrototype[member]);
2849             }
2850
2851             return this;
2852         },
2853
2854         
2855         override: function(members) {
2856             var prototype = this.prototype,
2857                 name, i, member, previous;
2858
2859             for (name in members) {
2860                 if (members.hasOwnProperty(name)) {
2861                     member = members[name];
2862
2863                     if (typeof member === 'function') {
2864                         if (typeof prototype[name] === 'function') {
2865                             previous = prototype[name];
2866                             member.$previous = previous;
2867                         }
2868
2869                         this.ownMethod(name, member);
2870                     }
2871                     else {
2872                         prototype[name] = member;
2873                     }
2874                 }
2875             }
2876
2877             if (Ext.enumerables) {
2878                 var enumerables = Ext.enumerables;
2879
2880                 for (i = enumerables.length; i--;) {
2881                     name = enumerables[i];
2882
2883                     if (members.hasOwnProperty(name)) {
2884                         if (prototype[name] !== undefined) {
2885                             previous = prototype[name];
2886                             members[name].$previous = previous;
2887                         }
2888
2889                         this.ownMethod(name, members[name]);
2890                     }
2891                 }
2892             }
2893
2894             return this;
2895         },
2896
2897         
2898         mixin: flexSetter(function(name, cls) {
2899             var mixin = cls.prototype,
2900                 my = this.prototype,
2901                 i, fn;
2902
2903             for (i in mixin) {
2904                 if (mixin.hasOwnProperty(i)) {
2905                     if (my[i] === undefined) {
2906                         if (typeof mixin[i] === 'function') {
2907                             fn = mixin[i];
2908
2909                             if (fn.$owner === undefined) {
2910                                 this.ownMethod(i, fn);
2911                             }
2912                             else {
2913                                 my[i] = fn;
2914                             }
2915                         }
2916                         else {
2917                             my[i] = mixin[i];
2918                         }
2919                     }
2920                     else if (i === 'config' && my.config && mixin.config) {
2921                         Ext.Object.merge(my.config, mixin.config);
2922                     }
2923                 }
2924             }
2925
2926             if (my.mixins === undefined) {
2927                 my.mixins = {};
2928             }
2929
2930             my.mixins[name] = mixin;
2931         }),
2932
2933         
2934         getName: function() {
2935             return Ext.getClassName(this);
2936         },
2937
2938         
2939         createAlias: flexSetter(function(alias, origin) {
2940             this.prototype[alias] = this.prototype[origin];
2941         })
2942     });
2943
2944 })(Ext.Function.flexSetter);
2945
2946
2947 (function() {
2948
2949     var Class,
2950         Base = Ext.Base,
2951         baseStaticProperties = [],
2952         baseStaticProperty;
2953
2954     for (baseStaticProperty in Base) {
2955         if (Base.hasOwnProperty(baseStaticProperty)) {
2956             baseStaticProperties.push(baseStaticProperty);
2957         }
2958     }
2959
2960     
2961     Ext.Class = Class = function(newClass, classData, onClassCreated) {
2962         if (typeof newClass !== 'function') {
2963             onClassCreated = classData;
2964             classData = newClass;
2965             newClass = function() {
2966                 return this.constructor.apply(this, arguments);
2967             };
2968         }
2969
2970         if (!classData) {
2971             classData = {};
2972         }
2973
2974         var preprocessorStack = classData.preprocessors || Class.getDefaultPreprocessors(),
2975             registeredPreprocessors = Class.getPreprocessors(),
2976             index = 0,
2977             preprocessors = [],
2978             preprocessor, preprocessors, staticPropertyName, process, i, j, ln;
2979
2980         for (i = 0, ln = baseStaticProperties.length; i < ln; i++) {
2981             staticPropertyName = baseStaticProperties[i];
2982             newClass[staticPropertyName] = Base[staticPropertyName];
2983         }
2984
2985         delete classData.preprocessors;
2986
2987         for (j = 0, ln = preprocessorStack.length; j < ln; j++) {
2988             preprocessor = preprocessorStack[j];
2989
2990             if (typeof preprocessor === 'string') {
2991                 preprocessor = registeredPreprocessors[preprocessor];
2992
2993                 if (!preprocessor.always) {
2994                     if (classData.hasOwnProperty(preprocessor.name)) {
2995                         preprocessors.push(preprocessor.fn);
2996                     }
2997                 }
2998                 else {
2999                     preprocessors.push(preprocessor.fn);
3000                 }
3001             }
3002             else {
3003                 preprocessors.push(preprocessor);
3004             }
3005         }
3006
3007         classData.onClassCreated = onClassCreated;
3008
3009         classData.onBeforeClassCreated = function(cls, data) {
3010             onClassCreated = data.onClassCreated;
3011
3012             delete data.onBeforeClassCreated;
3013             delete data.onClassCreated;
3014
3015             cls.implement(data);
3016
3017             if (onClassCreated) {
3018                 onClassCreated.call(cls, cls);
3019             }
3020         };
3021
3022         process = function(cls, data) {
3023             preprocessor = preprocessors[index++];
3024
3025             if (!preprocessor) {
3026                 data.onBeforeClassCreated.apply(this, arguments);
3027                 return;
3028             }
3029
3030             if (preprocessor.call(this, cls, data, process) !== false) {
3031                 process.apply(this, arguments);
3032             }
3033         };
3034
3035         process.call(Class, newClass, classData);
3036
3037         return newClass;
3038     };
3039
3040     Ext.apply(Class, {
3041
3042         
3043         preprocessors: {},
3044
3045         
3046         registerPreprocessor: function(name, fn, always) {
3047             this.preprocessors[name] = {
3048                 name: name,
3049                 always: always ||  false,
3050                 fn: fn
3051             };
3052
3053             return this;
3054         },
3055
3056         
3057         getPreprocessor: function(name) {
3058             return this.preprocessors[name];
3059         },
3060
3061         getPreprocessors: function() {
3062             return this.preprocessors;
3063         },
3064
3065         
3066         getDefaultPreprocessors: function() {
3067             return this.defaultPreprocessors || [];
3068         },
3069
3070         
3071         setDefaultPreprocessors: function(preprocessors) {
3072             this.defaultPreprocessors = Ext.Array.from(preprocessors);
3073
3074             return this;
3075         },
3076
3077         
3078         setDefaultPreprocessorPosition: function(name, offset, relativeName) {
3079             var defaultPreprocessors = this.defaultPreprocessors,
3080                 index;
3081
3082             if (typeof offset === 'string') {
3083                 if (offset === 'first') {
3084                     defaultPreprocessors.unshift(name);
3085
3086                     return this;
3087                 }
3088                 else if (offset === 'last') {
3089                     defaultPreprocessors.push(name);
3090
3091                     return this;
3092                 }
3093
3094                 offset = (offset === 'after') ? 1 : -1;
3095             }
3096
3097             index = Ext.Array.indexOf(defaultPreprocessors, relativeName);
3098
3099             if (index !== -1) {
3100                 defaultPreprocessors.splice(Math.max(0, index + offset), 0, name);
3101             }
3102
3103             return this;
3104         }
3105     });
3106
3107     Class.registerPreprocessor('extend', function(cls, data) {
3108         var extend = data.extend,
3109             base = Ext.Base,
3110             basePrototype = base.prototype,
3111             prototype = function() {},
3112             parent, i, k, ln, staticName, parentStatics,
3113             parentPrototype, clsPrototype;
3114
3115         if (extend && extend !== Object) {
3116             parent = extend;
3117         }
3118         else {
3119             parent = base;
3120         }
3121
3122         parentPrototype = parent.prototype;
3123
3124         prototype.prototype = parentPrototype;
3125         clsPrototype = cls.prototype = new prototype();
3126
3127         if (!('$class' in parent)) {
3128             for (i in basePrototype) {
3129                 if (!parentPrototype[i]) {
3130                     parentPrototype[i] = basePrototype[i];
3131                 }
3132             }
3133         }
3134
3135         clsPrototype.self = cls;
3136
3137         cls.superclass = clsPrototype.superclass = parentPrototype;
3138
3139         delete data.extend;
3140
3141         
3142         parentStatics = parentPrototype.$inheritableStatics;
3143
3144         if (parentStatics) {
3145             for (k = 0, ln = parentStatics.length; k < ln; k++) {
3146                 staticName = parentStatics[k];
3147
3148                 if (!cls.hasOwnProperty(staticName)) {
3149                     cls[staticName] = parent[staticName];
3150                 }
3151             }
3152         }
3153
3154         
3155         if (parentPrototype.config) {
3156             clsPrototype.config = Ext.Object.merge({}, parentPrototype.config);
3157         }
3158         else {
3159             clsPrototype.config = {};
3160         }
3161
3162         if (clsPrototype.$onExtended) {
3163             clsPrototype.$onExtended.call(cls, cls, data);
3164         }
3165
3166         if (data.onClassExtended) {
3167             clsPrototype.$onExtended = data.onClassExtended;
3168             delete data.onClassExtended;
3169         }
3170
3171     }, true);
3172
3173     Class.registerPreprocessor('statics', function(cls, data) {
3174         var statics = data.statics,
3175             name;
3176
3177         for (name in statics) {
3178             if (statics.hasOwnProperty(name)) {
3179                 cls[name] = statics[name];
3180             }
3181         }
3182
3183         delete data.statics;
3184     });
3185
3186     Class.registerPreprocessor('inheritableStatics', function(cls, data) {
3187         var statics = data.inheritableStatics,
3188             inheritableStatics,
3189             prototype = cls.prototype,
3190             name;
3191
3192         inheritableStatics = prototype.$inheritableStatics;
3193
3194         if (!inheritableStatics) {
3195             inheritableStatics = prototype.$inheritableStatics = [];
3196         }
3197
3198         for (name in statics) {
3199             if (statics.hasOwnProperty(name)) {
3200                 cls[name] = statics[name];
3201                 inheritableStatics.push(name);
3202             }
3203         }
3204
3205         delete data.inheritableStatics;
3206     });
3207
3208     Class.registerPreprocessor('mixins', function(cls, data) {
3209         cls.mixin(data.mixins);
3210
3211         delete data.mixins;
3212     });
3213
3214     Class.registerPreprocessor('config', function(cls, data) {
3215         var prototype = cls.prototype;
3216
3217         Ext.Object.each(data.config, function(name) {
3218             var cName = name.charAt(0).toUpperCase() + name.substr(1),
3219                 pName = name,
3220                 apply = 'apply' + cName,
3221                 setter = 'set' + cName,
3222                 getter = 'get' + cName;
3223
3224             if (!(apply in prototype) && !data.hasOwnProperty(apply)) {
3225                 data[apply] = function(val) {
3226                     return val;
3227                 };
3228             }
3229
3230             if (!(setter in prototype) && !data.hasOwnProperty(setter)) {
3231                 data[setter] = function(val) {
3232                     var ret = this[apply].call(this, val, this[pName]);
3233
3234                     if (ret !== undefined) {
3235                         this[pName] = ret;
3236                     }
3237
3238                     return this;
3239                 };
3240             }
3241
3242             if (!(getter in prototype) && !data.hasOwnProperty(getter)) {
3243                 data[getter] = function() {
3244                     return this[pName];
3245                 };
3246             }
3247         });
3248
3249         Ext.Object.merge(prototype.config, data.config);
3250         delete data.config;
3251     });
3252
3253     Class.setDefaultPreprocessors(['extend', 'statics', 'inheritableStatics', 'mixins', 'config']);
3254
3255     
3256     Ext.extend = function(subclass, superclass, members) {
3257         if (arguments.length === 2 && Ext.isObject(superclass)) {
3258             members = superclass;
3259             superclass = subclass;
3260             subclass = null;
3261         }
3262
3263         var cls;
3264
3265         if (!superclass) {
3266             Ext.Error.raise("Attempting to extend from a class which has not been loaded on the page.");
3267         }
3268
3269         members.extend = superclass;
3270         members.preprocessors = ['extend', 'mixins', 'config', 'statics'];
3271
3272         if (subclass) {
3273             cls = new Class(subclass, members);
3274         }
3275         else {
3276             cls = new Class(members);
3277         }
3278
3279         cls.prototype.override = function(o) {
3280             for (var m in o) {
3281                 if (o.hasOwnProperty(m)) {
3282                     this[m] = o[m];
3283                 }
3284             }
3285         };
3286
3287         return cls;
3288     };
3289
3290 })();
3291
3292
3293 (function(Class, alias) {
3294
3295     var slice = Array.prototype.slice;
3296
3297     var Manager = Ext.ClassManager = {
3298
3299         
3300         classes: {},
3301
3302         
3303         existCache: {},
3304
3305         
3306         namespaceRewrites: [{
3307             from: 'Ext.',
3308             to: Ext
3309         }],
3310
3311         
3312         maps: {
3313             alternateToName: {},
3314             aliasToName: {},
3315             nameToAliases: {}
3316         },
3317
3318         
3319         enableNamespaceParseCache: true,
3320
3321         
3322         namespaceParseCache: {},
3323
3324         
3325         instantiators: [],
3326
3327         
3328         instantiationCounts: {},
3329
3330         
3331         isCreated: function(className) {
3332             var i, ln, part, root, parts;
3333
3334             if (typeof className !== 'string' || className.length < 1) {
3335                 Ext.Error.raise({
3336                     sourceClass: "Ext.ClassManager",
3337                     sourceMethod: "exist",
3338                     msg: "Invalid classname, must be a string and must not be empty"
3339                 });
3340             }
3341
3342             if (this.classes.hasOwnProperty(className) || this.existCache.hasOwnProperty(className)) {
3343                 return true;
3344             }
3345
3346             root = Ext.global;
3347             parts = this.parseNamespace(className);
3348
3349             for (i = 0, ln = parts.length; i < ln; i++) {
3350                 part = parts[i];
3351
3352                 if (typeof part !== 'string') {
3353                     root = part;
3354                 } else {
3355                     if (!root || !root[part]) {
3356                         return false;
3357                     }
3358
3359                     root = root[part];
3360                 }
3361             }
3362
3363             Ext.Loader.historyPush(className);
3364
3365             this.existCache[className] = true;
3366
3367             return true;
3368         },
3369
3370         
3371         parseNamespace: function(namespace) {
3372             if (typeof namespace !== 'string') {
3373                 Ext.Error.raise({
3374                     sourceClass: "Ext.ClassManager",
3375                     sourceMethod: "parseNamespace",
3376                     msg: "Invalid namespace, must be a string"
3377                 });
3378             }
3379
3380             var cache = this.namespaceParseCache;
3381
3382             if (this.enableNamespaceParseCache) {
3383                 if (cache.hasOwnProperty(namespace)) {
3384                     return cache[namespace];
3385                 }
3386             }
3387
3388             var parts = [],
3389                 rewrites = this.namespaceRewrites,
3390                 rewrite, from, to, i, ln, root = Ext.global;
3391
3392             for (i = 0, ln = rewrites.length; i < ln; i++) {
3393                 rewrite = rewrites[i];
3394                 from = rewrite.from;
3395                 to = rewrite.to;
3396
3397                 if (namespace === from || namespace.substring(0, from.length) === from) {
3398                     namespace = namespace.substring(from.length);
3399
3400                     if (typeof to !== 'string') {
3401                         root = to;
3402                     } else {
3403                         parts = parts.concat(to.split('.'));
3404                     }
3405
3406                     break;
3407                 }
3408             }
3409
3410             parts.push(root);
3411
3412             parts = parts.concat(namespace.split('.'));
3413
3414             if (this.enableNamespaceParseCache) {
3415                 cache[namespace] = parts;
3416             }
3417
3418             return parts;
3419         },
3420
3421         
3422         setNamespace: function(name, value) {
3423             var root = Ext.global,
3424                 parts = this.parseNamespace(name),
3425                 leaf = parts.pop(),
3426                 i, ln, part;
3427
3428             for (i = 0, ln = parts.length; i < ln; i++) {
3429                 part = parts[i];
3430
3431                 if (typeof part !== 'string') {
3432                     root = part;
3433                 } else {
3434                     if (!root[part]) {
3435                         root[part] = {};
3436                     }
3437
3438                     root = root[part];
3439                 }
3440             }
3441
3442             root[leaf] = value;
3443
3444             return root[leaf];
3445         },
3446
3447         
3448         createNamespaces: function() {
3449             var root = Ext.global,
3450                 parts, part, i, j, ln, subLn;
3451
3452             for (i = 0, ln = arguments.length; i < ln; i++) {
3453                 parts = this.parseNamespace(arguments[i]);
3454
3455                 for (j = 0, subLn = parts.length; j < subLn; j++) {
3456                     part = parts[j];
3457
3458                     if (typeof part !== 'string') {
3459                         root = part;
3460                     } else {
3461                         if (!root[part]) {
3462                             root[part] = {};
3463                         }
3464
3465                         root = root[part];
3466                     }
3467                 }
3468             }
3469
3470             return root;
3471         },
3472
3473         
3474         set: function(name, value) {
3475             var targetName = this.getName(value);
3476
3477             this.classes[name] = this.setNamespace(name, value);
3478
3479             if (targetName && targetName !== name) {
3480                 this.maps.alternateToName[name] = targetName;
3481             }
3482
3483             return this;
3484         },
3485
3486         
3487         get: function(name) {
3488             if (this.classes.hasOwnProperty(name)) {
3489                 return this.classes[name];
3490             }
3491
3492             var root = Ext.global,
3493                 parts = this.parseNamespace(name),
3494                 part, i, ln;
3495
3496             for (i = 0, ln = parts.length; i < ln; i++) {
3497                 part = parts[i];
3498
3499                 if (typeof part !== 'string') {
3500                     root = part;
3501                 } else {
3502                     if (!root || !root[part]) {
3503                         return null;
3504                     }
3505
3506                     root = root[part];
3507                 }
3508             }
3509
3510             return root;
3511         },
3512
3513         
3514         setAlias: function(cls, alias) {
3515             var aliasToNameMap = this.maps.aliasToName,
3516                 nameToAliasesMap = this.maps.nameToAliases,
3517                 className;
3518
3519             if (typeof cls === 'string') {
3520                 className = cls;
3521             } else {
3522                 className = this.getName(cls);
3523             }
3524
3525             if (alias && aliasToNameMap[alias] !== className) {
3526                 if (aliasToNameMap.hasOwnProperty(alias) && Ext.isDefined(Ext.global.console)) {
3527                     Ext.global.console.log("[Ext.ClassManager] Overriding existing alias: '" + alias + "' " +
3528                         "of: '" + aliasToNameMap[alias] + "' with: '" + className + "'. Be sure it's intentional.");
3529                 }
3530
3531                 aliasToNameMap[alias] = className;
3532             }
3533
3534             if (!nameToAliasesMap[className]) {
3535                 nameToAliasesMap[className] = [];
3536             }
3537
3538             if (alias) {
3539                 Ext.Array.include(nameToAliasesMap[className], alias);
3540             }
3541
3542             return this;
3543         },
3544
3545         
3546         getByAlias: function(alias) {
3547             return this.get(this.getNameByAlias(alias));
3548         },
3549
3550         
3551         getNameByAlias: function(alias) {
3552             return this.maps.aliasToName[alias] || '';
3553         },
3554
3555         
3556         getNameByAlternate: function(alternate) {
3557             return this.maps.alternateToName[alternate] || '';
3558         },
3559
3560         
3561         getAliasesByName: function(name) {
3562             return this.maps.nameToAliases[name] || [];
3563         },
3564
3565         
3566         getName: function(object) {
3567             return object && object.$className || '';
3568         },
3569
3570         
3571         getClass: function(object) {
3572             return object && object.self || null;
3573         },
3574
3575         
3576         create: function(className, data, createdFn) {
3577             var manager = this;
3578
3579             if (typeof className !== 'string') {
3580                 Ext.Error.raise({
3581                     sourceClass: "Ext",
3582                     sourceMethod: "define",
3583                     msg: "Invalid class name '" + className + "' specified, must be a non-empty string"
3584                 });
3585             }
3586
3587             data.$className = className;
3588
3589             return new Class(data, function() {
3590                 var postprocessorStack = data.postprocessors || manager.defaultPostprocessors,
3591                     registeredPostprocessors = manager.postprocessors,
3592                     index = 0,
3593                     postprocessors = [],
3594                     postprocessor, postprocessors, process, i, ln;
3595
3596                 delete data.postprocessors;
3597
3598                 for (i = 0, ln = postprocessorStack.length; i < ln; i++) {
3599                     postprocessor = postprocessorStack[i];
3600
3601                     if (typeof postprocessor === 'string') {
3602                         postprocessor = registeredPostprocessors[postprocessor];
3603
3604                         if (!postprocessor.always) {
3605                             if (data[postprocessor.name] !== undefined) {
3606                                 postprocessors.push(postprocessor.fn);
3607                             }
3608                         }
3609                         else {
3610                             postprocessors.push(postprocessor.fn);
3611                         }
3612                     }
3613                     else {
3614                         postprocessors.push(postprocessor);
3615                     }
3616                 }
3617
3618                 process = function(clsName, cls, clsData) {
3619                     postprocessor = postprocessors[index++];
3620
3621                     if (!postprocessor) {
3622                         manager.set(className, cls);
3623
3624                         Ext.Loader.historyPush(className);
3625
3626                         if (createdFn) {
3627                             createdFn.call(cls, cls);
3628                         }
3629
3630                         return;
3631                     }
3632
3633                     if (postprocessor.call(this, clsName, cls, clsData, process) !== false) {
3634                         process.apply(this, arguments);
3635                     }
3636                 };
3637
3638                 process.call(manager, className, this, data);
3639             });
3640         },
3641
3642         
3643         instantiateByAlias: function() {
3644             var alias = arguments[0],
3645                 args = slice.call(arguments),
3646                 className = this.getNameByAlias(alias);
3647
3648             if (!className) {
3649                 className = this.maps.aliasToName[alias];
3650
3651                 if (!className) {
3652                     Ext.Error.raise({
3653                         sourceClass: "Ext",
3654                         sourceMethod: "createByAlias",
3655                         msg: "Cannot create an instance of unrecognized alias: " + alias
3656                     });
3657                 }
3658
3659                 if (Ext.global.console) {
3660                     Ext.global.console.warn("[Ext.Loader] Synchronously loading '" + className + "'; consider adding " +
3661                          "Ext.require('" + alias + "') above Ext.onReady");
3662                 }
3663
3664                 Ext.syncRequire(className);
3665             }
3666
3667             args[0] = className;
3668
3669             return this.instantiate.apply(this, args);
3670         },
3671
3672         
3673         instantiate: function() {
3674             var name = arguments[0],
3675                 args = slice.call(arguments, 1),
3676                 alias = name,
3677                 possibleName, cls;
3678
3679             if (typeof name !== 'function') {
3680                 if ((typeof name !== 'string' || name.length < 1)) {
3681                     Ext.Error.raise({
3682                         sourceClass: "Ext",
3683                         sourceMethod: "create",
3684                         msg: "Invalid class name or alias '" + name + "' specified, must be a non-empty string"
3685                     });
3686                 }
3687
3688                 cls = this.get(name);
3689             }
3690             else {
3691                 cls = name;
3692             }
3693
3694             
3695             if (!cls) {
3696                 possibleName = this.getNameByAlias(name);
3697
3698                 if (possibleName) {
3699                     name = possibleName;
3700
3701                     cls = this.get(name);
3702                 }
3703             }
3704
3705             
3706             if (!cls) {
3707                 possibleName = this.getNameByAlternate(name);
3708
3709                 if (possibleName) {
3710                     name = possibleName;
3711
3712                     cls = this.get(name);
3713                 }
3714             }
3715
3716             
3717             if (!cls) {
3718                 if (Ext.global.console) {
3719                     Ext.global.console.warn("[Ext.Loader] Synchronously loading '" + name + "'; consider adding " +
3720                          "Ext.require('" + ((possibleName) ? alias : name) + "') above Ext.onReady");
3721                 }
3722
3723                 Ext.syncRequire(name);
3724
3725                 cls = this.get(name);
3726             }
3727
3728             if (!cls) {
3729                 Ext.Error.raise({
3730                     sourceClass: "Ext",
3731                     sourceMethod: "create",
3732                     msg: "Cannot create an instance of unrecognized class name / alias: " + alias
3733                 });
3734             }
3735
3736             if (typeof cls !== 'function') {
3737                 Ext.Error.raise({
3738                     sourceClass: "Ext",
3739                     sourceMethod: "create",
3740                     msg: "'" + name + "' is a singleton and cannot be instantiated"
3741                 });
3742             }
3743
3744             if (!this.instantiationCounts[name]) {
3745                 this.instantiationCounts[name] = 0;
3746             }
3747
3748             this.instantiationCounts[name]++;
3749
3750             return this.getInstantiator(args.length)(cls, args);
3751         },
3752
3753         
3754         dynInstantiate: function(name, args) {
3755             args = Ext.Array.from(args, true);
3756             args.unshift(name);
3757
3758             return this.instantiate.apply(this, args);
3759         },
3760
3761         
3762         getInstantiator: function(length) {
3763             if (!this.instantiators[length]) {
3764                 var i = length,
3765                     args = [];
3766
3767                 for (i = 0; i < length; i++) {
3768                     args.push('a['+i+']');
3769                 }
3770
3771                 this.instantiators[length] = new Function('c', 'a', 'return new c('+args.join(',')+')');
3772             }
3773
3774             return this.instantiators[length];
3775         },
3776
3777         
3778         postprocessors: {},
3779
3780         
3781         defaultPostprocessors: [],
3782
3783         
3784         registerPostprocessor: function(name, fn, always) {
3785             this.postprocessors[name] = {
3786                 name: name,
3787                 always: always ||  false,
3788                 fn: fn
3789             };
3790
3791             return this;
3792         },
3793
3794         
3795         setDefaultPostprocessors: function(postprocessors) {
3796             this.defaultPostprocessors = Ext.Array.from(postprocessors);
3797
3798             return this;
3799         },
3800
3801         
3802         setDefaultPostprocessorPosition: function(name, offset, relativeName) {
3803             var defaultPostprocessors = this.defaultPostprocessors,
3804                 index;
3805
3806             if (typeof offset === 'string') {
3807                 if (offset === 'first') {
3808                     defaultPostprocessors.unshift(name);
3809
3810                     return this;
3811                 }
3812                 else if (offset === 'last') {
3813                     defaultPostprocessors.push(name);
3814
3815                     return this;
3816                 }
3817
3818                 offset = (offset === 'after') ? 1 : -1;
3819             }
3820
3821             index = Ext.Array.indexOf(defaultPostprocessors, relativeName);
3822
3823             if (index !== -1) {
3824                 defaultPostprocessors.splice(Math.max(0, index + offset), 0, name);
3825             }
3826
3827             return this;
3828         },
3829
3830         
3831         getNamesByExpression: function(expression) {
3832             var nameToAliasesMap = this.maps.nameToAliases,
3833                 names = [],
3834                 name, alias, aliases, possibleName, regex, i, ln;
3835
3836             if (typeof expression !== 'string' || expression.length < 1) {
3837                 Ext.Error.raise({
3838                     sourceClass: "Ext.ClassManager",
3839                     sourceMethod: "getNamesByExpression",
3840                     msg: "Expression " + expression + " is invalid, must be a non-empty string"
3841                 });
3842             }
3843
3844             if (expression.indexOf('*') !== -1) {
3845                 expression = expression.replace(/\*/g, '(.*?)');
3846                 regex = new RegExp('^' + expression + '$');
3847
3848                 for (name in nameToAliasesMap) {
3849                     if (nameToAliasesMap.hasOwnProperty(name)) {
3850                         aliases = nameToAliasesMap[name];
3851
3852                         if (name.search(regex) !== -1) {
3853                             names.push(name);
3854                         }
3855                         else {
3856                             for (i = 0, ln = aliases.length; i < ln; i++) {
3857                                 alias = aliases[i];
3858
3859                                 if (alias.search(regex) !== -1) {
3860                                     names.push(name);
3861                                     break;
3862                                 }
3863                             }
3864                         }
3865                     }
3866                 }
3867
3868             } else {
3869                 possibleName = this.getNameByAlias(expression);
3870
3871                 if (possibleName) {
3872                     names.push(possibleName);
3873                 } else {
3874                     possibleName = this.getNameByAlternate(expression);
3875
3876                     if (possibleName) {
3877                         names.push(possibleName);
3878                     } else {
3879                         names.push(expression);
3880                     }
3881                 }
3882             }
3883
3884             return names;
3885         }
3886     };
3887
3888     Manager.registerPostprocessor('alias', function(name, cls, data) {
3889         var aliases = data.alias,
3890             widgetPrefix = 'widget.',
3891             i, ln, alias;
3892
3893         if (!(aliases instanceof Array)) {
3894             aliases = [aliases];
3895         }
3896
3897         for (i = 0, ln = aliases.length; i < ln; i++) {
3898             alias = aliases[i];
3899
3900             if (typeof alias !== 'string') {
3901                 Ext.Error.raise({
3902                     sourceClass: "Ext",
3903                     sourceMethod: "define",
3904                     msg: "Invalid alias of: '" + alias + "' for class: '" + name + "'; must be a valid string"
3905                 });
3906             }
3907
3908             this.setAlias(cls, alias);
3909         }
3910
3911         
3912         for (i = 0, ln = aliases.length; i < ln; i++) {
3913             alias = aliases[i];
3914
3915             if (alias.substring(0, widgetPrefix.length) === widgetPrefix) {
3916                 
3917                 cls.xtype = cls.$xtype = alias.substring(widgetPrefix.length);
3918                 break;
3919             }
3920         }
3921     });
3922
3923     Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {
3924         fn.call(this, name, new cls(), data);
3925         return false;
3926     });
3927
3928     Manager.registerPostprocessor('alternateClassName', function(name, cls, data) {
3929         var alternates = data.alternateClassName,
3930             i, ln, alternate;
3931
3932         if (!(alternates instanceof Array)) {
3933             alternates = [alternates];
3934         }
3935
3936         for (i = 0, ln = alternates.length; i < ln; i++) {
3937             alternate = alternates[i];
3938
3939             if (typeof alternate !== 'string') {
3940                 Ext.Error.raise({
3941                     sourceClass: "Ext",
3942                     sourceMethod: "define",
3943                     msg: "Invalid alternate of: '" + alternate + "' for class: '" + name + "'; must be a valid string"
3944                 });
3945             }
3946
3947             this.set(alternate, cls);
3948         }
3949     });
3950
3951     Manager.setDefaultPostprocessors(['alias', 'singleton', 'alternateClassName']);
3952
3953     Ext.apply(Ext, {
3954         
3955         create: alias(Manager, 'instantiate'),
3956
3957         
3958         factory: function(item, namespace) {
3959             if (item instanceof Array) {
3960                 var i, ln;
3961
3962                 for (i = 0, ln = item.length; i < ln; i++) {
3963                     item[i] = Ext.factory(item[i], namespace);
3964                 }
3965
3966                 return item;
3967             }
3968
3969             var isString = (typeof item === 'string');
3970
3971             if (isString || (item instanceof Object && item.constructor === Object)) {
3972                 var name, config = {};
3973
3974                 if (isString) {
3975                     name = item;
3976                 }
3977                 else {
3978                     name = item.className;
3979                     config = item;
3980                     delete config.className;
3981                 }
3982
3983                 if (namespace !== undefined && name.indexOf(namespace) === -1) {
3984                     name = namespace + '.' + Ext.String.capitalize(name);
3985                 }
3986
3987                 return Ext.create(name, config);
3988             }
3989
3990             if (typeof item === 'function') {
3991                 return Ext.create(item);
3992             }
3993
3994             return item;
3995         },
3996
3997         
3998         widget: function(name) {
3999             var args = slice.call(arguments);
4000             args[0] = 'widget.' + name;
4001
4002             return Manager.instantiateByAlias.apply(Manager, args);
4003         },
4004
4005         
4006         createByAlias: alias(Manager, 'instantiateByAlias'),
4007
4008         
4009         define: alias(Manager, 'create'),
4010
4011         
4012         getClassName: alias(Manager, 'getName'),
4013
4014         
4015         getDisplayName: function(object) {
4016             if (object.displayName) {
4017                 return object.displayName;
4018             }
4019
4020             if (object.$name && object.$class) {
4021                 return Ext.getClassName(object.$class) + '#' + object.$name;
4022             }
4023
4024             if (object.$className) {
4025                 return object.$className;
4026             }
4027
4028             return 'Anonymous';
4029         },
4030
4031         
4032         getClass: alias(Manager, 'getClass'),
4033
4034         
4035         namespace: alias(Manager, 'createNamespaces')
4036     });
4037
4038     Ext.createWidget = Ext.widget;
4039
4040     
4041     Ext.ns = Ext.namespace;
4042
4043     Class.registerPreprocessor('className', function(cls, data) {
4044         if (data.$className) {
4045             cls.$className = data.$className;
4046             cls.displayName = cls.$className;
4047         }
4048     }, true);
4049
4050     Class.setDefaultPreprocessorPosition('className', 'first');
4051
4052 })(Ext.Class, Ext.Function.alias);
4053
4054
4055
4056 (function(Manager, Class, flexSetter, alias) {
4057
4058     var
4059         dependencyProperties = ['extend', 'mixins', 'requires'],
4060         Loader;
4061
4062     Loader = Ext.Loader = {
4063         
4064         documentHead: typeof document !== 'undefined' && (document.head || document.getElementsByTagName('head')[0]),
4065
4066         
4067         isLoading: false,
4068
4069         
4070         queue: [],
4071
4072         
4073         isFileLoaded: {},
4074
4075         
4076         readyListeners: [],
4077
4078         
4079         optionalRequires: [],
4080
4081         
4082         requiresMap: {},
4083
4084         
4085         numPendingFiles: 0,
4086
4087         
4088         numLoadedFiles: 0,
4089
4090         
4091         hasFileLoadError: false,
4092
4093         
4094         classNameToFilePathMap: {},
4095
4096         
4097         history: [],
4098
4099         
4100         config: {
4101             
4102             enabled: false,
4103
4104             
4105             disableCaching: true,
4106
4107             
4108             disableCachingParam: '_dc',
4109
4110             
4111             paths: {
4112                 'Ext': '.'
4113             }
4114         },
4115
4116         
4117         setConfig: function(name, value) {
4118             if (Ext.isObject(name) && arguments.length === 1) {
4119                 Ext.Object.merge(this.config, name);
4120             }
4121             else {
4122                 this.config[name] = (Ext.isObject(value)) ? Ext.Object.merge(this.config[name], value) : value;
4123             }
4124
4125             return this;
4126         },
4127
4128         
4129         getConfig: function(name) {
4130             if (name) {
4131                 return this.config[name];
4132             }
4133
4134             return this.config;
4135         },
4136
4137         
4138         setPath: flexSetter(function(name, path) {
4139             this.config.paths[name] = path;
4140
4141             return this;
4142         }),
4143
4144         
4145         getPath: function(className) {
4146             var path = '',
4147                 paths = this.config.paths,
4148                 prefix = this.getPrefix(className);
4149
4150             if (prefix.length > 0) {
4151                 if (prefix === className) {
4152                     return paths[prefix];
4153                 }
4154
4155                 path = paths[prefix];
4156                 className = className.substring(prefix.length + 1);
4157             }
4158
4159             if (path.length > 0) {
4160                 path += '/';
4161             }
4162
4163             return path.replace(/\/\.\//g, '/') + className.replace(/\./g, "/") + '.js';
4164         },
4165
4166         
4167         getPrefix: function(className) {
4168             var paths = this.config.paths,
4169                 prefix, deepestPrefix = '';
4170
4171             if (paths.hasOwnProperty(className)) {
4172                 return className;
4173             }
4174
4175             for (prefix in paths) {
4176                 if (paths.hasOwnProperty(prefix) && prefix + '.' === className.substring(0, prefix.length + 1)) {
4177                     if (prefix.length > deepestPrefix.length) {
4178                         deepestPrefix = prefix;
4179                     }
4180                 }
4181             }
4182
4183             return deepestPrefix;
4184         },
4185
4186         
4187         refreshQueue: function() {
4188             var ln = this.queue.length,
4189                 i, item, j, requires;
4190
4191             if (ln === 0) {
4192                 this.triggerReady();
4193                 return;
4194             }
4195
4196             for (i = 0; i < ln; i++) {
4197                 item = this.queue[i];
4198
4199                 if (item) {
4200                     requires = item.requires;
4201
4202                     
4203                     
4204                     if (requires.length > this.numLoadedFiles) {
4205                         continue;
4206                     }
4207
4208                     j = 0;
4209
4210                     do {
4211                         if (Manager.isCreated(requires[j])) {
4212                             
4213                             requires.splice(j, 1);
4214                         }
4215                         else {
4216                             j++;
4217                         }
4218                     } while (j < requires.length);
4219
4220                     if (item.requires.length === 0) {
4221                         this.queue.splice(i, 1);
4222                         item.callback.call(item.scope);
4223                         this.refreshQueue();
4224                         break;
4225                     }
4226                 }
4227             }
4228
4229             return this;
4230         },
4231
4232         
4233         injectScriptElement: function(url, onLoad, onError, scope) {
4234             var script = document.createElement('script'),
4235                 me = this,
4236                 onLoadFn = function() {
4237                     me.cleanupScriptElement(script);
4238                     onLoad.call(scope);
4239                 },
4240                 onErrorFn = function() {
4241                     me.cleanupScriptElement(script);
4242                     onError.call(scope);
4243                 };
4244
4245             script.type = 'text/javascript';
4246             script.src = url;
4247             script.onload = onLoadFn;
4248             script.onerror = onErrorFn;
4249             script.onreadystatechange = function() {
4250                 if (this.readyState === 'loaded' || this.readyState === 'complete') {
4251                     onLoadFn();
4252                 }
4253             };
4254
4255             this.documentHead.appendChild(script);
4256
4257             return script;
4258         },
4259
4260         
4261         cleanupScriptElement: function(script) {
4262             script.onload = null;
4263             script.onreadystatechange = null;
4264             script.onerror = null;
4265
4266             return this;
4267         },
4268
4269         
4270         loadScriptFile: function(url, onLoad, onError, scope, synchronous) {
4271             var me = this,
4272                 noCacheUrl = url + (this.getConfig('disableCaching') ? ('?' + this.getConfig('disableCachingParam') + '=' + Ext.Date.now()) : ''),
4273                 fileName = url.split('/').pop(),
4274                 isCrossOriginRestricted = false,
4275                 xhr, status, onScriptError;
4276
4277             scope = scope || this;
4278
4279             this.isLoading = true;
4280
4281             if (!synchronous) {
4282                 onScriptError = function() {
4283                     onError.call(scope, "Failed loading '" + url + "', please verify that the file exists", synchronous);
4284                 };
4285
4286                 if (!Ext.isReady && Ext.onDocumentReady) {
4287                     Ext.onDocumentReady(function() {
4288                         me.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
4289                     });
4290                 }
4291                 else {
4292                     this.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
4293                 }
4294             }
4295             else {
4296                 if (typeof XMLHttpRequest !== 'undefined') {
4297                     xhr = new XMLHttpRequest();
4298                 } else {
4299                     xhr = new ActiveXObject('Microsoft.XMLHTTP');
4300                 }
4301
4302                 try {
4303                     xhr.open('GET', noCacheUrl, false);
4304                     xhr.send(null);
4305                 } catch (e) {
4306                     isCrossOriginRestricted = true;
4307                 }
4308
4309                 status = (xhr.status === 1223) ? 204 : xhr.status;
4310
4311                 if (!isCrossOriginRestricted) {
4312                     isCrossOriginRestricted = (status === 0);
4313                 }
4314
4315                 if (isCrossOriginRestricted
4316                 ) {
4317                     onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; It's likely that the file is either " +
4318                                        "being loaded from a different domain or from the local file system whereby cross origin " +
4319                                        "requests are not allowed due to security reasons. Use asynchronous loading with " +
4320                                        "Ext.require instead.", synchronous);
4321                 }
4322                 else if (status >= 200 && status < 300
4323                 ) {
4324                     
4325                     new Function(xhr.responseText + "\n//@ sourceURL=" + fileName)();
4326
4327                     onLoad.call(scope);
4328                 }
4329                 else {
4330                     onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; please " +
4331                                        "verify that the file exists. " +
4332                                        "XHR status code: " + status, synchronous);
4333                 }
4334
4335                 
4336                 xhr = null;
4337             }
4338         },
4339
4340         
4341         exclude: function(excludes) {
4342             var me = this;
4343
4344             return {
4345                 require: function(expressions, fn, scope) {
4346                     return me.require(expressions, fn, scope, excludes);
4347                 },
4348
4349                 syncRequire: function(expressions, fn, scope) {
4350                     return me.syncRequire(expressions, fn, scope, excludes);
4351                 }
4352             };
4353         },
4354
4355         
4356         syncRequire: function() {
4357             this.syncModeEnabled = true;
4358             this.require.apply(this, arguments);
4359             this.refreshQueue();
4360             this.syncModeEnabled = false;
4361         },
4362
4363         
4364         require: function(expressions, fn, scope, excludes) {
4365             var filePath, expression, exclude, className, excluded = {},
4366                 excludedClassNames = [],
4367                 possibleClassNames = [],
4368                 possibleClassName, classNames = [],
4369                 i, j, ln, subLn;
4370
4371             expressions = Ext.Array.from(expressions);
4372             excludes = Ext.Array.from(excludes);
4373
4374             fn = fn || Ext.emptyFn;
4375
4376             scope = scope || Ext.global;
4377
4378             for (i = 0, ln = excludes.length; i < ln; i++) {
4379                 exclude = excludes[i];
4380
4381                 if (typeof exclude === 'string' && exclude.length > 0) {
4382                     excludedClassNames = Manager.getNamesByExpression(exclude);
4383
4384                     for (j = 0, subLn = excludedClassNames.length; j < subLn; j++) {
4385                         excluded[excludedClassNames[j]] = true;
4386                     }
4387                 }
4388             }
4389
4390             for (i = 0, ln = expressions.length; i < ln; i++) {
4391                 expression = expressions[i];
4392
4393                 if (typeof expression === 'string' && expression.length > 0) {
4394                     possibleClassNames = Manager.getNamesByExpression(expression);
4395
4396                     for (j = 0, subLn = possibleClassNames.length; j < subLn; j++) {
4397                         possibleClassName = possibleClassNames[j];
4398
4399                         if (!excluded.hasOwnProperty(possibleClassName) && !Manager.isCreated(possibleClassName)) {
4400                             Ext.Array.include(classNames, possibleClassName);
4401                         }
4402                     }
4403                 }
4404             }
4405
4406             
4407             
4408             if (!this.config.enabled) {
4409                 if (classNames.length > 0) {
4410                     Ext.Error.raise({
4411                         sourceClass: "Ext.Loader",
4412                         sourceMethod: "require",
4413                         msg: "Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " +
4414                              "Missing required class" + ((classNames.length > 1) ? "es" : "") + ": " + classNames.join(', ')
4415                     });
4416                 }
4417             }
4418
4419             if (classNames.length === 0) {
4420                 fn.call(scope);
4421                 return this;
4422             }
4423
4424             this.queue.push({
4425                 requires: classNames,
4426                 callback: fn,
4427                 scope: scope
4428             });
4429
4430             classNames = classNames.slice();
4431
4432             for (i = 0, ln = classNames.length; i < ln; i++) {
4433                 className = classNames[i];
4434
4435                 if (!this.isFileLoaded.hasOwnProperty(className)) {
4436                     this.isFileLoaded[className] = false;
4437
4438                     filePath = this.getPath(className);
4439
4440                     this.classNameToFilePathMap[className] = filePath;
4441
4442                     this.numPendingFiles++;
4443
4444                     this.loadScriptFile(
4445                         filePath,
4446                         Ext.Function.pass(this.onFileLoaded, [className, filePath], this),
4447                         Ext.Function.pass(this.onFileLoadError, [className, filePath]),
4448                         this,
4449                         this.syncModeEnabled
4450                     );
4451                 }
4452             }
4453
4454             return this;
4455         },
4456
4457         
4458         onFileLoaded: function(className, filePath) {
4459             this.numLoadedFiles++;
4460
4461             this.isFileLoaded[className] = true;
4462
4463             this.numPendingFiles--;
4464
4465             if (this.numPendingFiles === 0) {
4466                 this.refreshQueue();
4467             }
4468
4469             if (this.numPendingFiles <= 1) {
4470                 window.status = "Finished loading all dependencies, onReady fired!";
4471             }
4472             else {
4473                 window.status = "Loading dependencies, " + this.numPendingFiles + " files left...";
4474             }
4475
4476             if (!this.syncModeEnabled && this.numPendingFiles === 0 && this.isLoading && !this.hasFileLoadError) {
4477                 var queue = this.queue,
4478                     requires,
4479                     i, ln, j, subLn, missingClasses = [], missingPaths = [];
4480
4481                 for (i = 0, ln = queue.length; i < ln; i++) {
4482                     requires = queue[i].requires;
4483
4484                     for (j = 0, subLn = requires.length; j < ln; j++) {
4485                         if (this.isFileLoaded[requires[j]]) {
4486                             missingClasses.push(requires[j]);
4487                         }
4488                     }
4489                 }
4490
4491                 if (missingClasses.length < 1) {
4492                     return;
4493                 }
4494
4495                 missingClasses = Ext.Array.filter(missingClasses, function(item) {
4496                     return !this.requiresMap.hasOwnProperty(item);
4497                 }, this);
4498
4499                 for (i = 0,ln = missingClasses.length; i < ln; i++) {
4500                     missingPaths.push(this.classNameToFilePathMap[missingClasses[i]]);
4501                 }
4502
4503                 Ext.Error.raise({
4504                     sourceClass: "Ext.Loader",
4505                     sourceMethod: "onFileLoaded",
4506                     msg: "The following classes are not declared even if their files have been " +
4507                             "loaded: '" + missingClasses.join("', '") + "'. Please check the source code of their " +
4508                             "corresponding files for possible typos: '" + missingPaths.join("', '") + "'"
4509                 });
4510             }
4511         },
4512
4513         
4514         onFileLoadError: function(className, filePath, errorMessage, isSynchronous) {
4515             this.numPendingFiles--;
4516             this.hasFileLoadError = true;
4517
4518             Ext.Error.raise({
4519                 sourceClass: "Ext.Loader",
4520                 classToLoad: className,
4521                 loadPath: filePath,
4522                 loadingType: isSynchronous ? 'synchronous' : 'async',
4523                 msg: errorMessage
4524             });
4525         },
4526
4527         
4528         addOptionalRequires: function(requires) {
4529             var optionalRequires = this.optionalRequires,
4530                 i, ln, require;
4531
4532             requires = Ext.Array.from(requires);
4533
4534             for (i = 0, ln = requires.length; i < ln; i++) {
4535                 require = requires[i];
4536
4537                 Ext.Array.include(optionalRequires, require);
4538             }
4539
4540             return this;
4541         },
4542
4543         
4544         triggerReady: function(force) {
4545             var readyListeners = this.readyListeners,
4546                 optionalRequires, listener;
4547
4548             if (this.isLoading || force) {
4549                 this.isLoading = false;
4550
4551                 if (this.optionalRequires.length) {
4552                     
4553                     optionalRequires = Ext.Array.clone(this.optionalRequires);
4554
4555                     
4556                     this.optionalRequires.length = 0;
4557
4558                     this.require(optionalRequires, Ext.Function.pass(this.triggerReady, [true], this), this);
4559                     return this;
4560                 }
4561
4562                 while (readyListeners.length) {
4563                     listener = readyListeners.shift();
4564                     listener.fn.call(listener.scope);
4565
4566                     if (this.isLoading) {
4567                         return this;
4568                     }
4569                 }
4570             }
4571
4572             return this;
4573         },
4574
4575         
4576         onReady: function(fn, scope, withDomReady, options) {
4577             var oldFn;
4578
4579             if (withDomReady !== false && Ext.onDocumentReady) {
4580                 oldFn = fn;
4581
4582                 fn = function() {
4583                     Ext.onDocumentReady(oldFn, scope, options);
4584                 };
4585             }
4586
4587             if (!this.isLoading) {
4588                 fn.call(scope);
4589             }
4590             else {
4591                 this.readyListeners.push({
4592                     fn: fn,
4593                     scope: scope
4594                 });
4595             }
4596         },
4597
4598         
4599         historyPush: function(className) {
4600             if (className && this.isFileLoaded.hasOwnProperty(className)) {
4601                 Ext.Array.include(this.history, className);
4602             }
4603
4604             return this;
4605         }
4606     };
4607
4608     
4609     Ext.require = alias(Loader, 'require');
4610
4611     
4612     Ext.syncRequire = alias(Loader, 'syncRequire');
4613
4614     
4615     Ext.exclude = alias(Loader, 'exclude');
4616
4617     
4618     Ext.onReady = function(fn, scope, options) {
4619         Loader.onReady(fn, scope, true, options);
4620     };
4621
4622     Class.registerPreprocessor('loader', function(cls, data, continueFn) {
4623         var me = this,
4624             dependencies = [],
4625             className = Manager.getName(cls),
4626             i, j, ln, subLn, value, propertyName, propertyValue;
4627
4628         
4629
4630         for (i = 0, ln = dependencyProperties.length; i < ln; i++) {
4631             propertyName = dependencyProperties[i];
4632
4633             if (data.hasOwnProperty(propertyName)) {
4634                 propertyValue = data[propertyName];
4635
4636                 if (typeof propertyValue === 'string') {
4637                     dependencies.push(propertyValue);
4638                 }
4639                 else if (propertyValue instanceof Array) {
4640                     for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
4641                         value = propertyValue[j];
4642
4643                         if (typeof value === 'string') {
4644                             dependencies.push(value);
4645                         }
4646                     }
4647                 }
4648                 else {
4649                     for (j in propertyValue) {
4650                         if (propertyValue.hasOwnProperty(j)) {
4651                             value = propertyValue[j];
4652
4653                             if (typeof value === 'string') {
4654                                 dependencies.push(value);
4655                             }
4656                         }
4657                     }
4658                 }
4659             }
4660         }
4661
4662         if (dependencies.length === 0) {
4663
4664             return;
4665         }
4666
4667         var deadlockPath = [],
4668             requiresMap = Loader.requiresMap,
4669             detectDeadlock;
4670
4671         
4672
4673         if (className) {
4674             requiresMap[className] = dependencies;
4675
4676             detectDeadlock = function(cls) {
4677                 deadlockPath.push(cls);
4678
4679                 if (requiresMap[cls]) {
4680                     if (Ext.Array.contains(requiresMap[cls], className)) {
4681                         Ext.Error.raise({
4682                             sourceClass: "Ext.Loader",
4683                             msg: "Deadlock detected while loading dependencies! '" + className + "' and '" +
4684                                 deadlockPath[1] + "' " + "mutually require each other. Path: " +
4685                                 deadlockPath.join(' -> ') + " -> " + deadlockPath[0]
4686                         });
4687                     }
4688
4689                     for (i = 0, ln = requiresMap[cls].length; i < ln; i++) {
4690                         detectDeadlock(requiresMap[cls][i]);
4691                     }
4692                 }
4693             };
4694
4695             detectDeadlock(className);
4696         }
4697
4698
4699         Loader.require(dependencies, function() {
4700             for (i = 0, ln = dependencyProperties.length; i < ln; i++) {
4701                 propertyName = dependencyProperties[i];
4702
4703                 if (data.hasOwnProperty(propertyName)) {
4704                     propertyValue = data[propertyName];
4705
4706                     if (typeof propertyValue === 'string') {
4707                         data[propertyName] = Manager.get(propertyValue);
4708                     }
4709                     else if (propertyValue instanceof Array) {
4710                         for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
4711                             value = propertyValue[j];
4712
4713                             if (typeof value === 'string') {
4714                                 data[propertyName][j] = Manager.get(value);
4715                             }
4716                         }
4717                     }
4718                     else {
4719                         for (var k in propertyValue) {
4720                             if (propertyValue.hasOwnProperty(k)) {
4721                                 value = propertyValue[k];
4722
4723                                 if (typeof value === 'string') {
4724                                     data[propertyName][k] = Manager.get(value);
4725                                 }
4726                             }
4727                         }
4728                     }
4729                 }
4730             }
4731
4732             continueFn.call(me, cls, data);
4733         });
4734
4735         return false;
4736     }, true);
4737
4738     Class.setDefaultPreprocessorPosition('loader', 'after', 'className');
4739
4740     Manager.registerPostprocessor('uses', function(name, cls, data) {
4741         var uses = Ext.Array.from(data.uses),
4742             items = [],
4743             i, ln, item;
4744
4745         for (i = 0, ln = uses.length; i < ln; i++) {
4746             item = uses[i];
4747
4748             if (typeof item === 'string') {
4749                 items.push(item);
4750             }
4751         }
4752
4753         Loader.addOptionalRequires(items);
4754     });
4755
4756     Manager.setDefaultPostprocessorPosition('uses', 'last');
4757
4758 })(Ext.ClassManager, Ext.Class, Ext.Function.flexSetter, Ext.Function.alias);
4759
4760
4761 Ext.Error = Ext.extend(Error, {
4762     statics: {
4763         
4764         ignore: false,
4765
4766         
4767         
4768
4769         
4770         raise: function(err){
4771             err = err || {};
4772             if (Ext.isString(err)) {
4773                 err = { msg: err };
4774             }
4775
4776             var method = this.raise.caller;
4777
4778             if (method) {
4779                 if (method.$name) {
4780                     err.sourceMethod = method.$name;
4781                 }
4782                 if (method.$owner) {
4783                     err.sourceClass = method.$owner.$className;
4784                 }
4785             }
4786
4787             if (Ext.Error.handle(err) !== true) {
4788                 var msg = Ext.Error.prototype.toString.call(err);
4789
4790                 Ext.log({
4791                     msg: msg,
4792                     level: 'error',
4793                     dump: err,
4794                     stack: true
4795                 });
4796
4797                 throw new Ext.Error(err);
4798             }
4799         },
4800
4801         
4802         handle: function(){
4803             return Ext.Error.ignore;
4804         }
4805     },
4806
4807     
4808     name: 'Ext.Error',
4809
4810     
4811     constructor: function(config){
4812         if (Ext.isString(config)) {
4813             config = { msg: config };
4814         }
4815
4816         var me = this;
4817
4818         Ext.apply(me, config);
4819
4820         me.message = me.message || me.msg; 
4821         
4822     },
4823
4824     
4825     toString: function(){
4826         var me = this,
4827             className = me.className ? me.className  : '',
4828             methodName = me.methodName ? '.' + me.methodName + '(): ' : '',
4829             msg = me.msg || '(No description provided)';
4830
4831         return className + methodName + msg;
4832     }
4833 });
4834
4835
4836 (function () {
4837     var prevOnError, timer, errors = 0,
4838         extraordinarilyBad = /(out of stack)|(too much recursion)|(stack overflow)|(out of memory)/i,
4839         win = Ext.global;
4840
4841     if (typeof window === 'undefined') {
4842         return; 
4843     }
4844
4845     
4846     function notify () {
4847         var counters = Ext.log.counters,
4848             supports = Ext.supports,
4849             hasOnError = supports && supports.WindowOnError; 
4850
4851         
4852         if (counters && (counters.error + counters.warn + counters.info + counters.log)) {
4853             var msg = [ 'Logged Errors:',counters.error, 'Warnings:',counters.warn,
4854                         'Info:',counters.info, 'Log:',counters.log].join(' ');
4855             if (errors) {
4856                 msg = '*** Errors: ' + errors + ' - ' + msg;
4857             } else if (counters.error) {
4858                 msg = '*** ' + msg;
4859             }
4860             win.status = msg;
4861         }
4862
4863         
4864         if (!Ext.isDefined(Ext.Error.notify)) {
4865             Ext.Error.notify = Ext.isIE6 || Ext.isIE7; 
4866         }
4867         if (Ext.Error.notify && (hasOnError ? errors : (counters && counters.error))) {
4868             Ext.Error.notify = false;
4869
4870             if (timer) {
4871                 win.clearInterval(timer); 
4872                 timer = null;
4873             }
4874
4875             alert('Unhandled error on page: See console or log');
4876             poll();
4877         }
4878     }
4879
4880     
4881     
4882     
4883     function poll () {
4884         timer = win.setInterval(notify, 1000);
4885     }
4886
4887     
4888     
4889     prevOnError = win.onerror || Ext.emptyFn;
4890     win.onerror = function (message) {
4891         ++errors;
4892
4893         if (!extraordinarilyBad.test(message)) {
4894             
4895             
4896             notify();
4897         }
4898
4899         return prevOnError.apply(this, arguments);
4900     };
4901     poll();
4902 })();
4903
4904
4905
4906
4907
4908 Ext.JSON = new(function() {
4909     var useHasOwn = !! {}.hasOwnProperty,
4910     isNative = function() {
4911         var useNative = null;
4912
4913         return function() {
4914             if (useNative === null) {
4915                 useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
4916             }
4917
4918             return useNative;
4919         };
4920     }(),
4921     pad = function(n) {
4922         return n < 10 ? "0" + n : n;
4923     },
4924     doDecode = function(json) {
4925         return eval("(" + json + ')');
4926     },
4927     doEncode = function(o) {
4928         if (!Ext.isDefined(o) || o === null) {
4929             return "null";
4930         } else if (Ext.isArray(o)) {
4931             return encodeArray(o);
4932         } else if (Ext.isDate(o)) {
4933             return Ext.JSON.encodeDate(o);
4934         } else if (Ext.isString(o)) {
4935             return encodeString(o);
4936         } else if (typeof o == "number") {
4937             
4938             return isFinite(o) ? String(o) : "null";
4939         } else if (Ext.isBoolean(o)) {
4940             return String(o);
4941         } else if (Ext.isObject(o)) {
4942             return encodeObject(o);
4943         } else if (typeof o === "function") {
4944             return "null";
4945         }
4946         return 'undefined';
4947     },
4948     m = {
4949         "\b": '\\b',
4950         "\t": '\\t',
4951         "\n": '\\n',
4952         "\f": '\\f',
4953         "\r": '\\r',
4954         '"': '\\"',
4955         "\\": '\\\\',
4956         '\x0b': '\\u000b' 
4957     },
4958     charToReplace = /[\\\"\x00-\x1f\x7f-\uffff]/g,
4959     encodeString = function(s) {
4960         return '"' + s.replace(charToReplace, function(a) {
4961             var c = m[a];
4962             return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
4963         }) + '"';
4964     },
4965     encodeArray = function(o) {
4966         var a = ["[", ""],
4967         
4968         len = o.length,
4969         i;
4970         for (i = 0; i < len; i += 1) {
4971             a.push(doEncode(o[i]), ',');
4972         }
4973         
4974         a[a.length - 1] = ']';
4975         return a.join("");
4976     },
4977     encodeObject = function(o) {
4978         var a = ["{", ""],
4979         
4980         i;
4981         for (i in o) {
4982             if (!useHasOwn || o.hasOwnProperty(i)) {
4983                 a.push(doEncode(i), ":", doEncode(o[i]), ',');
4984             }
4985         }
4986         
4987         a[a.length - 1] = '}';
4988         return a.join("");
4989     };
4990
4991     
4992     this.encodeDate = function(o) {
4993         return '"' + o.getFullYear() + "-" 
4994         + pad(o.getMonth() + 1) + "-"
4995         + pad(o.getDate()) + "T"
4996         + pad(o.getHours()) + ":"
4997         + pad(o.getMinutes()) + ":"
4998         + pad(o.getSeconds()) + '"';
4999     };
5000
5001     
5002     this.encode = function() {
5003         var ec;
5004         return function(o) {
5005             if (!ec) {
5006                 
5007                 ec = isNative() ? JSON.stringify : doEncode;
5008             }
5009             return ec(o);
5010         };
5011     }();
5012
5013
5014     
5015     this.decode = function() {
5016         var dc;
5017         return function(json, safe) {
5018             if (!dc) {
5019                 
5020                 dc = isNative() ? JSON.parse : doDecode;
5021             }
5022             try {
5023                 return dc(json);
5024             } catch (e) {
5025                 if (safe === true) {
5026                     return null;
5027                 }
5028                 Ext.Error.raise({
5029                     sourceClass: "Ext.JSON",
5030                     sourceMethod: "decode",
5031                     msg: "You're trying to decode and invalid JSON String: " + json
5032                 });
5033             }
5034         };
5035     }();
5036
5037 })();
5038
5039 Ext.encode = Ext.JSON.encode;
5040
5041 Ext.decode = Ext.JSON.decode;
5042
5043
5044
5045 Ext.apply(Ext, {
5046     userAgent: navigator.userAgent.toLowerCase(),
5047     cache: {},
5048     idSeed: 1000,
5049     BLANK_IMAGE_URL : 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
5050     isStrict: document.compatMode == "CSS1Compat",
5051     windowId: 'ext-window',
5052     documentId: 'ext-document',
5053
5054     
5055     isReady: false,
5056
5057     
5058     enableGarbageCollector: true,
5059
5060     
5061     enableListenerCollection: true,
5062
5063     
5064     id: function(el, prefix) {
5065         el = Ext.getDom(el, true) || {};
5066         if (el === document) {
5067             el.id = this.documentId;
5068         }
5069         else if (el === window) {
5070             el.id = this.windowId;
5071         }
5072         if (!el.id) {
5073             el.id = (prefix || "ext-gen") + (++Ext.idSeed);
5074         }
5075         return el.id;
5076     },
5077
5078     
5079     getBody: function() {
5080         return Ext.get(document.body || false);
5081     },
5082
5083     
5084     getHead: function() {
5085         var head;
5086
5087         return function() {
5088             if (head == undefined) {
5089                 head = Ext.get(document.getElementsByTagName("head")[0]);
5090             }
5091
5092             return head;
5093         };
5094     }(),
5095
5096     
5097     getDoc: function() {
5098         return Ext.get(document);
5099     },
5100
5101     
5102     getCmp: function(id) {
5103         return Ext.ComponentManager.get(id);
5104     },
5105
5106     
5107     getOrientation: function() {
5108         return window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
5109     },
5110
5111     
5112     destroy: function() {
5113         var ln = arguments.length,
5114         i, arg;
5115
5116         for (i = 0; i < ln; i++) {
5117             arg = arguments[i];
5118             if (arg) {
5119                 if (Ext.isArray(arg)) {
5120                     this.destroy.apply(this, arg);
5121                 }
5122                 else if (Ext.isFunction(arg.destroy)) {
5123                     arg.destroy();
5124                 }
5125                 else if (arg.dom) {
5126                     arg.remove();
5127                 }
5128             }
5129         }
5130     },
5131
5132     
5133     callback: function(callback, scope, args, delay){
5134         if(Ext.isFunction(callback)){
5135             args = args || [];
5136             scope = scope || window;
5137             if (delay) {
5138                 Ext.defer(callback, delay, scope, args);
5139             } else {
5140                 callback.apply(scope, args);
5141             }
5142         }
5143     },
5144
5145     
5146     htmlEncode : function(value) {
5147         return Ext.String.htmlEncode(value);
5148     },
5149
5150     
5151     htmlDecode : function(value) {
5152          return Ext.String.htmlDecode(value);
5153     },
5154
5155     
5156     urlAppend : function(url, s) {
5157         if (!Ext.isEmpty(s)) {
5158             return url + (url.indexOf('?') === -1 ? '?' : '&') + s;
5159         }
5160         return url;
5161     }
5162 });
5163
5164
5165 Ext.ns = Ext.namespace;
5166
5167
5168 window.undefined = window.undefined;
5169
5170
5171 (function(){
5172     var check = function(regex){
5173             return regex.test(Ext.userAgent);
5174         },
5175         docMode = document.documentMode,
5176         isOpera = check(/opera/),
5177         isOpera10_5 = isOpera && check(/version\/10\.5/),
5178         isChrome = check(/\bchrome\b/),
5179         isWebKit = check(/webkit/),
5180         isSafari = !isChrome && check(/safari/),
5181         isSafari2 = isSafari && check(/applewebkit\/4/), 
5182         isSafari3 = isSafari && check(/version\/3/),
5183         isSafari4 = isSafari && check(/version\/4/),
5184         isIE = !isOpera && check(/msie/),
5185         isIE7 = isIE && (check(/msie 7/) || docMode == 7),
5186         isIE8 = isIE && (check(/msie 8/) && docMode != 7 && docMode != 9 || docMode == 8),
5187         isIE9 = isIE && (check(/msie 9/) && docMode != 7 && docMode != 8 || docMode == 9),
5188         isIE6 = isIE && check(/msie 6/),
5189         isGecko = !isWebKit && check(/gecko/),
5190         isGecko3 = isGecko && check(/rv:1\.9/),
5191         isGecko4 = isGecko && check(/rv:2\.0/),
5192         isFF3_0 = isGecko3 && check(/rv:1\.9\.0/),
5193         isFF3_5 = isGecko3 && check(/rv:1\.9\.1/),
5194         isFF3_6 = isGecko3 && check(/rv:1\.9\.2/),
5195         isWindows = check(/windows|win32/),
5196         isMac = check(/macintosh|mac os x/),
5197         isLinux = check(/linux/),
5198         scrollWidth = null,
5199         webKitVersion = isWebKit && (/webkit\/(\d+\.\d+)/.exec(Ext.userAgent));
5200
5201     
5202     try {
5203         document.execCommand("BackgroundImageCache", false, true);
5204     } catch(e) {}
5205
5206     Ext.setVersion('extjs', '4.0.1');
5207     Ext.apply(Ext, {
5208         
5209         SSL_SECURE_URL : Ext.isSecure && isIE ? 'javascript:""' : 'about:blank',
5210
5211         
5212
5213         
5214         scopeResetCSS : Ext.buildSettings.scopeResetCSS,
5215
5216         
5217         enableNestedListenerRemoval : false,
5218
5219         
5220         USE_NATIVE_JSON : false,
5221
5222         
5223         getDom : function(el, strict) {
5224             if (!el || !document) {
5225                 return null;
5226             }
5227             if (el.dom) {
5228                 return el.dom;
5229             } else {
5230                 if (typeof el == 'string') {
5231                     var e = document.getElementById(el);
5232                     
5233                     
5234                     if (e && isIE && strict) {
5235                         if (el == e.getAttribute('id')) {
5236                             return e;
5237                         } else {
5238                             return null;
5239                         }
5240                     }
5241                     return e;
5242                 } else {
5243                     return el;
5244                 }
5245             }
5246         },
5247
5248         
5249         removeNode : isIE6 || isIE7 ? function() {
5250             var d;
5251             return function(n){
5252                 if(n && n.tagName != 'BODY'){
5253                     (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
5254                     d = d || document.createElement('div');
5255                     d.appendChild(n);
5256                     d.innerHTML = '';
5257                     delete Ext.cache[n.id];
5258                 }
5259             };
5260         }() : function(n) {
5261             if (n && n.parentNode && n.tagName != 'BODY') {
5262                 (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
5263                 n.parentNode.removeChild(n);
5264                 delete Ext.cache[n.id];
5265             }
5266         },
5267
5268         
5269         isOpera : isOpera,
5270
5271         
5272         isOpera10_5 : isOpera10_5,
5273
5274         
5275         isWebKit : isWebKit,
5276
5277         
5278         isChrome : isChrome,
5279
5280         
5281         isSafari : isSafari,
5282
5283         
5284         isSafari3 : isSafari3,
5285
5286         
5287         isSafari4 : isSafari4,
5288
5289         
5290         isSafari2 : isSafari2,
5291
5292         
5293         isIE : isIE,
5294
5295         
5296         isIE6 : isIE6,
5297
5298         
5299         isIE7 : isIE7,
5300
5301         
5302         isIE8 : isIE8,
5303
5304         
5305         isIE9 : isIE9,
5306
5307         
5308         isGecko : isGecko,
5309
5310         
5311         isGecko3 : isGecko3,
5312
5313         
5314         isGecko4 : isGecko4,
5315
5316         
5317
5318         isFF3_0 : isFF3_0,
5319         
5320
5321         isFF3_5 : isFF3_5,
5322         
5323         isFF3_6 : isFF3_6,
5324
5325         
5326         isLinux : isLinux,
5327
5328         
5329         isWindows : isWindows,
5330
5331         
5332         isMac : isMac,
5333
5334         
5335         webKitVersion: webKitVersion ? parseFloat(webKitVersion[1]) : -1,
5336
5337         
5338         BLANK_IMAGE_URL : (isIE6 || isIE7) ? 'http:/' + '/www.sencha.com/s.gif' : 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
5339
5340         
5341         value : function(v, defaultValue, allowBlank){
5342             return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
5343         },
5344
5345         
5346         escapeRe : function(s) {
5347             return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
5348         },
5349
5350         
5351         addBehaviors : function(o){
5352             if(!Ext.isReady){
5353                 Ext.onReady(function(){
5354                     Ext.addBehaviors(o);
5355                 });
5356             } else {
5357                 var cache = {}, 
5358                     parts,
5359                     b,
5360                     s;
5361                 for (b in o) {
5362                     if ((parts = b.split('@'))[1]) { 
5363                         s = parts[0];
5364                         if(!cache[s]){
5365                             cache[s] = Ext.select(s);
5366                         }
5367                         cache[s].on(parts[1], o[b]);
5368                     }
5369                 }
5370                 cache = null;
5371             }
5372         },
5373
5374         
5375         getScrollBarWidth: function(force){
5376             if(!Ext.isReady){
5377                 return 0;
5378             }
5379
5380             if(force === true || scrollWidth === null){
5381                 
5382                 
5383                 
5384                 var cssClass = Ext.isIE9 ? '' : Ext.baseCSSPrefix + 'hide-offsets';
5385                     
5386                 var div = Ext.getBody().createChild('<div class="' + cssClass + '" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
5387                     child = div.child('div', true);
5388                 var w1 = child.offsetWidth;
5389                 div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
5390                 var w2 = child.offsetWidth;
5391                 div.remove();
5392                 
5393                 scrollWidth = w1 - w2 + 2;
5394             }
5395             return scrollWidth;
5396         },
5397
5398         
5399         copyTo : function(dest, source, names, usePrototypeKeys){
5400             if(typeof names == 'string'){
5401                 names = names.split(/[,;\s]/);
5402             }
5403             Ext.each(names, function(name){
5404                 if(usePrototypeKeys || source.hasOwnProperty(name)){
5405                     dest[name] = source[name];
5406                 }
5407             }, this);
5408             return dest;
5409         },
5410
5411         
5412         destroyMembers : function(o, arg1, arg2, etc){
5413             for (var i = 1, a = arguments, len = a.length; i < len; i++) {
5414                 Ext.destroy(o[a[i]]);
5415                 delete o[a[i]];
5416             }
5417         },
5418
5419         
5420         log : function (message) {
5421             var options, dump,
5422                 con = Ext.global.console,
5423                 log = Ext.log,
5424                 level = 'log',
5425                 stack,
5426                 members,
5427                 member;
5428
5429             if (!Ext.isString(message)) {
5430                 options = message;
5431                 message = options.msg || '';
5432                 level = options.level || level;
5433                 dump = options.dump;
5434                 stack = options.stack;
5435
5436                 if (dump && !(con && con.dir)) {
5437                     members = [];
5438
5439                     
5440                     
5441                     Ext.Object.each(dump, function (name, value) {
5442                         if (typeof(value) === "function") {
5443                             return;
5444                         }
5445
5446                         if (!Ext.isDefined(value) || value === null ||
5447                                 Ext.isDate(value) ||
5448                                 Ext.isString(value) || (typeof(value) == "number") ||
5449                                 Ext.isBoolean(value)) {
5450                             member = Ext.encode(value);
5451                         } else if (Ext.isArray(value)) {
5452                             member = '[ ]';
5453                         } else if (Ext.isObject(value)) {
5454                             member = '{ }';
5455                         } else {
5456                             member = 'undefined';
5457                         }
5458                         members.push(Ext.encode(name) + ': ' + member);
5459                     });
5460
5461                     if (members.length) {
5462                         message += ' \nData: {\n  ' + members.join(',\n  ') + '\n}';
5463                     }
5464                     dump = null;
5465                 }
5466             }
5467
5468             if (arguments.length > 1) {
5469                 message += Array.prototype.slice.call(arguments, 1).join('');
5470             }
5471
5472             
5473             
5474             
5475             if (con) { 
5476                 if (con[level]) {
5477                     con[level](message);
5478                 } else {
5479                     con.log(message);
5480                 }
5481
5482                 if (dump) {
5483                     con.dir(dump);
5484                 }
5485
5486                 if (stack && con.trace) {
5487                     
5488                     if (!con.firebug || level != 'error') {
5489                         con.trace();
5490                     }
5491                 }
5492             } else {
5493                 
5494                 if (level != 'log') {
5495                     message = level.toUpperCase() + ': ' + message;
5496                 }
5497
5498                 if (Ext.isOpera) {
5499                     opera.postError(message);
5500                 } else {
5501                     var out = log.out || (log.out = []),
5502                         max = log.max || (log.max = 100);
5503
5504                     if (out.length >= max) {
5505                         
5506                         
5507                         out.splice(0, out.length - 3 * Math.floor(max / 4)); 
5508                     }
5509
5510                     out.push(message);
5511                 }
5512             }
5513
5514             
5515             var counters = log.counters ||
5516                           (log.counters = { error: 0, warn: 0, info: 0, log: 0 });
5517
5518             ++counters[level];
5519         },
5520
5521         
5522         partition : function(arr, truth){
5523             var ret = [[],[]];
5524             Ext.each(arr, function(v, i, a) {
5525                 ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
5526             });
5527             return ret;
5528         },
5529
5530         
5531         invoke : function(arr, methodName){
5532             var ret = [],
5533                 args = Array.prototype.slice.call(arguments, 2);
5534             Ext.each(arr, function(v,i) {
5535                 if (v && typeof v[methodName] == 'function') {
5536                     ret.push(v[methodName].apply(v, args));
5537                 } else {
5538                     ret.push(undefined);
5539                 }
5540             });
5541             return ret;
5542         },
5543
5544         
5545         zip : function(){
5546             var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
5547                 arrs = parts[0],
5548                 fn = parts[1][0],
5549                 len = Ext.max(Ext.pluck(arrs, "length")),
5550                 ret = [];
5551
5552             for (var i = 0; i < len; i++) {
5553                 ret[i] = [];
5554                 if(fn){
5555                     ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
5556                 }else{
5557                     for (var j = 0, aLen = arrs.length; j < aLen; j++){
5558                         ret[i].push( arrs[j][i] );
5559                     }
5560                 }
5561             }
5562             return ret;
5563         },
5564
5565         
5566         toSentence: function(items, connector) {
5567             var length = items.length;
5568
5569             if (length <= 1) {
5570                 return items[0];
5571             } else {
5572                 var head = items.slice(0, length - 1),
5573                     tail = items[length - 1];
5574
5575                 return Ext.util.Format.format("{0} {1} {2}", head.join(", "), connector || 'and', tail);
5576             }
5577         },
5578
5579         
5580         useShims: isIE6
5581     });
5582 })();
5583
5584
5585 Ext.application = function(config) {
5586     Ext.require('Ext.app.Application');
5587
5588     Ext.onReady(function() {
5589         Ext.create('Ext.app.Application', config);
5590     });
5591 };
5592
5593
5594 (function() {
5595     Ext.ns('Ext.util');
5596
5597     Ext.util.Format = {};
5598     var UtilFormat     = Ext.util.Format,
5599         stripTagsRE    = /<\/?[^>]+>/gi,
5600         stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
5601         nl2brRe        = /\r?\n/g,
5602
5603         
5604         formatCleanRe  = /[^\d\.]/g,
5605
5606         
5607         
5608         I18NFormatCleanRe;
5609
5610     Ext.apply(UtilFormat, {
5611         
5612         thousandSeparator: ',',
5613
5614         
5615         decimalSeparator: '.',
5616
5617         
5618         currencyPrecision: 2,
5619
5620         
5621         currencySign: '$',
5622
5623         
5624         currencyAtEnd: false,
5625
5626         
5627         undef : function(value) {
5628             return value !== undefined ? value : "";
5629         },
5630
5631         
5632         defaultValue : function(value, defaultValue) {
5633             return value !== undefined && value !== '' ? value : defaultValue;
5634         },
5635
5636         
5637         substr : function(value, start, length) {
5638             return String(value).substr(start, length);
5639         },
5640
5641         
5642         lowercase : function(value) {
5643             return String(value).toLowerCase();
5644         },
5645
5646         
5647         uppercase : function(value) {
5648             return String(value).toUpperCase();
5649         },
5650
5651         
5652         usMoney : function(v) {
5653             return UtilFormat.currency(v, '$', 2);
5654         },
5655
5656         
5657         currency: function(v, currencySign, decimals, end) {
5658             var negativeSign = '',
5659                 format = ",0",
5660                 i = 0;
5661             v = v - 0;
5662             if (v < 0) {
5663                 v = -v;
5664                 negativeSign = '-';
5665             }
5666             decimals = decimals || UtilFormat.currencyPrecision;
5667             format += format + (decimals > 0 ? '.' : '');
5668             for (; i < decimals; i++) {
5669                 format += '0';
5670             }
5671             v = UtilFormat.number(v, format); 
5672             if ((end || UtilFormat.currencyAtEnd) === true) {
5673                 return Ext.String.format("{0}{1}{2}", negativeSign, v, currencySign || UtilFormat.currencySign);
5674             } else {
5675                 return Ext.String.format("{0}{1}{2}", negativeSign, currencySign || UtilFormat.currencySign, v);
5676             }
5677         },
5678
5679         
5680         date: function(v, format) {
5681             if (!v) {
5682                 return "";
5683             }
5684             if (!Ext.isDate(v)) {
5685                 v = new Date(Date.parse(v));
5686             }
5687             return Ext.Date.dateFormat(v, format || Ext.Date.defaultFormat);
5688         },
5689
5690         
5691         dateRenderer : function(format) {
5692             return function(v) {
5693                 return UtilFormat.date(v, format);
5694             };
5695         },
5696
5697         
5698         stripTags : function(v) {
5699             return !v ? v : String(v).replace(stripTagsRE, "");
5700         },
5701
5702         
5703         stripScripts : function(v) {
5704             return !v ? v : String(v).replace(stripScriptsRe, "");
5705         },
5706
5707         
5708         fileSize : function(size) {
5709             if (size < 1024) {
5710                 return size + " bytes";
5711             } else if (size < 1048576) {
5712                 return (Math.round(((size*10) / 1024))/10) + " KB";
5713             } else {
5714                 return (Math.round(((size*10) / 1048576))/10) + " MB";
5715             }
5716         },
5717
5718         
5719         math : function(){
5720             var fns = {};
5721
5722             return function(v, a){
5723                 if (!fns[a]) {
5724                     fns[a] = Ext.functionFactory('v', 'return v ' + a + ';');
5725                 }
5726                 return fns[a](v);
5727             };
5728         }(),
5729
5730         
5731         round : function(value, precision) {
5732             var result = Number(value);
5733             if (typeof precision == 'number') {
5734                 precision = Math.pow(10, precision);
5735                 result = Math.round(value * precision) / precision;
5736             }
5737             return result;
5738         },
5739
5740         
5741         number:
5742             function(v, formatString) {
5743             if (!formatString) {
5744                 return v;
5745             }
5746             v = Ext.Number.from(v, NaN);
5747             if (isNaN(v)) {
5748                 return '';
5749             }
5750             var comma = UtilFormat.thousandSeparator,
5751                 dec   = UtilFormat.decimalSeparator,
5752                 i18n  = false,
5753                 neg   = v < 0,
5754                 hasComma,
5755                 psplit;
5756
5757             v = Math.abs(v);
5758
5759             
5760             
5761             
5762             
5763             if (formatString.substr(formatString.length - 2) == '/i') {
5764                 if (!I18NFormatCleanRe) {
5765                     I18NFormatCleanRe = new RegExp('[^\\d\\' + UtilFormat.decimalSeparator + ']','g');
5766                 }
5767                 formatString = formatString.substr(0, formatString.length - 2);
5768                 i18n   = true;
5769                 hasComma = formatString.indexOf(comma) != -1;
5770                 psplit = formatString.replace(I18NFormatCleanRe, '').split(dec);
5771             } else {
5772                 hasComma = formatString.indexOf(',') != -1;
5773                 psplit = formatString.replace(formatCleanRe, '').split('.');
5774             }
5775
5776             if (1 < psplit.length) {
5777                 v = v.toFixed(psplit[1].length);
5778             } else if(2 < psplit.length) {
5779                 Ext.Error.raise({
5780                     sourceClass: "Ext.util.Format",
5781                     sourceMethod: "number",
5782                     value: v,
5783                     formatString: formatString,
5784                     msg: "Invalid number format, should have no more than 1 decimal"
5785                 });
5786             } else {
5787                 v = v.toFixed(0);
5788             }
5789
5790             var fnum = v.toString();
5791
5792             psplit = fnum.split('.');
5793
5794             if (hasComma) {
5795                 var cnum = psplit[0],
5796                     parr = [],
5797                     j    = cnum.length,
5798                     m    = Math.floor(j / 3),
5799                     n    = cnum.length % 3 || 3,
5800                     i;
5801
5802                 for (i = 0; i < j; i += n) {
5803                     if (i !== 0) {
5804                         n = 3;
5805                     }
5806
5807                     parr[parr.length] = cnum.substr(i, n);
5808                     m -= 1;
5809                 }
5810                 fnum = parr.join(comma);
5811                 if (psplit[1]) {
5812                     fnum += dec + psplit[1];
5813                 }
5814             } else {
5815                 if (psplit[1]) {
5816                     fnum = psplit[0] + dec + psplit[1];
5817                 }
5818             }
5819
5820             return (neg ? '-' : '') + formatString.replace(/[\d,?\.?]+/, fnum);
5821         },
5822
5823         
5824         numberRenderer : function(format) {
5825             return function(v) {
5826                 return UtilFormat.number(v, format);
5827             };
5828         },
5829
5830         
5831         plural : function(v, s, p) {
5832             return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
5833         },
5834
5835         
5836         nl2br : function(v) {
5837             return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
5838         },
5839
5840         
5841         capitalize: Ext.String.capitalize,
5842
5843         
5844         ellipsis: Ext.String.ellipsis,
5845
5846         
5847         format: Ext.String.format,
5848
5849         
5850         htmlDecode: Ext.String.htmlDecode,
5851
5852         
5853         htmlEncode: Ext.String.htmlEncode,
5854
5855         
5856         leftPad: Ext.String.leftPad,
5857
5858         
5859         trim : Ext.String.trim,
5860
5861         
5862         parseBox : function(box) {
5863             if (Ext.isNumber(box)) {
5864                 box = box.toString();
5865             }
5866             var parts  = box.split(' '),
5867                 ln = parts.length;
5868
5869             if (ln == 1) {
5870                 parts[1] = parts[2] = parts[3] = parts[0];
5871             }
5872             else if (ln == 2) {
5873                 parts[2] = parts[0];
5874                 parts[3] = parts[1];
5875             }
5876             else if (ln == 3) {
5877                 parts[3] = parts[1];
5878             }
5879
5880             return {
5881                 top   :parseInt(parts[0], 10) || 0,
5882                 right :parseInt(parts[1], 10) || 0,
5883                 bottom:parseInt(parts[2], 10) || 0,
5884                 left  :parseInt(parts[3], 10) || 0
5885             };
5886         },
5887
5888         
5889         escapeRegex : function(s) {
5890             return s.replace(/([\-.*+?\^${}()|\[\]\/\\])/g, "\\$1");
5891         }
5892     });
5893 })();
5894
5895
5896 Ext.ns('Ext.util');
5897
5898 Ext.util.TaskRunner = function(interval) {
5899     interval = interval || 10;
5900     var tasks = [],
5901     removeQueue = [],
5902     id = 0,
5903     running = false,
5904
5905     
5906     stopThread = function() {
5907         running = false;
5908         clearInterval(id);
5909         id = 0;
5910     },
5911
5912     
5913     startThread = function() {
5914         if (!running) {
5915             running = true;
5916             id = setInterval(runTasks, interval);
5917         }
5918     },
5919
5920     
5921     removeTask = function(t) {
5922         removeQueue.push(t);
5923         if (t.onStop) {
5924             t.onStop.apply(t.scope || t);
5925         }
5926     },
5927
5928     
5929     runTasks = function() {
5930         var rqLen = removeQueue.length,
5931             now = new Date().getTime(),
5932             i;
5933
5934         if (rqLen > 0) {
5935             for (i = 0; i < rqLen; i++) {
5936                 Ext.Array.remove(tasks, removeQueue[i]);
5937             }
5938             removeQueue = [];
5939             if (tasks.length < 1) {
5940                 stopThread();
5941                 return;
5942             }
5943         }
5944         i = 0;
5945         var t,
5946             itime,
5947             rt,
5948             len = tasks.length;
5949         for (; i < len; ++i) {
5950             t = tasks[i];
5951             itime = now - t.taskRunTime;
5952             if (t.interval <= itime) {
5953                 rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
5954                 t.taskRunTime = now;
5955                 if (rt === false || t.taskRunCount === t.repeat) {
5956                     removeTask(t);
5957                     return;
5958                 }
5959             }
5960             if (t.duration && t.duration <= (now - t.taskStartTime)) {
5961                 removeTask(t);
5962             }
5963         }
5964     };
5965
5966     
5967     this.start = function(task) {
5968         tasks.push(task);
5969         task.taskStartTime = new Date().getTime();
5970         task.taskRunTime = 0;
5971         task.taskRunCount = 0;
5972         startThread();
5973         return task;
5974     };
5975
5976     
5977     this.stop = function(task) {
5978         removeTask(task);
5979         return task;
5980     };
5981
5982     
5983     this.stopAll = function() {
5984         stopThread();
5985         for (var i = 0, len = tasks.length; i < len; i++) {
5986             if (tasks[i].onStop) {
5987                 tasks[i].onStop();
5988             }
5989         }
5990         tasks = [];
5991         removeQueue = [];
5992     };
5993 };
5994
5995
5996 Ext.TaskManager = Ext.create('Ext.util.TaskRunner');
5997
5998 Ext.is = {
5999     init : function(navigator) {
6000         var platforms = this.platforms,
6001             ln = platforms.length,
6002             i, platform;
6003
6004         navigator = navigator || window.navigator;
6005
6006         for (i = 0; i < ln; i++) {
6007             platform = platforms[i];
6008             this[platform.identity] = platform.regex.test(navigator[platform.property]);
6009         }
6010
6011         
6012         this.Desktop = this.Mac || this.Windows || (this.Linux && !this.Android);
6013         
6014         this.Tablet = this.iPad;
6015         
6016         this.Phone = !this.Desktop && !this.Tablet;
6017         
6018         this.iOS = this.iPhone || this.iPad || this.iPod;
6019         
6020         
6021         this.Standalone = !!window.navigator.standalone;
6022     },
6023     
6024     
6025     platforms: [{
6026         property: 'platform',
6027         regex: /iPhone/i,
6028         identity: 'iPhone'
6029     },
6030     
6031     
6032     {
6033         property: 'platform',
6034         regex: /iPod/i,
6035         identity: 'iPod'
6036     },
6037     
6038     
6039     {
6040         property: 'userAgent',
6041         regex: /iPad/i,
6042         identity: 'iPad'
6043     },
6044     
6045     
6046     {
6047         property: 'userAgent',
6048         regex: /Blackberry/i,
6049         identity: 'Blackberry'
6050     },
6051     
6052     
6053     {
6054         property: 'userAgent',
6055         regex: /Android/i,
6056         identity: 'Android'
6057     },
6058     
6059     
6060     {
6061         property: 'platform',
6062         regex: /Mac/i,
6063         identity: 'Mac'
6064     },
6065     
6066     
6067     {
6068         property: 'platform',
6069         regex: /Win/i,
6070         identity: 'Windows'
6071     },
6072     
6073     
6074     {
6075         property: 'platform',
6076         regex: /Linux/i,
6077         identity: 'Linux'
6078     }]
6079 };
6080
6081 Ext.is.init();
6082
6083
6084 Ext.supports = {
6085     init : function() {
6086         var doc = document,
6087             div = doc.createElement('div'),
6088             tests = this.tests,
6089             ln = tests.length,
6090             i, test;
6091
6092         div.innerHTML = [
6093             '<div style="height:30px;width:50px;">',
6094                 '<div style="height:20px;width:20px;"></div>',
6095             '</div>',
6096             '<div style="width: 200px; height: 200px; position: relative; padding: 5px;">',
6097                 '<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></div>',
6098             '</div>',
6099             '<div style="float:left; background-color:transparent;"></div>'
6100         ].join('');
6101
6102         doc.body.appendChild(div);
6103
6104         for (i = 0; i < ln; i++) {
6105             test = tests[i];
6106             this[test.identity] = test.fn.call(this, doc, div);
6107         }
6108
6109         doc.body.removeChild(div);
6110     },
6111
6112     
6113     CSS3BoxShadow: Ext.isDefined(document.documentElement.style.boxShadow),
6114
6115     
6116     ClassList: !!document.documentElement.classList,
6117
6118     
6119     OrientationChange: ((typeof window.orientation != 'undefined') && ('onorientationchange' in window)),
6120     
6121     
6122     DeviceMotion: ('ondevicemotion' in window),
6123     
6124     
6125     
6126     
6127     Touch: ('ontouchstart' in window) && (!Ext.is.Desktop),
6128
6129     tests: [
6130         
6131         {
6132             identity: 'Transitions',
6133             fn: function(doc, div) {
6134                 var prefix = [
6135                         'webkit',
6136                         'Moz',
6137                         'o',
6138                         'ms',
6139                         'khtml'
6140                     ],
6141                     TE = 'TransitionEnd',
6142                     transitionEndName = [
6143                         prefix[0] + TE,
6144                         'transitionend', 
6145                         prefix[2] + TE,
6146                         prefix[3] + TE,
6147                         prefix[4] + TE
6148                     ],
6149                     ln = prefix.length,
6150                     i = 0,
6151                     out = false;
6152                 div = Ext.get(div);
6153                 for (; i < ln; i++) {
6154                     if (div.getStyle(prefix[i] + "TransitionProperty")) {
6155                         Ext.supports.CSS3Prefix = prefix[i];
6156                         Ext.supports.CSS3TransitionEnd = transitionEndName[i];
6157                         out = true;
6158                         break;
6159                     }
6160                 }
6161                 return out;
6162             }
6163         },
6164         
6165         
6166         {
6167             identity: 'RightMargin',
6168             fn: function(doc, div) {
6169                 var view = doc.defaultView;
6170                 return !(view && view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px');
6171             }
6172         },
6173
6174         
6175         {
6176             identity: 'DisplayChangeInputSelectionBug',
6177             fn: function() {
6178                 var webKitVersion = Ext.webKitVersion;
6179                 
6180                 return 0 < webKitVersion && webKitVersion < 533;
6181             }
6182         },
6183
6184         
6185         {
6186             identity: 'DisplayChangeTextAreaSelectionBug',
6187             fn: function() {
6188                 var webKitVersion = Ext.webKitVersion;
6189
6190                 
6191                 return 0 < webKitVersion && webKitVersion < 534.24;
6192             }
6193         },
6194
6195         
6196         {
6197             identity: 'TransparentColor',
6198             fn: function(doc, div, view) {
6199                 view = doc.defaultView;
6200                 return !(view && view.getComputedStyle(div.lastChild, null).backgroundColor != 'transparent');
6201             }
6202         },
6203
6204         
6205         {
6206             identity: 'ComputedStyle',
6207             fn: function(doc, div, view) {
6208                 view = doc.defaultView;
6209                 return view && view.getComputedStyle;
6210             }
6211         },
6212         
6213         
6214         {
6215             identity: 'Svg',
6216             fn: function(doc) {
6217                 return !!doc.createElementNS && !!doc.createElementNS( "http:/" + "/www.w3.org/2000/svg", "svg").createSVGRect;
6218             }
6219         },
6220     
6221         
6222         {
6223             identity: 'Canvas',
6224             fn: function(doc) {
6225                 return !!doc.createElement('canvas').getContext;
6226             }
6227         },
6228         
6229         
6230         {
6231             identity: 'Vml',
6232             fn: function(doc) {
6233                 var d = doc.createElement("div");
6234                 d.innerHTML = "<!--[if vml]><br><br><![endif]-->";
6235                 return (d.childNodes.length == 2);
6236             }
6237         },
6238         
6239         
6240         {
6241             identity: 'Float',
6242             fn: function(doc, div) {
6243                 return !!div.lastChild.style.cssFloat;
6244             }
6245         },
6246         
6247         
6248         {
6249             identity: 'AudioTag',
6250             fn: function(doc) {
6251                 return !!doc.createElement('audio').canPlayType;
6252             }
6253         },
6254         
6255         
6256         {
6257             identity: 'History',
6258             fn: function() {
6259                 return !!(window.history && history.pushState);
6260             }
6261         },
6262         
6263         
6264         {
6265             identity: 'CSS3DTransform',
6266             fn: function() {
6267                 return (typeof WebKitCSSMatrix != 'undefined' && new WebKitCSSMatrix().hasOwnProperty('m41'));
6268             }
6269         },
6270
6271                 
6272         {
6273             identity: 'CSS3LinearGradient',
6274             fn: function(doc, div) {
6275                 var property = 'background-image:',
6276                     webkit   = '-webkit-gradient(linear, left top, right bottom, from(black), to(white))',
6277                     w3c      = 'linear-gradient(left top, black, white)',
6278                     moz      = '-moz-' + w3c,
6279                     options  = [property + webkit, property + w3c, property + moz];
6280                 
6281                 div.style.cssText = options.join(';');
6282                 
6283                 return ("" + div.style.backgroundImage).indexOf('gradient') !== -1;
6284             }
6285         },
6286         
6287         
6288         {
6289             identity: 'CSS3BorderRadius',
6290             fn: function(doc, div) {
6291                 var domPrefixes = ['borderRadius', 'BorderRadius', 'MozBorderRadius', 'WebkitBorderRadius', 'OBorderRadius', 'KhtmlBorderRadius'],
6292                     pass = false,
6293                     i;
6294                 for (i = 0; i < domPrefixes.length; i++) {
6295                     if (document.body.style[domPrefixes[i]] !== undefined) {
6296                         return true;
6297                     }
6298                 }
6299                 return pass;
6300             }
6301         },
6302         
6303         
6304         {
6305             identity: 'GeoLocation',
6306             fn: function() {
6307                 return (typeof navigator != 'undefined' && typeof navigator.geolocation != 'undefined') || (typeof google != 'undefined' && typeof google.gears != 'undefined');
6308             }
6309         },
6310         
6311         {
6312             identity: 'MouseEnterLeave',
6313             fn: function(doc, div){
6314                 return ('onmouseenter' in div && 'onmouseleave' in div);
6315             }
6316         },
6317         
6318         {
6319             identity: 'MouseWheel',
6320             fn: function(doc, div) {
6321                 return ('onmousewheel' in div);
6322             }
6323         },
6324         
6325         {
6326             identity: 'Opacity',
6327             fn: function(doc, div){
6328                 
6329                 if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
6330                     return false;
6331                 }
6332                 div.firstChild.style.cssText = 'opacity:0.73';
6333                 return div.firstChild.style.opacity == '0.73';
6334             }
6335         },
6336         
6337         {
6338             identity: 'Placeholder',
6339             fn: function(doc) {
6340                 return 'placeholder' in doc.createElement('input');
6341             }
6342         },
6343         
6344         
6345         {
6346             identity: 'Direct2DBug',
6347             fn: function() {
6348                 return Ext.isString(document.body.style.msTransformOrigin);
6349             }
6350         },
6351         
6352         {
6353             identity: 'BoundingClientRect',
6354             fn: function(doc, div) {
6355                 return Ext.isFunction(div.getBoundingClientRect);
6356             }
6357         },
6358         {
6359             identity: 'IncludePaddingInWidthCalculation',
6360             fn: function(doc, div){
6361                 var el = Ext.get(div.childNodes[1].firstChild);
6362                 return el.getWidth() == 210;
6363             }
6364         },
6365         {
6366             identity: 'IncludePaddingInHeightCalculation',
6367             fn: function(doc, div){
6368                 var el = Ext.get(div.childNodes[1].firstChild);
6369                 return el.getHeight() == 210;
6370             }
6371         },
6372         
6373         
6374         {
6375             identity: 'ArraySort',
6376             fn: function() {
6377                 var a = [1,2,3,4,5].sort(function(){ return 0; });
6378                 return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
6379             }
6380         },
6381         
6382         {
6383             identity: 'Range',
6384             fn: function() {
6385                 return !!document.createRange;
6386             }
6387         },
6388         
6389         {
6390             identity: 'CreateContextualFragment',
6391             fn: function() {
6392                 var range = Ext.supports.Range ? document.createRange() : false;
6393                 
6394                 return range && !!range.createContextualFragment;
6395             }
6396         },
6397
6398         
6399         {
6400             identity: 'WindowOnError',
6401             fn: function () {
6402                 
6403                 return Ext.isIE || Ext.isGecko || Ext.webKitVersion >= 534.16; 
6404             }
6405         }
6406     ]
6407 };
6408
6409
6410
6411
6412
6413 Ext.ns('Ext.core');
6414 Ext.core.DomHelper = function(){
6415     var tempTableEl = null,
6416         emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
6417         tableRe = /^table|tbody|tr|td$/i,
6418         confRe = /tag|children|cn|html$/i,
6419         tableElRe = /td|tr|tbody/i,
6420         endRe = /end/i,
6421         pub,
6422         
6423         afterbegin = 'afterbegin',
6424         afterend = 'afterend',
6425         beforebegin = 'beforebegin',
6426         beforeend = 'beforeend',
6427         ts = '<table>',
6428         te = '</table>',
6429         tbs = ts+'<tbody>',
6430         tbe = '</tbody>'+te,
6431         trs = tbs + '<tr>',
6432         tre = '</tr>'+tbe;
6433
6434     
6435     function doInsert(el, o, returnElement, pos, sibling, append){
6436         el = Ext.getDom(el);
6437         var newNode;
6438         if (pub.useDom) {
6439             newNode = createDom(o, null);
6440             if (append) {
6441                 el.appendChild(newNode);
6442             } else {
6443                 (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
6444             }
6445         } else {
6446             newNode = Ext.core.DomHelper.insertHtml(pos, el, Ext.core.DomHelper.createHtml(o));
6447         }
6448         return returnElement ? Ext.get(newNode, true) : newNode;
6449     }
6450     
6451     function createDom(o, parentNode){
6452         var el,
6453             doc = document,
6454             useSet,
6455             attr,
6456             val,
6457             cn;
6458
6459         if (Ext.isArray(o)) {                       
6460             el = doc.createDocumentFragment(); 
6461             for (var i = 0, l = o.length; i < l; i++) {
6462                 createDom(o[i], el);
6463             }
6464         } else if (typeof o == 'string') {         
6465             el = doc.createTextNode(o);
6466         } else {
6467             el = doc.createElement( o.tag || 'div' );
6468             useSet = !!el.setAttribute; 
6469             for (attr in o) {
6470                 if(!confRe.test(attr)){
6471                     val = o[attr];
6472                     if(attr == 'cls'){
6473                         el.className = val;
6474                     }else{
6475                         if(useSet){
6476                             el.setAttribute(attr, val);
6477                         }else{
6478                             el[attr] = val;
6479                         }
6480                     }
6481                 }
6482             }
6483             Ext.core.DomHelper.applyStyles(el, o.style);
6484
6485             if ((cn = o.children || o.cn)) {
6486                 createDom(cn, el);
6487             } else if (o.html) {
6488                 el.innerHTML = o.html;
6489             }
6490         }
6491         if(parentNode){
6492            parentNode.appendChild(el);
6493         }
6494         return el;
6495     }
6496
6497     
6498     function createHtml(o){
6499         var b = '',
6500             attr,
6501             val,
6502             key,
6503             cn,
6504             i;
6505
6506         if(typeof o == "string"){
6507             b = o;
6508         } else if (Ext.isArray(o)) {
6509             for (i=0; i < o.length; i++) {
6510                 if(o[i]) {
6511                     b += createHtml(o[i]);
6512                 }
6513             }
6514         } else {
6515             b += '<' + (o.tag = o.tag || 'div');
6516             for (attr in o) {
6517                 val = o[attr];
6518                 if(!confRe.test(attr)){
6519                     if (typeof val == "object") {
6520                         b += ' ' + attr + '="';
6521                         for (key in val) {
6522                             b += key + ':' + val[key] + ';';
6523                         }
6524                         b += '"';
6525                     }else{
6526                         b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
6527                     }
6528                 }
6529             }
6530             
6531             if (emptyTags.test(o.tag)) {
6532                 b += '/>';
6533             } else {
6534                 b += '>';
6535                 if ((cn = o.children || o.cn)) {
6536                     b += createHtml(cn);
6537                 } else if(o.html){
6538                     b += o.html;
6539                 }
6540                 b += '</' + o.tag + '>';
6541             }
6542         }
6543         return b;
6544     }
6545
6546     function ieTable(depth, s, h, e){
6547         tempTableEl.innerHTML = [s, h, e].join('');
6548         var i = -1,
6549             el = tempTableEl,
6550             ns;
6551         while(++i < depth){
6552             el = el.firstChild;
6553         }
6554
6555         ns = el.nextSibling;
6556         if (ns){
6557             var df = document.createDocumentFragment();
6558             while(el){
6559                 ns = el.nextSibling;
6560                 df.appendChild(el);
6561                 el = ns;
6562             }
6563             el = df;
6564         }
6565         return el;
6566     }
6567
6568     
6569     function insertIntoTable(tag, where, el, html) {
6570         var node,
6571             before;
6572
6573         tempTableEl = tempTableEl || document.createElement('div');
6574
6575         if(tag == 'td' && (where == afterbegin || where == beforeend) ||
6576            !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
6577             return null;
6578         }
6579         before = where == beforebegin ? el :
6580                  where == afterend ? el.nextSibling :
6581                  where == afterbegin ? el.firstChild : null;
6582
6583         if (where == beforebegin || where == afterend) {
6584             el = el.parentNode;
6585         }
6586
6587         if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
6588             node = ieTable(4, trs, html, tre);
6589         } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
6590                    (tag == 'tr' && (where == beforebegin || where == afterend))) {
6591             node = ieTable(3, tbs, html, tbe);
6592         } else {
6593             node = ieTable(2, ts, html, te);
6594         }
6595         el.insertBefore(node, before);
6596         return node;
6597     }
6598     
6599        
6600     function createContextualFragment(html){
6601         var div = document.createElement("div"),
6602             fragment = document.createDocumentFragment(),
6603             i = 0,
6604             length, childNodes;
6605         
6606         div.innerHTML = html;
6607         childNodes = div.childNodes;
6608         length = childNodes.length;
6609
6610         for (; i < length; i++) {
6611             fragment.appendChild(childNodes[i].cloneNode(true));
6612         }
6613
6614         return fragment;
6615     }
6616     
6617     pub = {
6618         
6619         markup : function(o){
6620             return createHtml(o);
6621         },
6622
6623         
6624         applyStyles : function(el, styles){
6625             if (styles) {
6626                 el = Ext.fly(el);
6627                 if (typeof styles == "function") {
6628                     styles = styles.call();
6629                 }
6630                 if (typeof styles == "string") {
6631                     styles = Ext.core.Element.parseStyles(styles);
6632                 }
6633                 if (typeof styles == "object") {
6634                     el.setStyle(styles);
6635                 }
6636             }
6637         },
6638
6639         
6640         insertHtml : function(where, el, html){
6641             var hash = {},
6642                 hashVal,
6643                 range,
6644                 rangeEl,
6645                 setStart,
6646                 frag,
6647                 rs;
6648
6649             where = where.toLowerCase();
6650             
6651             hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
6652             hash[afterend] = ['AfterEnd', 'nextSibling'];
6653             
6654             
6655             if (el.insertAdjacentHTML) {
6656                 if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
6657                     return rs;
6658                 }
6659                 
6660                 
6661                 hash[afterbegin] = ['AfterBegin', 'firstChild'];
6662                 hash[beforeend] = ['BeforeEnd', 'lastChild'];
6663                 if ((hashVal = hash[where])) {
6664                     el.insertAdjacentHTML(hashVal[0], html);
6665                     return el[hashVal[1]];
6666                 }
6667             
6668             } else {
6669                 
6670                 if (Ext.isTextNode(el)) {
6671                     where = where === 'afterbegin' ? 'beforebegin' : where; 
6672                     where = where === 'beforeend' ? 'afterend' : where;
6673                 }
6674                 range = Ext.supports.CreateContextualFragment ? el.ownerDocument.createRange() : undefined;
6675                 setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
6676                 if (hash[where]) {
6677                     if (range) {
6678                         range[setStart](el);
6679                         frag = range.createContextualFragment(html);
6680                     } else {
6681                         frag = createContextualFragment(html);
6682                     }
6683                     el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
6684                     return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
6685                 } else {
6686                     rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
6687                     if (el.firstChild) {
6688                         if (range) {
6689                             range[setStart](el[rangeEl]);
6690                             frag = range.createContextualFragment(html);
6691                         } else {
6692                             frag = createContextualFragment(html);
6693                         }
6694                         
6695                         if(where == afterbegin){
6696                             el.insertBefore(frag, el.firstChild);
6697                         }else{
6698                             el.appendChild(frag);
6699                         }
6700                     } else {
6701                         el.innerHTML = html;
6702                     }
6703                     return el[rangeEl];
6704                 }
6705             }
6706             Ext.Error.raise({
6707                 sourceClass: 'Ext.core.DomHelper',
6708                 sourceMethod: 'insertHtml',
6709                 htmlToInsert: html,
6710                 targetElement: el,
6711                 msg: 'Illegal insertion point reached: "' + where + '"'
6712             });
6713         },
6714
6715         
6716         insertBefore : function(el, o, returnElement){
6717             return doInsert(el, o, returnElement, beforebegin);
6718         },
6719
6720         
6721         insertAfter : function(el, o, returnElement){
6722             return doInsert(el, o, returnElement, afterend, 'nextSibling');
6723         },
6724
6725         
6726         insertFirst : function(el, o, returnElement){
6727             return doInsert(el, o, returnElement, afterbegin, 'firstChild');
6728         },
6729
6730         
6731         append : function(el, o, returnElement){
6732             return doInsert(el, o, returnElement, beforeend, '', true);
6733         },
6734
6735         
6736         overwrite : function(el, o, returnElement){
6737             el = Ext.getDom(el);
6738             el.innerHTML = createHtml(o);
6739             return returnElement ? Ext.get(el.firstChild) : el.firstChild;
6740         },
6741
6742         createHtml : createHtml,
6743         
6744         
6745         createDom: createDom,
6746         
6747         
6748         useDom : false,
6749         
6750         
6751         createTemplate : function(o){
6752             var html = Ext.core.DomHelper.createHtml(o);
6753             return Ext.create('Ext.Template', html);
6754         }
6755     };
6756     return pub;
6757 }();
6758
6759
6760
6761 Ext.ns('Ext.core');
6762
6763 Ext.core.DomQuery = Ext.DomQuery = function(){
6764     var cache = {},
6765         simpleCache = {},
6766         valueCache = {},
6767         nonSpace = /\S/,
6768         trimRe = /^\s+|\s+$/g,
6769         tplRe = /\{(\d+)\}/g,
6770         modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
6771         tagTokenRe = /^(#)?([\w-\*]+)/,
6772         nthRe = /(\d*)n\+?(\d*)/,
6773         nthRe2 = /\D/,
6774         
6775     
6776     
6777     isIE = window.ActiveXObject ? true : false,
6778     key = 30803;
6779
6780     
6781     
6782     eval("var batch = 30803;");
6783
6784     
6785     
6786     function child(parent, index){
6787         var i = 0,
6788             n = parent.firstChild;
6789         while(n){
6790             if(n.nodeType == 1){
6791                if(++i == index){
6792                    return n;
6793                }
6794             }
6795             n = n.nextSibling;
6796         }
6797         return null;
6798     }
6799
6800     
6801     function next(n){
6802         while((n = n.nextSibling) && n.nodeType != 1);
6803         return n;
6804     }
6805
6806     
6807     function prev(n){
6808         while((n = n.previousSibling) && n.nodeType != 1);
6809         return n;
6810     }
6811
6812     
6813     
6814     function children(parent){
6815         var n = parent.firstChild,
6816         nodeIndex = -1,
6817         nextNode;
6818         while(n){
6819             nextNode = n.nextSibling;
6820             
6821             if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
6822             parent.removeChild(n);
6823             }else{
6824             
6825             n.nodeIndex = ++nodeIndex;
6826             }
6827             n = nextNode;
6828         }
6829         return this;
6830     }
6831
6832
6833     
6834     
6835     function byClassName(nodeSet, cls){
6836         if(!cls){
6837             return nodeSet;
6838         }
6839         var result = [], ri = -1;
6840         for(var i = 0, ci; ci = nodeSet[i]; i++){
6841             if((' '+ci.className+' ').indexOf(cls) != -1){
6842                 result[++ri] = ci;
6843             }
6844         }
6845         return result;
6846     };
6847
6848     function attrValue(n, attr){
6849         
6850         if(!n.tagName && typeof n.length != "undefined"){
6851             n = n[0];
6852         }
6853         if(!n){
6854             return null;
6855         }
6856
6857         if(attr == "for"){
6858             return n.htmlFor;
6859         }
6860         if(attr == "class" || attr == "className"){
6861             return n.className;
6862         }
6863         return n.getAttribute(attr) || n[attr];
6864
6865     };
6866
6867
6868     
6869     
6870     
6871     function getNodes(ns, mode, tagName){
6872         var result = [], ri = -1, cs;
6873         if(!ns){
6874             return result;
6875         }
6876         tagName = tagName || "*";
6877         
6878         if(typeof ns.getElementsByTagName != "undefined"){
6879             ns = [ns];
6880         }
6881
6882         
6883         
6884         if(!mode){
6885             for(var i = 0, ni; ni = ns[i]; i++){
6886                 cs = ni.getElementsByTagName(tagName);
6887                 for(var j = 0, ci; ci = cs[j]; j++){
6888                     result[++ri] = ci;
6889                 }
6890             }
6891         
6892         
6893         } else if(mode == "/" || mode == ">"){
6894             var utag = tagName.toUpperCase();
6895             for(var i = 0, ni, cn; ni = ns[i]; i++){
6896                 cn = ni.childNodes;
6897                 for(var j = 0, cj; cj = cn[j]; j++){
6898                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
6899                         result[++ri] = cj;
6900                     }
6901                 }
6902             }
6903         
6904         
6905         }else if(mode == "+"){
6906             var utag = tagName.toUpperCase();
6907             for(var i = 0, n; n = ns[i]; i++){
6908                 while((n = n.nextSibling) && n.nodeType != 1);
6909                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
6910                     result[++ri] = n;
6911                 }
6912             }
6913         
6914         
6915         }else if(mode == "~"){
6916             var utag = tagName.toUpperCase();
6917             for(var i = 0, n; n = ns[i]; i++){
6918                 while((n = n.nextSibling)){
6919                     if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
6920                         result[++ri] = n;
6921                     }
6922                 }
6923             }
6924         }
6925         return result;
6926     }
6927
6928     function concat(a, b){
6929         if(b.slice){
6930             return a.concat(b);
6931         }
6932         for(var i = 0, l = b.length; i < l; i++){
6933             a[a.length] = b[i];
6934         }
6935         return a;
6936     }
6937
6938     function byTag(cs, tagName){
6939         if(cs.tagName || cs == document){
6940             cs = [cs];
6941         }
6942         if(!tagName){
6943             return cs;
6944         }
6945         var result = [], ri = -1;
6946         tagName = tagName.toLowerCase();
6947         for(var i = 0, ci; ci = cs[i]; i++){
6948             if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
6949                 result[++ri] = ci;
6950             }
6951         }
6952         return result;
6953     }
6954
6955     function byId(cs, id){
6956         if(cs.tagName || cs == document){
6957             cs = [cs];
6958         }
6959         if(!id){
6960             return cs;
6961         }
6962         var result = [], ri = -1;
6963         for(var i = 0, ci; ci = cs[i]; i++){
6964             if(ci && ci.id == id){
6965                 result[++ri] = ci;
6966                 return result;
6967             }
6968         }
6969         return result;
6970     }
6971
6972     
6973     
6974     function byAttribute(cs, attr, value, op, custom){
6975         var result = [],
6976             ri = -1,
6977             useGetStyle = custom == "{",
6978             fn = Ext.DomQuery.operators[op],
6979             a,
6980             xml,
6981             hasXml;
6982
6983         for(var i = 0, ci; ci = cs[i]; i++){
6984             
6985             if(ci.nodeType != 1){
6986                 continue;
6987             }
6988             
6989             if(!hasXml){
6990                 xml = Ext.DomQuery.isXml(ci);
6991                 hasXml = true;
6992             }
6993
6994             
6995             if(!xml){
6996                 if(useGetStyle){
6997                     a = Ext.DomQuery.getStyle(ci, attr);
6998                 } else if (attr == "class" || attr == "className"){
6999                     a = ci.className;
7000                 } else if (attr == "for"){
7001                     a = ci.htmlFor;
7002                 } else if (attr == "href"){
7003                     
7004                     
7005                     a = ci.getAttribute("href", 2);
7006                 } else{
7007                     a = ci.getAttribute(attr);
7008                 }
7009             }else{
7010                 a = ci.getAttribute(attr);
7011             }
7012             if((fn && fn(a, value)) || (!fn && a)){
7013                 result[++ri] = ci;
7014             }
7015         }
7016         return result;
7017     }
7018
7019     function byPseudo(cs, name, value){
7020         return Ext.DomQuery.pseudos[name](cs, value);
7021     }
7022
7023     function nodupIEXml(cs){
7024         var d = ++key,
7025             r;
7026         cs[0].setAttribute("_nodup", d);
7027         r = [cs[0]];
7028         for(var i = 1, len = cs.length; i < len; i++){
7029             var c = cs[i];
7030             if(!c.getAttribute("_nodup") != d){
7031                 c.setAttribute("_nodup", d);
7032                 r[r.length] = c;
7033             }
7034         }
7035         for(var i = 0, len = cs.length; i < len; i++){
7036             cs[i].removeAttribute("_nodup");
7037         }
7038         return r;
7039     }
7040
7041     function nodup(cs){
7042         if(!cs){
7043             return [];
7044         }
7045         var len = cs.length, c, i, r = cs, cj, ri = -1;
7046         if(!len || typeof cs.nodeType != "undefined" || len == 1){
7047             return cs;
7048         }
7049         if(isIE && typeof cs[0].selectSingleNode != "undefined"){
7050             return nodupIEXml(cs);
7051         }
7052         var d = ++key;
7053         cs[0]._nodup = d;
7054         for(i = 1; c = cs[i]; i++){
7055             if(c._nodup != d){
7056                 c._nodup = d;
7057             }else{
7058                 r = [];
7059                 for(var j = 0; j < i; j++){
7060                     r[++ri] = cs[j];
7061                 }
7062                 for(j = i+1; cj = cs[j]; j++){
7063                     if(cj._nodup != d){
7064                         cj._nodup = d;
7065                         r[++ri] = cj;
7066                     }
7067                 }
7068                 return r;
7069             }
7070         }
7071         return r;
7072     }
7073
7074     function quickDiffIEXml(c1, c2){
7075         var d = ++key,
7076             r = [];
7077         for(var i = 0, len = c1.length; i < len; i++){
7078             c1[i].setAttribute("_qdiff", d);
7079         }
7080         for(var i = 0, len = c2.length; i < len; i++){
7081             if(c2[i].getAttribute("_qdiff") != d){
7082                 r[r.length] = c2[i];
7083             }
7084         }
7085         for(var i = 0, len = c1.length; i < len; i++){
7086            c1[i].removeAttribute("_qdiff");
7087         }
7088         return r;
7089     }
7090
7091     function quickDiff(c1, c2){
7092         var len1 = c1.length,
7093             d = ++key,
7094             r = [];
7095         if(!len1){
7096             return c2;
7097         }
7098         if(isIE && typeof c1[0].selectSingleNode != "undefined"){
7099             return quickDiffIEXml(c1, c2);
7100         }
7101         for(var i = 0; i < len1; i++){
7102             c1[i]._qdiff = d;
7103         }
7104         for(var i = 0, len = c2.length; i < len; i++){
7105             if(c2[i]._qdiff != d){
7106                 r[r.length] = c2[i];
7107             }
7108         }
7109         return r;
7110     }
7111
7112     function quickId(ns, mode, root, id){
7113         if(ns == root){
7114            var d = root.ownerDocument || root;
7115            return d.getElementById(id);
7116         }
7117         ns = getNodes(ns, mode, "*");
7118         return byId(ns, id);
7119     }
7120
7121     return {
7122         getStyle : function(el, name){
7123             return Ext.fly(el).getStyle(name);
7124         },
7125         
7126         compile : function(path, type){
7127             type = type || "select";
7128
7129             
7130             var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
7131                 mode,
7132                 lastPath,
7133                 matchers = Ext.DomQuery.matchers,
7134                 matchersLn = matchers.length,
7135                 modeMatch,
7136                 
7137                 lmode = path.match(modeRe);
7138
7139             if(lmode && lmode[1]){
7140                 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
7141                 path = path.replace(lmode[1], "");
7142             }
7143
7144             
7145             while(path.substr(0, 1)=="/"){
7146                 path = path.substr(1);
7147             }
7148
7149             while(path && lastPath != path){
7150                 lastPath = path;
7151                 var tokenMatch = path.match(tagTokenRe);
7152                 if(type == "select"){
7153                     if(tokenMatch){
7154                         
7155                         if(tokenMatch[1] == "#"){
7156                             fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';
7157                         }else{
7158                             fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';
7159                         }
7160                         path = path.replace(tokenMatch[0], "");
7161                     }else if(path.substr(0, 1) != '@'){
7162                         fn[fn.length] = 'n = getNodes(n, mode, "*");';
7163                     }
7164                 
7165                 }else{
7166                     if(tokenMatch){
7167                         if(tokenMatch[1] == "#"){
7168                             fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';
7169                         }else{
7170                             fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';
7171                         }
7172                         path = path.replace(tokenMatch[0], "");
7173                     }
7174                 }
7175                 while(!(modeMatch = path.match(modeRe))){
7176                     var matched = false;
7177                     for(var j = 0; j < matchersLn; j++){
7178                         var t = matchers[j];
7179                         var m = path.match(t.re);
7180                         if(m){
7181                             fn[fn.length] = t.select.replace(tplRe, function(x, i){
7182                                 return m[i];
7183                             });
7184                             path = path.replace(m[0], "");
7185                             matched = true;
7186                             break;
7187                         }
7188                     }
7189                     
7190                     if(!matched){
7191                         Ext.Error.raise({
7192                             sourceClass: 'Ext.DomQuery',
7193                             sourceMethod: 'compile',
7194                             msg: 'Error parsing selector. Parsing failed at "' + path + '"'
7195                         });
7196                     }
7197                 }
7198                 if(modeMatch[1]){
7199                     fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';
7200                     path = path.replace(modeMatch[1], "");
7201                 }
7202             }
7203             
7204             fn[fn.length] = "return nodup(n);\n}";
7205
7206             
7207             eval(fn.join(""));
7208             return f;
7209         },
7210
7211         
7212         jsSelect: function(path, root, type){
7213             
7214             root = root || document;
7215
7216             if(typeof root == "string"){
7217                 root = document.getElementById(root);
7218             }
7219             var paths = path.split(","),
7220                 results = [];
7221
7222             
7223             for(var i = 0, len = paths.length; i < len; i++){
7224                 var subPath = paths[i].replace(trimRe, "");
7225                 
7226                 if(!cache[subPath]){
7227                     cache[subPath] = Ext.DomQuery.compile(subPath);
7228                     if(!cache[subPath]){
7229                         Ext.Error.raise({
7230                             sourceClass: 'Ext.DomQuery',
7231                             sourceMethod: 'jsSelect',
7232                             msg: subPath + ' is not a valid selector'
7233                         });
7234                     }
7235                 }
7236                 var result = cache[subPath](root);
7237                 if(result && result != document){
7238                     results = results.concat(result);
7239                 }
7240             }
7241
7242             
7243             
7244             if(paths.length > 1){
7245                 return nodup(results);
7246             }
7247             return results;
7248         },
7249
7250         isXml: function(el) {
7251             var docEl = (el ? el.ownerDocument || el : 0).documentElement;
7252             return docEl ? docEl.nodeName !== "HTML" : false;
7253         },
7254
7255         
7256         select : document.querySelectorAll ? function(path, root, type) {
7257             root = root || document;
7258             if (!Ext.DomQuery.isXml(root)) {
7259             try {
7260                 var cs = root.querySelectorAll(path);
7261                 return Ext.Array.toArray(cs);
7262             }
7263             catch (ex) {}
7264             }
7265             return Ext.DomQuery.jsSelect.call(this, path, root, type);
7266         } : function(path, root, type) {
7267             return Ext.DomQuery.jsSelect.call(this, path, root, type);
7268         },
7269
7270         
7271         selectNode : function(path, root){
7272             return Ext.DomQuery.select(path, root)[0];
7273         },
7274
7275         
7276         selectValue : function(path, root, defaultValue){
7277             path = path.replace(trimRe, "");
7278             if(!valueCache[path]){
7279                 valueCache[path] = Ext.DomQuery.compile(path, "select");
7280             }
7281             var n = valueCache[path](root), v;
7282             n = n[0] ? n[0] : n;
7283
7284             
7285             
7286             
7287             
7288             if (typeof n.normalize == 'function') n.normalize();
7289
7290             v = (n && n.firstChild ? n.firstChild.nodeValue : null);
7291             return ((v === null||v === undefined||v==='') ? defaultValue : v);
7292         },
7293
7294         
7295         selectNumber : function(path, root, defaultValue){
7296             var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
7297             return parseFloat(v);
7298         },
7299
7300         
7301         is : function(el, ss){
7302             if(typeof el == "string"){
7303                 el = document.getElementById(el);
7304             }
7305             var isArray = Ext.isArray(el),
7306                 result = Ext.DomQuery.filter(isArray ? el : [el], ss);
7307             return isArray ? (result.length == el.length) : (result.length > 0);
7308         },
7309
7310         
7311         filter : function(els, ss, nonMatches){
7312             ss = ss.replace(trimRe, "");
7313             if(!simpleCache[ss]){
7314                 simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
7315             }
7316             var result = simpleCache[ss](els);
7317             return nonMatches ? quickDiff(result, els) : result;
7318         },
7319
7320         
7321         matchers : [{
7322                 re: /^\.([\w-]+)/,
7323                 select: 'n = byClassName(n, " {1} ");'
7324             }, {
7325                 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
7326                 select: 'n = byPseudo(n, "{1}", "{2}");'
7327             },{
7328                 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
7329                 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
7330             }, {
7331                 re: /^#([\w-]+)/,
7332                 select: 'n = byId(n, "{1}");'
7333             },{
7334                 re: /^@([\w-]+)/,
7335                 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
7336             }
7337         ],
7338
7339         
7340         operators : {
7341             "=" : function(a, v){
7342                 return a == v;
7343             },
7344             "!=" : function(a, v){
7345                 return a != v;
7346             },
7347             "^=" : function(a, v){
7348                 return a && a.substr(0, v.length) == v;
7349             },
7350             "$=" : function(a, v){
7351                 return a && a.substr(a.length-v.length) == v;
7352             },
7353             "*=" : function(a, v){
7354                 return a && a.indexOf(v) !== -1;
7355             },
7356             "%=" : function(a, v){
7357                 return (a % v) == 0;
7358             },
7359             "|=" : function(a, v){
7360                 return a && (a == v || a.substr(0, v.length+1) == v+'-');
7361             },
7362             "~=" : function(a, v){
7363                 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
7364             }
7365         },
7366
7367         
7368         pseudos : {
7369             "first-child" : function(c){
7370                 var r = [], ri = -1, n;
7371                 for(var i = 0, ci; ci = n = c[i]; i++){
7372                     while((n = n.previousSibling) && n.nodeType != 1);
7373                     if(!n){
7374                         r[++ri] = ci;
7375                     }
7376                 }
7377                 return r;
7378             },
7379
7380             "last-child" : function(c){
7381                 var r = [], ri = -1, n;
7382                 for(var i = 0, ci; ci = n = c[i]; i++){
7383                     while((n = n.nextSibling) && n.nodeType != 1);
7384                     if(!n){
7385                         r[++ri] = ci;
7386                     }
7387                 }
7388                 return r;
7389             },
7390
7391             "nth-child" : function(c, a) {
7392                 var r = [], ri = -1,
7393                     m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
7394                     f = (m[1] || 1) - 0, l = m[2] - 0;
7395                 for(var i = 0, n; n = c[i]; i++){
7396                     var pn = n.parentNode;
7397                     if (batch != pn._batch) {
7398                         var j = 0;
7399                         for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
7400                             if(cn.nodeType == 1){
7401                                cn.nodeIndex = ++j;
7402                             }
7403                         }
7404                         pn._batch = batch;
7405                     }
7406                     if (f == 1) {
7407                         if (l == 0 || n.nodeIndex == l){
7408                             r[++ri] = n;
7409                         }
7410                     } else if ((n.nodeIndex + l) % f == 0){
7411                         r[++ri] = n;
7412                     }
7413                 }
7414
7415                 return r;
7416             },
7417
7418             "only-child" : function(c){
7419                 var r = [], ri = -1;;
7420                 for(var i = 0, ci; ci = c[i]; i++){
7421                     if(!prev(ci) && !next(ci)){
7422                         r[++ri] = ci;
7423                     }
7424                 }
7425                 return r;
7426             },
7427
7428             "empty" : function(c){
7429                 var r = [], ri = -1;
7430                 for(var i = 0, ci; ci = c[i]; i++){
7431                     var cns = ci.childNodes, j = 0, cn, empty = true;
7432                     while(cn = cns[j]){
7433                         ++j;
7434                         if(cn.nodeType == 1 || cn.nodeType == 3){
7435                             empty = false;
7436                             break;
7437                         }
7438                     }
7439                     if(empty){
7440                         r[++ri] = ci;
7441                     }
7442                 }
7443                 return r;
7444             },
7445
7446             "contains" : function(c, v){
7447                 var r = [], ri = -1;
7448                 for(var i = 0, ci; ci = c[i]; i++){
7449                     if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
7450                         r[++ri] = ci;
7451                     }
7452                 }
7453                 return r;
7454             },
7455
7456             "nodeValue" : function(c, v){
7457                 var r = [], ri = -1;
7458                 for(var i = 0, ci; ci = c[i]; i++){
7459                     if(ci.firstChild && ci.firstChild.nodeValue == v){
7460                         r[++ri] = ci;
7461                     }
7462                 }
7463                 return r;
7464             },
7465
7466             "checked" : function(c){
7467                 var r = [], ri = -1;
7468                 for(var i = 0, ci; ci = c[i]; i++){
7469                     if(ci.checked == true){
7470                         r[++ri] = ci;
7471                     }
7472                 }
7473                 return r;
7474             },
7475
7476             "not" : function(c, ss){
7477                 return Ext.DomQuery.filter(c, ss, true);
7478             },
7479
7480             "any" : function(c, selectors){
7481                 var ss = selectors.split('|'),
7482                     r = [], ri = -1, s;
7483                 for(var i = 0, ci; ci = c[i]; i++){
7484                     for(var j = 0; s = ss[j]; j++){
7485                         if(Ext.DomQuery.is(ci, s)){
7486                             r[++ri] = ci;
7487                             break;
7488                         }
7489                     }
7490                 }
7491                 return r;
7492             },
7493
7494             "odd" : function(c){
7495                 return this["nth-child"](c, "odd");
7496             },
7497
7498             "even" : function(c){
7499                 return this["nth-child"](c, "even");
7500             },
7501
7502             "nth" : function(c, a){
7503                 return c[a-1] || [];
7504             },
7505
7506             "first" : function(c){
7507                 return c[0] || [];
7508             },
7509
7510             "last" : function(c){
7511                 return c[c.length-1] || [];
7512             },
7513
7514             "has" : function(c, ss){
7515                 var s = Ext.DomQuery.select,
7516                     r = [], ri = -1;
7517                 for(var i = 0, ci; ci = c[i]; i++){
7518                     if(s(ss, ci).length > 0){
7519                         r[++ri] = ci;
7520                     }
7521                 }
7522                 return r;
7523             },
7524
7525             "next" : function(c, ss){
7526                 var is = Ext.DomQuery.is,
7527                     r = [], ri = -1;
7528                 for(var i = 0, ci; ci = c[i]; i++){
7529                     var n = next(ci);
7530                     if(n && is(n, ss)){
7531                         r[++ri] = ci;
7532                     }
7533                 }
7534                 return r;
7535             },
7536
7537             "prev" : function(c, ss){
7538                 var is = Ext.DomQuery.is,
7539                     r = [], ri = -1;
7540                 for(var i = 0, ci; ci = c[i]; i++){
7541                     var n = prev(ci);
7542                     if(n && is(n, ss)){
7543                         r[++ri] = ci;
7544                     }
7545                 }
7546                 return r;
7547             }
7548         }
7549     };
7550 }();
7551
7552
7553 Ext.query = Ext.DomQuery.select;
7554
7555
7556  (function() {
7557     var DOC = document,
7558         EC = Ext.cache;
7559
7560     Ext.Element = Ext.core.Element = function(element, forceNew) {
7561         var dom = typeof element == "string" ? DOC.getElementById(element) : element,
7562         id;
7563
7564         if (!dom) {
7565             return null;
7566         }
7567
7568         id = dom.id;
7569
7570         if (!forceNew && id && EC[id]) {
7571             
7572             return EC[id].el;
7573         }
7574
7575         
7576         this.dom = dom;
7577
7578         
7579         this.id = id || Ext.id(dom);
7580     };
7581
7582     var DH = Ext.core.DomHelper,
7583     El = Ext.core.Element;
7584
7585
7586     El.prototype = {
7587         
7588         set: function(o, useSet) {
7589             var el = this.dom,
7590                 attr,
7591                 val;
7592             useSet = (useSet !== false) && !!el.setAttribute;
7593
7594             for (attr in o) {
7595                 if (o.hasOwnProperty(attr)) {
7596                     val = o[attr];
7597                     if (attr == 'style') {
7598                         DH.applyStyles(el, val);
7599                     } else if (attr == 'cls') {
7600                         el.className = val;
7601                     } else if (useSet) {
7602                         el.setAttribute(attr, val);
7603                     } else {
7604                         el[attr] = val;
7605                     }
7606                 }
7607             }
7608             return this;
7609         },
7610
7611         
7612         
7613         
7614         
7615         
7616         
7617         
7618         
7619         
7620         
7621         
7622
7623         
7624         
7625         
7626         
7627
7628
7629         
7630         
7631         
7632         
7633         
7634         
7635         
7636
7637         
7638         
7639         
7640         
7641         
7642         
7643         
7644
7645         
7646         
7647         
7648         
7649
7650         
7651         
7652         
7653         
7654         
7655         
7656         
7657         
7658
7659         
7660         defaultUnit: "px",
7661
7662         
7663         is: function(simpleSelector) {
7664             return Ext.DomQuery.is(this.dom, simpleSelector);
7665         },
7666
7667         
7668         focus: function(defer,
7669                         
7670                         dom) {
7671             var me = this;
7672             dom = dom || me.dom;
7673             try {
7674                 if (Number(defer)) {
7675                     Ext.defer(me.focus, defer, null, [null, dom]);
7676                 } else {
7677                     dom.focus();
7678                 }
7679             } catch(e) {}
7680             return me;
7681         },
7682
7683         
7684         blur: function() {
7685             try {
7686                 this.dom.blur();
7687             } catch(e) {}
7688             return this;
7689         },
7690
7691         
7692         getValue: function(asNumber) {
7693             var val = this.dom.value;
7694             return asNumber ? parseInt(val, 10) : val;
7695         },
7696
7697         
7698         addListener: function(eventName, fn, scope, options) {
7699             Ext.EventManager.on(this.dom, eventName, fn, scope || this, options);
7700             return this;
7701         },
7702
7703         
7704         removeListener: function(eventName, fn, scope) {
7705             Ext.EventManager.un(this.dom, eventName, fn, scope || this);
7706             return this;
7707         },
7708
7709         
7710         removeAllListeners: function() {
7711             Ext.EventManager.removeAll(this.dom);
7712             return this;
7713         },
7714
7715         
7716         purgeAllListeners: function() {
7717             Ext.EventManager.purgeElement(this);
7718             return this;
7719         },
7720
7721         
7722         addUnits: function(size, units) {
7723
7724             
7725             if (Ext.isNumber(size)) {
7726                 return size + (units || this.defaultUnit || 'px');
7727             }
7728
7729             
7730             if (size === "" || size == "auto" || size === undefined || size === null) {
7731                 return size || '';
7732             }
7733
7734             
7735             if (!unitPattern.test(size)) {
7736                 if (Ext.isDefined(Ext.global.console)) {
7737                     Ext.global.console.warn("Warning, size detected as NaN on Element.addUnits.");
7738                 }
7739                 return size || '';
7740             }
7741             return size;
7742         },
7743
7744         
7745         isBorderBox: function() {
7746             return Ext.isBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()];
7747         },
7748
7749         
7750         remove: function() {
7751             var me = this,
7752             dom = me.dom;
7753
7754             if (dom) {
7755                 delete me.dom;
7756                 Ext.removeNode(dom);
7757             }
7758         },
7759
7760         
7761         hover: function(overFn, outFn, scope, options) {
7762             var me = this;
7763             me.on('mouseenter', overFn, scope || me.dom, options);
7764             me.on('mouseleave', outFn, scope || me.dom, options);
7765             return me;
7766         },
7767
7768         
7769         contains: function(el) {
7770             return ! el ? false: Ext.core.Element.isAncestor(this.dom, el.dom ? el.dom: el);
7771         },
7772
7773         
7774         getAttributeNS: function(ns, name) {
7775             return this.getAttribute(name, ns);
7776         },
7777
7778         
7779         getAttribute: (Ext.isIE && !(Ext.isIE9 && document.documentMode === 9)) ?
7780         function(name, ns) {
7781             var d = this.dom,
7782             type;
7783             if(ns) {
7784                 type = typeof d[ns + ":" + name];
7785                 if (type != 'undefined' && type != 'unknown') {
7786                     return d[ns + ":" + name] || null;
7787                 }
7788                 return null;
7789             }
7790             if (name === "for") {
7791                 name = "htmlFor";
7792             }
7793             return d[name] || null;
7794         }: function(name, ns) {
7795             var d = this.dom;
7796             if (ns) {
7797                return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name);
7798             }
7799             return  d.getAttribute(name) || d[name] || null;
7800         },
7801
7802         
7803         update: function(html) {
7804             if (this.dom) {
7805                 this.dom.innerHTML = html;
7806             }
7807             return this;
7808         }
7809     };
7810
7811     var ep = El.prototype;
7812
7813     El.addMethods = function(o) {
7814         Ext.apply(ep, o);
7815     };
7816
7817     
7818     ep.on = ep.addListener;
7819
7820     
7821     ep.un = ep.removeListener;
7822
7823     
7824     ep.clearListeners = ep.removeAllListeners;
7825
7826     
7827     ep.destroy = ep.remove;
7828
7829     
7830     ep.autoBoxAdjust = true;
7831
7832     
7833     var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
7834     docEl;
7835
7836     
7837     El.get = function(el) {
7838         var ex,
7839         elm,
7840         id;
7841         if (!el) {
7842             return null;
7843         }
7844         if (typeof el == "string") {
7845             
7846             if (! (elm = DOC.getElementById(el))) {
7847                 return null;
7848             }
7849             if (EC[el] && EC[el].el) {
7850                 ex = EC[el].el;
7851                 ex.dom = elm;
7852             } else {
7853                 ex = El.addToCache(new El(elm));
7854             }
7855             return ex;
7856         } else if (el.tagName) {
7857             
7858             if (! (id = el.id)) {
7859                 id = Ext.id(el);
7860             }
7861             if (EC[id] && EC[id].el) {
7862                 ex = EC[id].el;
7863                 ex.dom = el;
7864             } else {
7865                 ex = El.addToCache(new El(el));
7866             }
7867             return ex;
7868         } else if (el instanceof El) {
7869             if (el != docEl) {
7870                 
7871                 
7872                 
7873                 if (Ext.isIE && (el.id == undefined || el.id == '')) {
7874                     el.dom = el.dom;
7875                 } else {
7876                     el.dom = DOC.getElementById(el.id) || el.dom;
7877                 }
7878             }
7879             return el;
7880         } else if (el.isComposite) {
7881             return el;
7882         } else if (Ext.isArray(el)) {
7883             return El.select(el);
7884         } else if (el == DOC) {
7885             
7886             if (!docEl) {
7887                 var f = function() {};
7888                 f.prototype = El.prototype;
7889                 docEl = new f();
7890                 docEl.dom = DOC;
7891             }
7892             return docEl;
7893         }
7894         return null;
7895     };
7896
7897     El.addToCache = function(el, id) {
7898         if (el) {
7899             id = id || el.id;
7900             EC[id] = {
7901                 el: el,
7902                 data: {},
7903                 events: {}
7904             };
7905         }
7906         return el;
7907     };
7908
7909     
7910     El.data = function(el, key, value) {
7911         el = El.get(el);
7912         if (!el) {
7913             return null;
7914         }
7915         var c = EC[el.id].data;
7916         if (arguments.length == 2) {
7917             return c[key];
7918         } else {
7919             return (c[key] = value);
7920         }
7921     };
7922
7923     
7924     
7925     
7926     function garbageCollect() {
7927         if (!Ext.enableGarbageCollector) {
7928             clearInterval(El.collectorThreadId);
7929         } else {
7930             var eid,
7931             el,
7932             d,
7933             o;
7934
7935             for (eid in EC) {
7936                 if (!EC.hasOwnProperty(eid)) {
7937                     continue;
7938                 }
7939                 o = EC[eid];
7940                 if (o.skipGarbageCollection) {
7941                     continue;
7942                 }
7943                 el = o.el;
7944                 d = el.dom;
7945                 
7946                 
7947                 
7948                 
7949                 
7950                 
7951                 
7952                 
7953                 
7954                 
7955                 
7956                 
7957                 
7958                 
7959                 
7960                 
7961                 
7962                 if (!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))) {
7963                     if (d && Ext.enableListenerCollection) {
7964                         Ext.EventManager.removeAll(d);
7965                     }
7966                     delete EC[eid];
7967                 }
7968             }
7969             
7970             if (Ext.isIE) {
7971                 var t = {};
7972                 for (eid in EC) {
7973                     if (!EC.hasOwnProperty(eid)) {
7974                         continue;
7975                     }
7976                     t[eid] = EC[eid];
7977                 }
7978                 EC = Ext.cache = t;
7979             }
7980         }
7981     }
7982     El.collectorThreadId = setInterval(garbageCollect, 30000);
7983
7984     var flyFn = function() {};
7985     flyFn.prototype = El.prototype;
7986
7987     
7988     El.Flyweight = function(dom) {
7989         this.dom = dom;
7990     };
7991
7992     El.Flyweight.prototype = new flyFn();
7993     El.Flyweight.prototype.isFlyweight = true;
7994     El._flyweights = {};
7995
7996     
7997     El.fly = function(el, named) {
7998         var ret = null;
7999         named = named || '_global';
8000         el = Ext.getDom(el);
8001         if (el) {
8002             (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
8003             ret = El._flyweights[named];
8004         }
8005         return ret;
8006     };
8007
8008     
8009     Ext.get = El.get;
8010
8011     
8012     Ext.fly = El.fly;
8013
8014     
8015     var noBoxAdjust = Ext.isStrict ? {
8016         select: 1
8017     }: {
8018         input: 1,
8019         select: 1,
8020         textarea: 1
8021     };
8022     if (Ext.isIE || Ext.isGecko) {
8023         noBoxAdjust['button'] = 1;
8024     }
8025 })();
8026
8027
8028 Ext.core.Element.addMethods({
8029     
8030     findParent : function(simpleSelector, maxDepth, returnEl) {
8031         var p = this.dom,
8032             b = document.body,
8033             depth = 0,
8034             stopEl;
8035
8036         maxDepth = maxDepth || 50;
8037         if (isNaN(maxDepth)) {
8038             stopEl = Ext.getDom(maxDepth);
8039             maxDepth = Number.MAX_VALUE;
8040         }
8041         while (p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl) {
8042             if (Ext.DomQuery.is(p, simpleSelector)) {
8043                 return returnEl ? Ext.get(p) : p;
8044             }
8045             depth++;
8046             p = p.parentNode;
8047         }
8048         return null;
8049     },
8050     
8051     
8052     findParentNode : function(simpleSelector, maxDepth, returnEl) {
8053         var p = Ext.fly(this.dom.parentNode, '_internal');
8054         return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
8055     },
8056
8057     
8058     up : function(simpleSelector, maxDepth) {
8059         return this.findParentNode(simpleSelector, maxDepth, true);
8060     },
8061
8062     
8063     select : function(selector) {
8064         return Ext.core.Element.select(selector, false,  this.dom);
8065     },
8066
8067     
8068     query : function(selector) {
8069         return Ext.DomQuery.select(selector, this.dom);
8070     },
8071
8072     
8073     down : function(selector, returnDom) {
8074         var n = Ext.DomQuery.selectNode(selector, this.dom);
8075         return returnDom ? n : Ext.get(n);
8076     },
8077
8078     
8079     child : function(selector, returnDom) {
8080         var node,
8081             me = this,
8082             id;
8083         id = Ext.get(me).id;
8084         
8085         id = id.replace(/[\.:]/g, "\\$0");
8086         node = Ext.DomQuery.selectNode('#' + id + " > " + selector, me.dom);
8087         return returnDom ? node : Ext.get(node);
8088     },
8089
8090      
8091     parent : function(selector, returnDom) {
8092         return this.matchNode('parentNode', 'parentNode', selector, returnDom);
8093     },
8094
8095      
8096     next : function(selector, returnDom) {
8097         return this.matchNode('nextSibling', 'nextSibling', selector, returnDom);
8098     },
8099
8100     
8101     prev : function(selector, returnDom) {
8102         return this.matchNode('previousSibling', 'previousSibling', selector, returnDom);
8103     },
8104
8105
8106     
8107     first : function(selector, returnDom) {
8108         return this.matchNode('nextSibling', 'firstChild', selector, returnDom);
8109     },
8110
8111     
8112     last : function(selector, returnDom) {
8113         return this.matchNode('previousSibling', 'lastChild', selector, returnDom);
8114     },
8115
8116     matchNode : function(dir, start, selector, returnDom) {
8117         if (!this.dom) {
8118             return null;
8119         }
8120         
8121         var n = this.dom[start];
8122         while (n) {
8123             if (n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))) {
8124                 return !returnDom ? Ext.get(n) : n;
8125             }
8126             n = n[dir];
8127         }
8128         return null;
8129     }
8130 });
8131
8132
8133 Ext.core.Element.addMethods({
8134     
8135     appendChild : function(el) {
8136         return Ext.get(el).appendTo(this);
8137     },
8138
8139     
8140     appendTo : function(el) {
8141         Ext.getDom(el).appendChild(this.dom);
8142         return this;
8143     },
8144
8145     
8146     insertBefore : function(el) {
8147         el = Ext.getDom(el);
8148         el.parentNode.insertBefore(this.dom, el);
8149         return this;
8150     },
8151
8152     
8153     insertAfter : function(el) {
8154         el = Ext.getDom(el);
8155         el.parentNode.insertBefore(this.dom, el.nextSibling);
8156         return this;
8157     },
8158
8159     
8160     insertFirst : function(el, returnDom) {
8161         el = el || {};
8162         if (el.nodeType || el.dom || typeof el == 'string') { 
8163             el = Ext.getDom(el);
8164             this.dom.insertBefore(el, this.dom.firstChild);
8165             return !returnDom ? Ext.get(el) : el;
8166         }
8167         else { 
8168             return this.createChild(el, this.dom.firstChild, returnDom);
8169         }
8170     },
8171
8172     
8173     insertSibling: function(el, where, returnDom){
8174         var me = this, rt,
8175         isAfter = (where || 'before').toLowerCase() == 'after',
8176         insertEl;
8177
8178         if(Ext.isArray(el)){
8179             insertEl = me;
8180             Ext.each(el, function(e) {
8181                 rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
8182                 if(isAfter){
8183                     insertEl = rt;
8184                 }
8185             });
8186             return rt;
8187         }
8188
8189         el = el || {};
8190
8191         if(el.nodeType || el.dom){
8192             rt = me.dom.parentNode.insertBefore(Ext.getDom(el), isAfter ? me.dom.nextSibling : me.dom);
8193             if (!returnDom) {
8194                 rt = Ext.get(rt);
8195             }
8196         }else{
8197             if (isAfter && !me.dom.nextSibling) {
8198                 rt = Ext.core.DomHelper.append(me.dom.parentNode, el, !returnDom);
8199             } else {
8200                 rt = Ext.core.DomHelper[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom);
8201             }
8202         }
8203         return rt;
8204     },
8205
8206     
8207     replace : function(el) {
8208         el = Ext.get(el);
8209         this.insertBefore(el);
8210         el.remove();
8211         return this;
8212     },
8213     
8214     
8215     replaceWith: function(el){
8216         var me = this;
8217             
8218         if(el.nodeType || el.dom || typeof el == 'string'){
8219             el = Ext.get(el);
8220             me.dom.parentNode.insertBefore(el, me.dom);
8221         }else{
8222             el = Ext.core.DomHelper.insertBefore(me.dom, el);
8223         }
8224         
8225         delete Ext.cache[me.id];
8226         Ext.removeNode(me.dom);      
8227         me.id = Ext.id(me.dom = el);
8228         Ext.core.Element.addToCache(me.isFlyweight ? new Ext.core.Element(me.dom) : me);     
8229         return me;
8230     },
8231     
8232     
8233     createChild : function(config, insertBefore, returnDom) {
8234         config = config || {tag:'div'};
8235         if (insertBefore) {
8236             return Ext.core.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8237         }
8238         else {
8239             return Ext.core.DomHelper[!this.dom.firstChild ? 'insertFirst' : 'append'](this.dom, config,  returnDom !== true);
8240         }
8241     },
8242
8243     
8244     wrap : function(config, returnDom) {
8245         var newEl = Ext.core.DomHelper.insertBefore(this.dom, config || {tag: "div"}, !returnDom),
8246             d = newEl.dom || newEl;
8247
8248         d.appendChild(this.dom);
8249         return newEl;
8250     },
8251
8252     
8253     insertHtml : function(where, html, returnEl) {
8254         var el = Ext.core.DomHelper.insertHtml(where, this.dom, html);
8255         return returnEl ? Ext.get(el) : el;
8256     }
8257 });
8258
8259
8260 (function(){
8261     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>';
8262     
8263     var supports = Ext.supports,
8264         view = document.defaultView,
8265         opacityRe = /alpha\(opacity=(.*)\)/i,
8266         trimRe = /^\s+|\s+$/g,
8267         spacesRe = /\s+/,
8268         wordsRe = /\w/g,
8269         adjustDirect2DTableRe = /table-row|table-.*-group/,
8270         INTERNAL = '_internal',
8271         PADDING = 'padding',
8272         MARGIN = 'margin',
8273         BORDER = 'border',
8274         LEFT = '-left',
8275         RIGHT = '-right',
8276         TOP = '-top',
8277         BOTTOM = '-bottom',
8278         WIDTH = '-width',
8279         MATH = Math,
8280         HIDDEN = 'hidden',
8281         ISCLIPPED = 'isClipped',
8282         OVERFLOW = 'overflow',
8283         OVERFLOWX = 'overflow-x',
8284         OVERFLOWY = 'overflow-y',
8285         ORIGINALCLIP = 'originalClip',
8286         
8287         borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
8288         paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
8289         margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
8290         data = Ext.core.Element.data;
8291
8292     Ext.override(Ext.core.Element, {
8293         
8294         
8295         
8296         adjustWidth : function(width) {
8297             var me = this,
8298                 isNum = (typeof width == 'number');
8299                 
8300             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
8301                width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
8302             }
8303             return (isNum && width < 0) ? 0 : width;
8304         },
8305
8306         
8307         adjustHeight : function(height) {
8308             var me = this,
8309                 isNum = (typeof height == "number");
8310                 
8311             if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
8312                height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
8313             }
8314             return (isNum && height < 0) ? 0 : height;
8315         },
8316
8317
8318         
8319         addCls : function(className){
8320             var me = this,
8321                 cls = [],
8322                 space = ((me.dom.className.replace(trimRe, '') == '') ? "" : " "),
8323                 i, len, v;
8324             if (!Ext.isDefined(className)) {
8325                 return me;
8326             }
8327             
8328             if (!Ext.isArray(className)) {
8329                 if (typeof className === 'string') {
8330                     className = className.replace(trimRe, '').split(spacesRe);
8331                     if (className.length === 1) {
8332                         className = className[0];
8333                         if (!me.hasCls(className)) {
8334                             me.dom.className += space + className;
8335                         }
8336                     } else {
8337                         this.addCls(className);
8338                     }
8339                 }
8340             } else {
8341                 for (i = 0, len = className.length; i < len; i++) {
8342                     v = className[i];
8343                     if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
8344                         cls.push(v);
8345                     }
8346                 }
8347                 if (cls.length) {
8348                     me.dom.className += space + cls.join(" ");
8349                 }
8350             }
8351             return me;
8352         },
8353
8354         
8355         removeCls : function(className){
8356             var me = this,
8357                 i, idx, len, cls, elClasses;
8358             if (!Ext.isDefined(className)) {
8359                 return me;
8360             }
8361             if (!Ext.isArray(className)){
8362                 className = className.replace(trimRe, '').split(spacesRe);
8363             }
8364             if (me.dom && me.dom.className) {
8365                 elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
8366                 for (i = 0, len = className.length; i < len; i++) {
8367                     cls = className[i];
8368                     if (typeof cls == 'string') {
8369                         cls = cls.replace(trimRe, '');
8370                         idx = Ext.Array.indexOf(elClasses, cls);
8371                         if (idx != -1) {
8372                             elClasses.splice(idx, 1);
8373                         }
8374                     }
8375                 }
8376                 me.dom.className = elClasses.join(" ");
8377             }
8378             return me;
8379         },
8380
8381         
8382         radioCls : function(className){
8383             var cn = this.dom.parentNode.childNodes,
8384                 v, i, len;
8385             className = Ext.isArray(className) ? className : [className];
8386             for (i = 0, len = cn.length; i < len; i++) {
8387                 v = cn[i];
8388                 if (v && v.nodeType == 1) {
8389                     Ext.fly(v, '_internal').removeCls(className);
8390                 }
8391             }
8392             return this.addCls(className);
8393         },
8394
8395         
8396         toggleCls : Ext.supports.ClassList ?
8397             function(className) {
8398                 this.dom.classList.toggle(Ext.String.trim(className));
8399                 return this;
8400             } :
8401             function(className) {
8402                 return this.hasCls(className) ? this.removeCls(className) : this.addCls(className);
8403             },
8404
8405         
8406         hasCls : Ext.supports.ClassList ?
8407             function(className) {
8408                 if (!className) {
8409                     return false;
8410                 }
8411                 className = className.split(spacesRe);
8412                 var ln = className.length,
8413                     i = 0;
8414                 for (; i < ln; i++) {
8415                     if (className[i] && this.dom.classList.contains(className[i])) {
8416                         return true;
8417                     }
8418                 }
8419                 return false;
8420             } :
8421             function(className){
8422                 return className && (' ' + this.dom.className + ' ').indexOf(' ' + className + ' ') != -1;
8423             },
8424
8425         
8426         replaceCls : function(oldClassName, newClassName){
8427             return this.removeCls(oldClassName).addCls(newClassName);
8428         },
8429
8430         isStyle : function(style, val) {
8431             return this.getStyle(style) == val;
8432         },
8433
8434         
8435         getStyle : function(){
8436             return view && view.getComputedStyle ?
8437                 function(prop){
8438                     var el = this.dom,
8439                         v, cs, out, display, cleaner;
8440
8441                     if(el == document){
8442                         return null;
8443                     }
8444                     prop = Ext.core.Element.normalize(prop);
8445                     out = (v = el.style[prop]) ? v :
8446                            (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
8447                            
8448                     
8449                     
8450                     if(prop == 'marginRight' && out != '0px' && !supports.RightMargin){
8451                         cleaner = Ext.core.Element.getRightMarginFixCleaner(el);
8452                         display = this.getStyle('display');
8453                         el.style.display = 'inline-block';
8454                         out = view.getComputedStyle(el, '').marginRight;
8455                         el.style.display = display;
8456                         cleaner();
8457                     }
8458                     
8459                     if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.TransparentColor){
8460                         out = 'transparent';
8461                     }
8462                     return out;
8463                 } :
8464                 function(prop){
8465                     var el = this.dom,
8466                         m, cs;
8467
8468                     if (el == document) {
8469                         return null;
8470                     }
8471                     
8472                     if (prop == 'opacity') {
8473                         if (el.style.filter.match) {
8474                             m = el.style.filter.match(opacityRe);
8475                             if(m){
8476                                 var fv = parseFloat(m[1]);
8477                                 if(!isNaN(fv)){
8478                                     return fv ? fv / 100 : 0;
8479                                 }
8480                             }
8481                         }
8482                         return 1;
8483                     }
8484                     prop = Ext.core.Element.normalize(prop);
8485                     return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
8486                 };
8487         }(),
8488
8489         
8490         getColor : function(attr, defaultValue, prefix){
8491             var v = this.getStyle(attr),
8492                 color = prefix || prefix === '' ? prefix : '#',
8493                 h;
8494
8495             if(!v || (/transparent|inherit/.test(v))) {
8496                 return defaultValue;
8497             }
8498             if(/^r/.test(v)){
8499                 Ext.each(v.slice(4, v.length -1).split(','), function(s){
8500                     h = parseInt(s, 10);
8501                     color += (h < 16 ? '0' : '') + h.toString(16);
8502                 });
8503             }else{
8504                 v = v.replace('#', '');
8505                 color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
8506             }
8507             return(color.length > 5 ? color.toLowerCase() : defaultValue);
8508         },
8509
8510         
8511         setStyle : function(prop, value){
8512             var me = this,
8513                 tmp, style;
8514
8515             if (!me.dom) {
8516                 return me;
8517             }
8518
8519             if (!Ext.isObject(prop)) {
8520                 tmp = {};
8521                 tmp[prop] = value;
8522                 prop = tmp;
8523             }
8524             for (style in prop) {
8525                 if (prop.hasOwnProperty(style)) {
8526                     value = Ext.value(prop[style], '');
8527                     if (style == 'opacity') {
8528                         me.setOpacity(value);
8529                     }
8530                     else {
8531                         me.dom.style[Ext.core.Element.normalize(style)] = value;
8532                     }
8533                 }
8534             }
8535             return me;
8536         },
8537
8538         
8539         setOpacity: function(opacity, animate) {
8540             var me = this,
8541                 dom = me.dom,
8542                 val,
8543                 style;
8544
8545             if (!me.dom) {
8546                 return me;
8547             }
8548
8549             style = me.dom.style;
8550
8551             if (!animate || !me.anim) {
8552                 if (!Ext.supports.Opacity) {
8553                     opacity = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')': '';
8554                     val = style.filter.replace(opacityRe, '').replace(trimRe, '');
8555
8556                     style.zoom = 1;
8557                     style.filter = val + (val.length > 0 ? ' ': '') + opacity;
8558                 }
8559                 else {
8560                     style.opacity = opacity;
8561                 }
8562             }
8563             else {
8564                 if (!Ext.isObject(animate)) {
8565                     animate = {
8566                         duration: 350,
8567                         easing: 'ease-in'
8568                     };
8569                 }
8570                 me.animate(Ext.applyIf({
8571                     to: {
8572                         opacity: opacity
8573                     }
8574                 },
8575                 animate));
8576             }
8577             return me;
8578         },
8579
8580
8581         
8582         clearOpacity : function(){
8583             var style = this.dom.style;
8584             if(!Ext.supports.Opacity){
8585                 if(!Ext.isEmpty(style.filter)){
8586                     style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
8587                 }
8588             }else{
8589                 style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
8590             }
8591             return this;
8592         },
8593         
8594         
8595         adjustDirect2DDimension: function(dimension) {
8596             var me = this,
8597                 dom = me.dom,
8598                 display = me.getStyle('display'),
8599                 inlineDisplay = dom.style['display'],
8600                 inlinePosition = dom.style['position'],
8601                 originIndex = dimension === 'width' ? 0 : 1,
8602                 floating;
8603                 
8604             if (display === 'inline') {
8605                 dom.style['display'] = 'inline-block';
8606             }
8607
8608             dom.style['position'] = display.match(adjustDirect2DTableRe) ? 'absolute' : 'static';
8609
8610             
8611             
8612             floating = (parseFloat(me.getStyle(dimension)) || parseFloat(dom.currentStyle.msTransformOrigin.split(' ')[originIndex]) * 2) % 1;
8613             
8614             dom.style['position'] = inlinePosition;
8615             
8616             if (display === 'inline') {
8617                 dom.style['display'] = inlineDisplay;
8618             }
8619
8620             return floating;
8621         },
8622         
8623         
8624         getHeight: function(contentHeight, preciseHeight) {
8625             var me = this,
8626                 dom = me.dom,
8627                 hidden = Ext.isIE && me.isStyle('display', 'none'),
8628                 height, overflow, style, floating;
8629
8630             
8631             
8632             if (Ext.isIEQuirks) {
8633                 style = dom.style;
8634                 overflow = style.overflow;
8635                 me.setStyle({ overflow: 'hidden'});
8636             }
8637
8638             height = dom.offsetHeight;
8639
8640             height = MATH.max(height, hidden ? 0 : dom.clientHeight) || 0;
8641
8642             
8643             if (!hidden && Ext.supports.Direct2DBug) {
8644                 floating = me.adjustDirect2DDimension('height');
8645                 if (preciseHeight) {
8646                     height += floating;
8647                 }
8648                 else if (floating > 0 && floating < 0.5) {
8649                     height++;
8650                 }
8651             }
8652
8653             if (contentHeight) {
8654                 height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
8655             }
8656
8657             if (Ext.isIEQuirks) {
8658                 me.setStyle({ overflow: overflow});
8659             }
8660
8661             if (height < 0) {
8662                 height = 0;
8663             }
8664             return height;
8665         },
8666                 
8667         
8668         getWidth: function(contentWidth, preciseWidth) {
8669             var me = this,
8670                 dom = me.dom,
8671                 hidden = Ext.isIE && me.isStyle('display', 'none'),
8672                 rect, width, overflow, style, floating, parentPosition;
8673
8674             
8675             
8676             if (Ext.isIEQuirks) {
8677                 style = dom.style;
8678                 overflow = style.overflow;
8679                 me.setStyle({overflow: 'hidden'});
8680             }
8681             
8682             
8683             if (Ext.isOpera10_5) {
8684                 if (dom.parentNode.currentStyle.position === 'relative') {
8685                     parentPosition = dom.parentNode.style.position;
8686                     dom.parentNode.style.position = 'static';
8687                     width = dom.offsetWidth;
8688                     dom.parentNode.style.position = parentPosition;
8689                 }
8690                 width = Math.max(width || 0, dom.offsetWidth);
8691             
8692             
8693             
8694             
8695             
8696             
8697             } else if (Ext.supports.BoundingClientRect) {
8698                 rect = dom.getBoundingClientRect();
8699                 width = rect.right - rect.left;
8700                 width = preciseWidth ? width : Math.ceil(width);
8701             } else {
8702                 width = dom.offsetWidth;
8703             }
8704
8705             width = MATH.max(width, hidden ? 0 : dom.clientWidth) || 0;
8706
8707             
8708             if (!hidden && Ext.supports.Direct2DBug) {
8709                 floating = me.adjustDirect2DDimension('width');
8710                 if (preciseWidth) {
8711                     width += floating;
8712                 }
8713                 else if (floating > 0 && floating < 0.5) {
8714                     width++;
8715                 }
8716             }
8717             
8718             if (contentWidth) {
8719                 width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
8720             }
8721             
8722             if (Ext.isIEQuirks) {
8723                 me.setStyle({ overflow: overflow});
8724             }
8725
8726             if (width < 0) {
8727                 width = 0;
8728             }
8729             return width;
8730         },
8731
8732         
8733         setWidth : function(width, animate){
8734             var me = this;
8735             width = me.adjustWidth(width);
8736             if (!animate || !me.anim) {
8737                 me.dom.style.width = me.addUnits(width);
8738             }
8739             else {
8740                 if (!Ext.isObject(animate)) {
8741                     animate = {};
8742                 }
8743                 me.animate(Ext.applyIf({
8744                     to: {
8745                         width: width
8746                     }
8747                 }, animate));
8748             }
8749             return me;
8750         },
8751
8752         
8753          setHeight : function(height, animate){
8754             var me = this;
8755             height = me.adjustHeight(height);
8756             if (!animate || !me.anim) {
8757                 me.dom.style.height = me.addUnits(height);
8758             }
8759             else {
8760                 if (!Ext.isObject(animate)) {
8761                     animate = {};
8762                 }
8763                 me.animate(Ext.applyIf({
8764                     to: {
8765                         height: height
8766                     }
8767                 }, animate));
8768             }
8769             return me;
8770         },
8771
8772         
8773         getBorderWidth : function(side){
8774             return this.addStyles(side, borders);
8775         },
8776
8777         
8778         getPadding : function(side){
8779             return this.addStyles(side, paddings);
8780         },
8781
8782         
8783         clip : function(){
8784             var me = this,
8785                 dom = me.dom;
8786
8787             if(!data(dom, ISCLIPPED)){
8788                 data(dom, ISCLIPPED, true);
8789                 data(dom, ORIGINALCLIP, {
8790                     o: me.getStyle(OVERFLOW),
8791                     x: me.getStyle(OVERFLOWX),
8792                     y: me.getStyle(OVERFLOWY)
8793                 });
8794                 me.setStyle(OVERFLOW, HIDDEN);
8795                 me.setStyle(OVERFLOWX, HIDDEN);
8796                 me.setStyle(OVERFLOWY, HIDDEN);
8797             }
8798             return me;
8799         },
8800
8801         
8802         unclip : function(){
8803             var me = this,
8804                 dom = me.dom,
8805                 clip;
8806
8807             if(data(dom, ISCLIPPED)){
8808                 data(dom, ISCLIPPED, false);
8809                 clip = data(dom, ORIGINALCLIP);
8810                 if(o.o){
8811                     me.setStyle(OVERFLOW, o.o);
8812                 }
8813                 if(o.x){
8814                     me.setStyle(OVERFLOWX, o.x);
8815                 }
8816                 if(o.y){
8817                     me.setStyle(OVERFLOWY, o.y);
8818                 }
8819             }
8820             return me;
8821         },
8822
8823         
8824         addStyles : function(sides, styles){
8825             var totalSize = 0,
8826                 sidesArr = sides.match(wordsRe),
8827                 i = 0,
8828                 len = sidesArr.length,
8829                 side, size;
8830             for (; i < len; i++) {
8831                 side = sidesArr[i];
8832                 size = side && parseInt(this.getStyle(styles[side]), 10);
8833                 if (size) {
8834                     totalSize += MATH.abs(size);
8835                 }
8836             }
8837             return totalSize;
8838         },
8839
8840         margins : margins,
8841         
8842         
8843         applyStyles : function(style){
8844             Ext.core.DomHelper.applyStyles(this.dom, style);
8845             return this;
8846         },
8847
8848         
8849         getStyles : function(){
8850             var styles = {},
8851                 len = arguments.length,
8852                 i = 0, style;
8853                 
8854             for(; i < len; ++i) {
8855                 style = arguments[i];
8856                 styles[style] = this.getStyle(style);
8857             }
8858             return styles;
8859         },
8860
8861        
8862         boxWrap : function(cls){
8863             cls = cls || Ext.baseCSSPrefix + 'box';
8864             var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + Ext.String.format(Ext.core.Element.boxMarkup, cls) + "</div>"));
8865             Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
8866             return el;
8867         },
8868
8869         
8870         setSize : function(width, height, animate){
8871             var me = this;
8872             if (Ext.isObject(width)){ 
8873                 height = width.height;
8874                 width = width.width;
8875             }
8876             width = me.adjustWidth(width);
8877             height = me.adjustHeight(height);
8878             if(!animate || !me.anim){
8879                 me.dom.style.width = me.addUnits(width);
8880                 me.dom.style.height = me.addUnits(height);
8881             }
8882             else {
8883                 if (!Ext.isObject(animate)) {
8884                     animate = {};
8885                 }
8886                 me.animate(Ext.applyIf({
8887                     to: {
8888                         width: width,
8889                         height: height
8890                     }
8891                 }, animate));
8892             }
8893             return me;
8894         },
8895
8896         
8897         getComputedHeight : function(){
8898             var me = this,
8899                 h = Math.max(me.dom.offsetHeight, me.dom.clientHeight);
8900             if(!h){
8901                 h = parseFloat(me.getStyle('height')) || 0;
8902                 if(!me.isBorderBox()){
8903                     h += me.getFrameWidth('tb');
8904                 }
8905             }
8906             return h;
8907         },
8908
8909         
8910         getComputedWidth : function(){
8911             var me = this,
8912                 w = Math.max(me.dom.offsetWidth, me.dom.clientWidth);
8913                 
8914             if(!w){
8915                 w = parseFloat(me.getStyle('width')) || 0;
8916                 if(!me.isBorderBox()){
8917                     w += me.getFrameWidth('lr');
8918                 }
8919             }
8920             return w;
8921         },
8922
8923         
8924         getFrameWidth : function(sides, onlyContentBox){
8925             return onlyContentBox && this.isBorderBox() ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8926         },
8927
8928         
8929         addClsOnOver : function(className){
8930             var dom = this.dom;
8931             this.hover(
8932                 function(){
8933                     Ext.fly(dom, INTERNAL).addCls(className);
8934                 },
8935                 function(){
8936                     Ext.fly(dom, INTERNAL).removeCls(className);
8937                 }
8938             );
8939             return this;
8940         },
8941
8942         
8943         addClsOnFocus : function(className){
8944             var me = this,
8945                 dom = me.dom;
8946             me.on("focus", function(){
8947                 Ext.fly(dom, INTERNAL).addCls(className);
8948             });
8949             me.on("blur", function(){
8950                 Ext.fly(dom, INTERNAL).removeCls(className);
8951             });
8952             return me;
8953         },
8954
8955         
8956         addClsOnClick : function(className){
8957             var dom = this.dom;
8958             this.on("mousedown", function(){
8959                 Ext.fly(dom, INTERNAL).addCls(className);
8960                 var d = Ext.getDoc(),
8961                     fn = function(){
8962                         Ext.fly(dom, INTERNAL).removeCls(className);
8963                         d.removeListener("mouseup", fn);
8964                     };
8965                 d.on("mouseup", fn);
8966             });
8967             return this;
8968         },
8969
8970         
8971
8972         getViewSize : function(){
8973             var me = this,
8974                 dom = me.dom,
8975                 isDoc = (dom == Ext.getDoc().dom || dom == Ext.getBody().dom),
8976                 style, overflow, ret;
8977
8978             
8979             if (isDoc) {
8980                 ret = {
8981                     width : Ext.core.Element.getViewWidth(),
8982                     height : Ext.core.Element.getViewHeight()
8983                 };
8984
8985             
8986             }
8987             else {
8988                 
8989                 
8990                 if (Ext.isIE6 || Ext.isIEQuirks) {
8991                     style = dom.style;
8992                     overflow = style.overflow;
8993                     me.setStyle({ overflow: 'hidden'});
8994                 }
8995                 ret = {
8996                     width : dom.clientWidth,
8997                     height : dom.clientHeight
8998                 };
8999                 if (Ext.isIE6 || Ext.isIEQuirks) {
9000                     me.setStyle({ overflow: overflow });
9001                 }
9002             }
9003             return ret;
9004         },
9005
9006         
9007
9008         getStyleSize : function(){
9009             var me = this,
9010                 doc = document,
9011                 d = this.dom,
9012                 isDoc = (d == doc || d == doc.body),
9013                 s = d.style,
9014                 w, h;
9015
9016             
9017             if (isDoc) {
9018                 return {
9019                     width : Ext.core.Element.getViewWidth(),
9020                     height : Ext.core.Element.getViewHeight()
9021                 };
9022             }
9023             
9024             if(s.width && s.width != 'auto'){
9025                 w = parseFloat(s.width);
9026                 if(me.isBorderBox()){
9027                    w -= me.getFrameWidth('lr');
9028                 }
9029             }
9030             
9031             if(s.height && s.height != 'auto'){
9032                 h = parseFloat(s.height);
9033                 if(me.isBorderBox()){
9034                    h -= me.getFrameWidth('tb');
9035                 }
9036             }
9037             
9038             return {width: w || me.getWidth(true), height: h || me.getHeight(true)};
9039         },
9040
9041         
9042         getSize : function(contentSize){
9043             return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
9044         },
9045
9046         
9047         repaint : function(){
9048             var dom = this.dom;
9049             this.addCls(Ext.baseCSSPrefix + 'repaint');
9050             setTimeout(function(){
9051                 Ext.fly(dom).removeCls(Ext.baseCSSPrefix + 'repaint');
9052             }, 1);
9053             return this;
9054         },
9055
9056         
9057         unselectable : function(){
9058             var me = this;
9059             me.dom.unselectable = "on";
9060
9061             me.swallowEvent("selectstart", true);
9062             me.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
9063             me.addCls(Ext.baseCSSPrefix + 'unselectable');
9064             
9065             return me;
9066         },
9067
9068         
9069         getMargin : function(side){
9070             var me = this,
9071                 hash = {t:"top", l:"left", r:"right", b: "bottom"},
9072                 o = {},
9073                 key;
9074
9075             if (!side) {
9076                 for (key in me.margins){
9077                     o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
9078                 }
9079                 return o;
9080             } else {
9081                 return me.addStyles.call(me, side, me.margins);
9082             }
9083         }
9084     });
9085 })();
9086
9087
9088 Ext.core.Element.VISIBILITY = 1;
9089
9090 Ext.core.Element.DISPLAY = 2;
9091
9092
9093 Ext.core.Element.OFFSETS = 3;
9094
9095
9096 Ext.core.Element.ASCLASS = 4;
9097
9098
9099 Ext.core.Element.visibilityCls = Ext.baseCSSPrefix + 'hide-nosize';
9100
9101 Ext.core.Element.addMethods(function(){
9102     var El = Ext.core.Element,
9103         OPACITY = "opacity",
9104         VISIBILITY = "visibility",
9105         DISPLAY = "display",
9106         HIDDEN = "hidden",
9107         OFFSETS = "offsets",
9108         ASCLASS = "asclass",
9109         NONE = "none",
9110         NOSIZE = 'nosize',
9111         ORIGINALDISPLAY = 'originalDisplay',
9112         VISMODE = 'visibilityMode',
9113         ISVISIBLE = 'isVisible',
9114         data = El.data,
9115         getDisplay = function(dom){
9116             var d = data(dom, ORIGINALDISPLAY);
9117             if(d === undefined){
9118                 data(dom, ORIGINALDISPLAY, d = '');
9119             }
9120             return d;
9121         },
9122         getVisMode = function(dom){
9123             var m = data(dom, VISMODE);
9124             if(m === undefined){
9125                 data(dom, VISMODE, m = 1);
9126             }
9127             return m;
9128         };
9129
9130     return {
9131         
9132         originalDisplay : "",
9133         visibilityMode : 1,
9134
9135         
9136         setVisibilityMode : function(visMode){
9137             data(this.dom, VISMODE, visMode);
9138             return this;
9139         },
9140
9141         
9142         isVisible : function() {
9143             var me = this,
9144                 dom = me.dom,
9145                 visible = data(dom, ISVISIBLE);
9146
9147             if(typeof visible == 'boolean'){ 
9148                 return visible;
9149             }
9150             
9151             visible = !me.isStyle(VISIBILITY, HIDDEN) &&
9152                       !me.isStyle(DISPLAY, NONE) &&
9153                       !((getVisMode(dom) == El.ASCLASS) && me.hasCls(me.visibilityCls || El.visibilityCls));
9154
9155             data(dom, ISVISIBLE, visible);
9156             return visible;
9157         },
9158
9159         
9160         setVisible : function(visible, animate){
9161             var me = this, isDisplay, isVisibility, isOffsets, isNosize,
9162                 dom = me.dom,
9163                 visMode = getVisMode(dom);
9164
9165
9166             
9167             if (typeof animate == 'string'){
9168                 switch (animate) {
9169                     case DISPLAY:
9170                         visMode = El.DISPLAY;
9171                         break;
9172                     case VISIBILITY:
9173                         visMode = El.VISIBILITY;
9174                         break;
9175                     case OFFSETS:
9176                         visMode = El.OFFSETS;
9177                         break;
9178                     case NOSIZE:
9179                     case ASCLASS:
9180                         visMode = El.ASCLASS;
9181                         break;
9182                 }
9183                 me.setVisibilityMode(visMode);
9184                 animate = false;
9185             }
9186
9187             if (!animate || !me.anim) {
9188                 if(visMode == El.ASCLASS ){
9189
9190                     me[visible?'removeCls':'addCls'](me.visibilityCls || El.visibilityCls);
9191
9192                 } else if (visMode == El.DISPLAY){
9193
9194                     return me.setDisplayed(visible);
9195
9196                 } else if (visMode == El.OFFSETS){
9197
9198                     if (!visible){
9199                         
9200                         if (!me.hideModeStyles) {
9201                             me.hideModeStyles = {
9202                                 position: me.getStyle('position'),
9203                                 top: me.getStyle('top'),
9204                                 left: me.getStyle('left')
9205                             };
9206                         }
9207                         me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
9208                     }
9209
9210                     
9211                     
9212                     else if (me.hideModeStyles) {
9213                         me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
9214                         delete me.hideModeStyles;
9215                     }
9216
9217                 }else{
9218                     me.fixDisplay();
9219                     
9220                     dom.style.visibility = visible ? '' : HIDDEN;
9221                 }
9222             }else{
9223                 
9224                 if(visible){
9225                     me.setOpacity(0.01);
9226                     me.setVisible(true);
9227                 }
9228                 if (!Ext.isObject(animate)) {
9229                     animate = {
9230                         duration: 350,
9231                         easing: 'ease-in'
9232                     };
9233                 }
9234                 me.animate(Ext.applyIf({
9235                     callback: function() {
9236                         visible || me.setVisible(false).setOpacity(1);
9237                     },
9238                     to: {
9239                         opacity: (visible) ? 1 : 0
9240                     }
9241                 }, animate));
9242             }
9243             data(dom, ISVISIBLE, visible);  
9244             return me;
9245         },
9246
9247
9248         
9249         hasMetrics  : function(){
9250             var dom = this.dom;
9251             return this.isVisible() || (getVisMode(dom) == El.OFFSETS) || (getVisMode(dom) == El.VISIBILITY);
9252         },
9253
9254         
9255         toggle : function(animate){
9256             var me = this;
9257             me.setVisible(!me.isVisible(), me.anim(animate));
9258             return me;
9259         },
9260
9261         
9262         setDisplayed : function(value) {
9263             if(typeof value == "boolean"){
9264                value = value ? getDisplay(this.dom) : NONE;
9265             }
9266             this.setStyle(DISPLAY, value);
9267             return this;
9268         },
9269
9270         
9271         fixDisplay : function(){
9272             var me = this;
9273             if (me.isStyle(DISPLAY, NONE)) {
9274                 me.setStyle(VISIBILITY, HIDDEN);
9275                 me.setStyle(DISPLAY, getDisplay(this.dom)); 
9276                 if (me.isStyle(DISPLAY, NONE)) { 
9277                     me.setStyle(DISPLAY, "block");
9278                 }
9279             }
9280         },
9281
9282         
9283         hide : function(animate){
9284             
9285             if (typeof animate == 'string'){
9286                 this.setVisible(false, animate);
9287                 return this;
9288             }
9289             this.setVisible(false, this.anim(animate));
9290             return this;
9291         },
9292
9293         
9294         show : function(animate){
9295             
9296             if (typeof animate == 'string'){
9297                 this.setVisible(true, animate);
9298                 return this;
9299             }
9300             this.setVisible(true, this.anim(animate));
9301             return this;
9302         }
9303     };
9304 }());
9305
9306 Ext.applyIf(Ext.core.Element.prototype, {
9307     
9308     animate: function(config) {
9309         var me = this;
9310         if (!me.id) {
9311             me = Ext.get(me.dom);
9312         }
9313         if (Ext.fx.Manager.hasFxBlock(me.id)) {
9314             return me;
9315         }
9316         Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(config)));
9317         return this;
9318     },
9319
9320     
9321     anim: function(config) {
9322         if (!Ext.isObject(config)) {
9323             return (config) ? {} : false;
9324         }
9325
9326         var me = this,
9327             duration = config.duration || Ext.fx.Anim.prototype.duration,
9328             easing = config.easing || 'ease',
9329             animConfig;
9330
9331         if (config.stopAnimation) {
9332             me.stopAnimation();
9333         }
9334
9335         Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
9336
9337         
9338         Ext.fx.Manager.setFxDefaults(me.id, {
9339             delay: 0
9340         });
9341
9342         animConfig = {
9343             target: me,
9344             remove: config.remove,
9345             alternate: config.alternate || false,
9346             duration: duration,
9347             easing: easing,
9348             callback: config.callback,
9349             listeners: config.listeners,
9350             iterations: config.iterations || 1,
9351             scope: config.scope,
9352             block: config.block,
9353             concurrent: config.concurrent,
9354             delay: config.delay || 0,
9355             paused: true,
9356             keyframes: config.keyframes,
9357             from: config.from || {},
9358             to: Ext.apply({}, config)
9359         };
9360         Ext.apply(animConfig.to, config.to);
9361
9362         
9363         delete animConfig.to.to;
9364         delete animConfig.to.from;
9365         delete animConfig.to.remove;
9366         delete animConfig.to.alternate;
9367         delete animConfig.to.keyframes;
9368         delete animConfig.to.iterations;
9369         delete animConfig.to.listeners;
9370         delete animConfig.to.target;
9371         delete animConfig.to.paused;
9372         delete animConfig.to.callback;
9373         delete animConfig.to.scope;
9374         delete animConfig.to.duration;
9375         delete animConfig.to.easing;
9376         delete animConfig.to.concurrent;
9377         delete animConfig.to.block;
9378         delete animConfig.to.stopAnimation;
9379         delete animConfig.to.delay;
9380         return animConfig;
9381     },
9382
9383     
9384     slideIn: function(anchor, obj, slideOut) { 
9385         var me = this,
9386             elStyle = me.dom.style,
9387             beforeAnim, wrapAnim;
9388
9389         anchor = anchor || "t";
9390         obj = obj || {};
9391
9392         beforeAnim = function() {
9393             var animScope = this,
9394                 listeners = obj.listeners,
9395                 box, position, restoreSize, wrap, anim;
9396
9397             if (!slideOut) {
9398                 me.fixDisplay();
9399             }
9400
9401             box = me.getBox();
9402             if ((anchor == 't' || anchor == 'b') && box.height == 0) {
9403                 box.height = me.dom.scrollHeight;
9404             }
9405             else if ((anchor == 'l' || anchor == 'r') && box.width == 0) {
9406                 box.width = me.dom.scrollWidth;
9407             }
9408             
9409             position = me.getPositioning();
9410             me.setSize(box.width, box.height);
9411
9412             wrap = me.wrap({
9413                 style: {
9414                     visibility: slideOut ? 'visible' : 'hidden'
9415                 }
9416             });
9417             wrap.setPositioning(position);
9418             if (wrap.isStyle('position', 'static')) {
9419                 wrap.position('relative');
9420             }
9421             me.clearPositioning('auto');
9422             wrap.clip();
9423
9424             
9425             
9426             
9427             me.setStyle({
9428                 visibility: '',
9429                 position: 'absolute'
9430             });
9431             if (slideOut) {
9432                 wrap.setSize(box.width, box.height);
9433             }
9434
9435             switch (anchor) {
9436                 case 't':
9437                     anim = {
9438                         from: {
9439                             width: box.width + 'px',
9440                             height: '0px'
9441                         },
9442                         to: {
9443                             width: box.width + 'px',
9444                             height: box.height + 'px'
9445                         }
9446                     };
9447                     elStyle.bottom = '0px';
9448                     break;
9449                 case 'l':
9450                     anim = {
9451                         from: {
9452                             width: '0px',
9453                             height: box.height + 'px'
9454                         },
9455                         to: {
9456                             width: box.width + 'px',
9457                             height: box.height + 'px'
9458                         }
9459                     };
9460                     elStyle.right = '0px';
9461                     break;
9462                 case 'r':
9463                     anim = {
9464                         from: {
9465                             x: box.x + box.width,
9466                             width: '0px',
9467                             height: box.height + 'px'
9468                         },
9469                         to: {
9470                             x: box.x,
9471                             width: box.width + 'px',
9472                             height: box.height + 'px'
9473                         }
9474                     };
9475                     break;
9476                 case 'b':
9477                     anim = {
9478                         from: {
9479                             y: box.y + box.height,
9480                             width: box.width + 'px',
9481                             height: '0px'
9482                         },
9483                         to: {
9484                             y: box.y,
9485                             width: box.width + 'px',
9486                             height: box.height + 'px'
9487                         }
9488                     };
9489                     break;
9490                 case 'tl':
9491                     anim = {
9492                         from: {
9493                             x: box.x,
9494                             y: box.y,
9495                             width: '0px',
9496                             height: '0px'
9497                         },
9498                         to: {
9499                             width: box.width + 'px',
9500                             height: box.height + 'px'
9501                         }
9502                     };
9503                     elStyle.bottom = '0px';
9504                     elStyle.right = '0px';
9505                     break;
9506                 case 'bl':
9507                     anim = {
9508                         from: {
9509                             x: box.x + box.width,
9510                             width: '0px',
9511                             height: '0px'
9512                         },
9513                         to: {
9514                             x: box.x,
9515                             width: box.width + 'px',
9516                             height: box.height + 'px'
9517                         }
9518                     };
9519                     elStyle.right = '0px';
9520                     break;
9521                 case 'br':
9522                     anim = {
9523                         from: {
9524                             x: box.x + box.width,
9525                             y: box.y + box.height,
9526                             width: '0px',
9527                             height: '0px'
9528                         },
9529                         to: {
9530                             x: box.x,
9531                             y: box.y,
9532                             width: box.width + 'px',
9533                             height: box.height + 'px'
9534                         }
9535                     };
9536                     break;
9537                 case 'tr':
9538                     anim = {
9539                         from: {
9540                             y: box.y + box.height,
9541                             width: '0px',
9542                             height: '0px'
9543                         },
9544                         to: {
9545                             y: box.y,
9546                             width: box.width + 'px',
9547                             height: box.height + 'px'
9548                         }
9549                     };
9550                     elStyle.bottom = '0px';
9551                     break;
9552             }
9553
9554             wrap.show();
9555             wrapAnim = Ext.apply({}, obj);
9556             delete wrapAnim.listeners;
9557             wrapAnim = Ext.create('Ext.fx.Anim', Ext.applyIf(wrapAnim, {
9558                 target: wrap,
9559                 duration: 500,
9560                 easing: 'ease-out',
9561                 from: slideOut ? anim.to : anim.from,
9562                 to: slideOut ? anim.from : anim.to
9563             }));
9564
9565             
9566             wrapAnim.on('afteranimate', function() {
9567                 if (slideOut) {
9568                     me.setPositioning(position);
9569                     if (obj.useDisplay) {
9570                         me.setDisplayed(false);
9571                     } else {
9572                         me.hide();   
9573                     }
9574                 }
9575                 else {
9576                     me.clearPositioning();
9577                     me.setPositioning(position);
9578                 }
9579                 if (wrap.dom) {
9580                     wrap.dom.parentNode.insertBefore(me.dom, wrap.dom); 
9581                     wrap.remove();
9582                 }
9583                 me.setSize(box.width, box.height);
9584                 animScope.end();
9585             });
9586             
9587             if (listeners) {
9588                 wrapAnim.on(listeners);
9589             }
9590         };
9591
9592         me.animate({
9593             duration: obj.duration ? obj.duration * 2 : 1000,
9594             listeners: {
9595                 beforeanimate: {
9596                     fn: beforeAnim
9597                 },
9598                 afteranimate: {
9599                     fn: function() {
9600                         if (wrapAnim && wrapAnim.running) {
9601                             wrapAnim.end();
9602                         }
9603                     }
9604                 }
9605             }
9606         });
9607         return me;
9608     },
9609
9610     
9611     
9612     slideOut: function(anchor, o) {
9613         return this.slideIn(anchor, o, true);
9614     },
9615
9616     
9617
9618     puff: function(obj) {
9619         var me = this,
9620             beforeAnim;
9621         obj = Ext.applyIf(obj || {}, {
9622             easing: 'ease-out',
9623             duration: 500,
9624             useDisplay: false
9625         });
9626
9627         beforeAnim = function() {
9628             me.clearOpacity();
9629             me.show();
9630
9631             var box = me.getBox(),
9632                 fontSize = me.getStyle('fontSize'),
9633                 position = me.getPositioning();
9634             this.to = {
9635                 width: box.width * 2,
9636                 height: box.height * 2,
9637                 x: box.x - (box.width / 2),
9638                 y: box.y - (box.height /2),
9639                 opacity: 0,
9640                 fontSize: '200%'
9641             };
9642             this.on('afteranimate',function() {
9643                 if (me.dom) {
9644                     if (obj.useDisplay) {
9645                         me.setDisplayed(false);
9646                     } else {
9647                         me.hide();
9648                     }
9649                     me.clearOpacity();  
9650                     me.setPositioning(position);
9651                     me.setStyle({fontSize: fontSize});
9652                 }
9653             });
9654         };
9655
9656         me.animate({
9657             duration: obj.duration,
9658             easing: obj.easing,
9659             listeners: {
9660                 beforeanimate: {
9661                     fn: beforeAnim
9662                 }
9663             }
9664         });
9665         return me;
9666     },
9667
9668     
9669     switchOff: function(obj) {
9670         var me = this,
9671             beforeAnim;
9672         
9673         obj = Ext.applyIf(obj || {}, {
9674             easing: 'ease-in',
9675             duration: 500,
9676             remove: false,
9677             useDisplay: false
9678         });
9679
9680         beforeAnim = function() {
9681             var animScope = this,
9682                 size = me.getSize(),
9683                 xy = me.getXY(),
9684                 keyframe, position;
9685             me.clearOpacity();
9686             me.clip();
9687             position = me.getPositioning();
9688
9689             keyframe = Ext.create('Ext.fx.Animator', {
9690                 target: me,
9691                 duration: obj.duration,
9692                 easing: obj.easing,
9693                 keyframes: {
9694                     33: {
9695                         opacity: 0.3
9696                     },
9697                     66: {
9698                         height: 1,
9699                         y: xy[1] + size.height / 2
9700                     },
9701                     100: {
9702                         width: 1,
9703                         x: xy[0] + size.width / 2
9704                     }
9705                 }
9706             });
9707             keyframe.on('afteranimate', function() {
9708                 if (obj.useDisplay) {
9709                     me.setDisplayed(false);
9710                 } else {
9711                     me.hide();
9712                 }  
9713                 me.clearOpacity();
9714                 me.setPositioning(position);
9715                 me.setSize(size);
9716                 animScope.end();
9717             });
9718         };
9719         me.animate({
9720             duration: (obj.duration * 2),
9721             listeners: {
9722                 beforeanimate: {
9723                     fn: beforeAnim
9724                 }
9725             }
9726         });
9727         return me;
9728     },
9729
9730    
9731     frame : function(color, count, obj){
9732         var me = this,
9733             beforeAnim;
9734
9735         color = color || '#C3DAF9';
9736         count = count || 1;
9737         obj = obj || {};
9738
9739         beforeAnim = function() {
9740             me.show();
9741             var animScope = this,
9742                 box = me.getBox(),
9743                 proxy = Ext.getBody().createChild({
9744                     style: {
9745                         position : 'absolute',
9746                         'pointer-events': 'none',
9747                         'z-index': 35000,
9748                         border : '0px solid ' + color
9749                     }
9750                 }),
9751                 proxyAnim;
9752             proxyAnim = Ext.create('Ext.fx.Anim', {
9753                 target: proxy,
9754                 duration: obj.duration || 1000,
9755                 iterations: count,
9756                 from: {
9757                     top: box.y,
9758                     left: box.x,
9759                     borderWidth: 0,
9760                     opacity: 1,
9761                     height: box.height,
9762                     width: box.width
9763                 },
9764                 to: {
9765                     top: box.y - 20,
9766                     left: box.x - 20,
9767                     borderWidth: 10,
9768                     opacity: 0,
9769                     height: box.height + 40,
9770                     width: box.width + 40
9771                 }
9772             });
9773             proxyAnim.on('afteranimate', function() {
9774                 proxy.remove();
9775                 animScope.end();
9776             });
9777         };
9778
9779         me.animate({
9780             duration: (obj.duration * 2) || 2000,
9781             listeners: {
9782                 beforeanimate: {
9783                     fn: beforeAnim
9784                 }
9785             }
9786         });
9787         return me;
9788     },
9789
9790     
9791     ghost: function(anchor, obj) {
9792         var me = this,
9793             beforeAnim;
9794
9795         anchor = anchor || "b";
9796         beforeAnim = function() {
9797             var width = me.getWidth(),
9798                 height = me.getHeight(),
9799                 xy = me.getXY(),
9800                 position = me.getPositioning(),
9801                 to = {
9802                     opacity: 0
9803                 };
9804             switch (anchor) {
9805                 case 't':
9806                     to.y = xy[1] - height;
9807                     break;
9808                 case 'l':
9809                     to.x = xy[0] - width;
9810                     break;
9811                 case 'r':
9812                     to.x = xy[0] + width;
9813                     break;
9814                 case 'b':
9815                     to.y = xy[1] + height;
9816                     break;
9817                 case 'tl':
9818                     to.x = xy[0] - width;
9819                     to.y = xy[1] - height;
9820                     break;
9821                 case 'bl':
9822                     to.x = xy[0] - width;
9823                     to.y = xy[1] + height;
9824                     break;
9825                 case 'br':
9826                     to.x = xy[0] + width;
9827                     to.y = xy[1] + height;
9828                     break;
9829                 case 'tr':
9830                     to.x = xy[0] + width;
9831                     to.y = xy[1] - height;
9832                     break;
9833             }
9834             this.to = to;
9835             this.on('afteranimate', function () {
9836                 if (me.dom) {
9837                     me.hide();
9838                     me.clearOpacity();
9839                     me.setPositioning(position);
9840                 }
9841             });
9842         };
9843
9844         me.animate(Ext.applyIf(obj || {}, {
9845             duration: 500,
9846             easing: 'ease-out',
9847             listeners: {
9848                 beforeanimate: {
9849                     fn: beforeAnim
9850                 }
9851             }
9852         }));
9853         return me;
9854     },
9855
9856      
9857     highlight: function(color, o) {
9858         var me = this,
9859             dom = me.dom,
9860             from = {},
9861             restore, to, attr, lns, event, fn;
9862
9863         o = o || {};
9864         lns = o.listeners || {};
9865         attr = o.attr || 'backgroundColor';
9866         from[attr] = color || 'ffff9c';
9867         
9868         if (!o.to) {
9869             to = {};
9870             to[attr] = o.endColor || me.getColor(attr, 'ffffff', '');
9871         }
9872         else {
9873             to = o.to;
9874         }
9875         
9876         
9877         o.listeners = Ext.apply(Ext.apply({}, lns), {
9878             beforeanimate: function() {
9879                 restore = dom.style[attr];
9880                 me.clearOpacity();
9881                 me.show();
9882                 
9883                 event = lns.beforeanimate;
9884                 if (event) {
9885                     fn = event.fn || event;
9886                     return fn.apply(event.scope || lns.scope || window, arguments);
9887                 }
9888             },
9889             afteranimate: function() {
9890                 if (dom) {
9891                     dom.style[attr] = restore;
9892                 }
9893                 
9894                 event = lns.afteranimate;
9895                 if (event) {
9896                     fn = event.fn || event;
9897                     fn.apply(event.scope || lns.scope || window, arguments);
9898                 }
9899             }
9900         });
9901
9902         me.animate(Ext.apply({}, o, {
9903             duration: 1000,
9904             easing: 'ease-in',
9905             from: from,
9906             to: to
9907         }));
9908         return me;
9909     },
9910
9911    
9912     pause: function(ms) {
9913         var me = this;
9914         Ext.fx.Manager.setFxDefaults(me.id, {
9915             delay: ms
9916         });
9917         return me;
9918     },
9919
9920    
9921     fadeIn: function(o) {
9922         this.animate(Ext.apply({}, o, {
9923             opacity: 1
9924         }));
9925         return this;
9926     },
9927
9928    
9929     fadeOut: function(o) {
9930         this.animate(Ext.apply({}, o, {
9931             opacity: 0
9932         }));
9933         return this;
9934     },
9935
9936    
9937     scale: function(w, h, o) {
9938         this.animate(Ext.apply({}, o, {
9939             width: w,
9940             height: h
9941         }));
9942         return this;
9943     },
9944
9945    
9946     shift: function(config) {
9947         this.animate(config);
9948         return this;
9949     }
9950 });
9951
9952
9953 Ext.applyIf(Ext.core.Element, {
9954     unitRe: /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
9955     camelRe: /(-[a-z])/gi,
9956     opacityRe: /alpha\(opacity=(.*)\)/i,
9957     cssRe: /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
9958     propertyCache: {},
9959     defaultUnit : "px",
9960     borders: {l: 'border-left-width', r: 'border-right-width', t: 'border-top-width', b: 'border-bottom-width'},
9961     paddings: {l: 'padding-left', r: 'padding-right', t: 'padding-top', b: 'padding-bottom'},
9962     margins: {l: 'margin-left', r: 'margin-right', t: 'margin-top', b: 'margin-bottom'},
9963
9964     
9965     addUnits : Ext.core.Element.prototype.addUnits,
9966
9967     
9968     parseBox : function(box) {
9969         if (Ext.isObject(box)) {
9970             return {
9971                 top: box.top || 0,
9972                 right: box.right || 0,
9973                 bottom: box.bottom || 0,
9974                 left: box.left || 0
9975             };
9976         } else {
9977             if (typeof box != 'string') {
9978                 box = box.toString();
9979             }
9980             var parts  = box.split(' '),
9981                 ln = parts.length;
9982     
9983             if (ln == 1) {
9984                 parts[1] = parts[2] = parts[3] = parts[0];
9985             }
9986             else if (ln == 2) {
9987                 parts[2] = parts[0];
9988                 parts[3] = parts[1];
9989             }
9990             else if (ln == 3) {
9991                 parts[3] = parts[1];
9992             }
9993     
9994             return {
9995                 top   :parseFloat(parts[0]) || 0,
9996                 right :parseFloat(parts[1]) || 0,
9997                 bottom:parseFloat(parts[2]) || 0,
9998                 left  :parseFloat(parts[3]) || 0
9999             };
10000         }
10001         
10002     },
10003     
10004     
10005     unitizeBox : function(box, units) {
10006         var A = this.addUnits,
10007             B = this.parseBox(box);
10008             
10009         return A(B.top, units) + ' ' +
10010                A(B.right, units) + ' ' +
10011                A(B.bottom, units) + ' ' +
10012                A(B.left, units);
10013         
10014     },
10015
10016     
10017     camelReplaceFn : function(m, a) {
10018         return a.charAt(1).toUpperCase();
10019     },
10020
10021     
10022     normalize : function(prop) {
10023         if (prop == 'float') {
10024             prop = Ext.supports.Float ? 'cssFloat' : 'styleFloat';
10025         }
10026         return this.propertyCache[prop] || (this.propertyCache[prop] = prop.replace(this.camelRe, this.camelReplaceFn));
10027     },
10028
10029     
10030     getDocumentHeight: function() {
10031         return Math.max(!Ext.isStrict ? document.body.scrollHeight : document.documentElement.scrollHeight, this.getViewportHeight());
10032     },
10033
10034     
10035     getDocumentWidth: function() {
10036         return Math.max(!Ext.isStrict ? document.body.scrollWidth : document.documentElement.scrollWidth, this.getViewportWidth());
10037     },
10038
10039     
10040     getViewportHeight: function(){
10041         return window.innerHeight;
10042     },
10043
10044     
10045     getViewportWidth : function() {
10046         return window.innerWidth;
10047     },
10048
10049     
10050     getViewSize : function() {
10051         return {
10052             width: window.innerWidth,
10053             height: window.innerHeight
10054         };
10055     },
10056
10057     
10058     getOrientation : function() {
10059         if (Ext.supports.OrientationChange) {
10060             return (window.orientation == 0) ? 'portrait' : 'landscape';
10061         }
10062         
10063         return (window.innerHeight > window.innerWidth) ? 'portrait' : 'landscape';
10064     },
10065
10066     
10067     fromPoint: function(x, y) {
10068         return Ext.get(document.elementFromPoint(x, y));
10069     },
10070     
10071     
10072     parseStyles: function(styles){
10073         var out = {},
10074             cssRe = this.cssRe,
10075             matches;
10076             
10077         if (styles) {
10078             
10079             
10080             
10081             
10082             cssRe.lastIndex = 0;
10083             while ((matches = cssRe.exec(styles))) {
10084                 out[matches[1]] = matches[2];
10085             }
10086         }
10087         return out;
10088     }
10089 });
10090
10091
10092 Ext.CompositeElementLite = function(els, root){
10093     
10094     this.elements = [];
10095     this.add(els, root);
10096     this.el = new Ext.core.Element.Flyweight();
10097 };
10098
10099 Ext.CompositeElementLite.prototype = {
10100     isComposite: true,
10101
10102     
10103     getElement : function(el){
10104         
10105         var e = this.el;
10106         e.dom = el;
10107         e.id = el.id;
10108         return e;
10109     },
10110
10111     
10112     transformElement : function(el){
10113         return Ext.getDom(el);
10114     },
10115
10116     
10117     getCount : function(){
10118         return this.elements.length;
10119     },
10120     
10121     add : function(els, root){
10122         var me = this,
10123             elements = me.elements;
10124         if(!els){
10125             return this;
10126         }
10127         if(typeof els == "string"){
10128             els = Ext.core.Element.selectorFunction(els, root);
10129         }else if(els.isComposite){
10130             els = els.elements;
10131         }else if(!Ext.isIterable(els)){
10132             els = [els];
10133         }
10134
10135         for(var i = 0, len = els.length; i < len; ++i){
10136             elements.push(me.transformElement(els[i]));
10137         }
10138         return me;
10139     },
10140
10141     invoke : function(fn, args){
10142         var me = this,
10143             els = me.elements,
10144             len = els.length,
10145             e,
10146             i;
10147
10148         for(i = 0; i < len; i++) {
10149             e = els[i];
10150             if(e){
10151                 Ext.core.Element.prototype[fn].apply(me.getElement(e), args);
10152             }
10153         }
10154         return me;
10155     },
10156     
10157     item : function(index){
10158         var me = this,
10159             el = me.elements[index],
10160             out = null;
10161
10162         if(el){
10163             out = me.getElement(el);
10164         }
10165         return out;
10166     },
10167
10168     
10169     addListener : function(eventName, handler, scope, opt){
10170         var els = this.elements,
10171             len = els.length,
10172             i, e;
10173
10174         for(i = 0; i<len; i++) {
10175             e = els[i];
10176             if(e) {
10177                 Ext.EventManager.on(e, eventName, handler, scope || e, opt);
10178             }
10179         }
10180         return this;
10181     },
10182     
10183     each : function(fn, scope){
10184         var me = this,
10185             els = me.elements,
10186             len = els.length,
10187             i, e;
10188
10189         for(i = 0; i<len; i++) {
10190             e = els[i];
10191             if(e){
10192                 e = this.getElement(e);
10193                 if(fn.call(scope || e, e, me, i) === false){
10194                     break;
10195                 }
10196             }
10197         }
10198         return me;
10199     },
10200
10201     
10202     fill : function(els){
10203         var me = this;
10204         me.elements = [];
10205         me.add(els);
10206         return me;
10207     },
10208
10209     
10210     filter : function(selector){
10211         var els = [],
10212             me = this,
10213             fn = Ext.isFunction(selector) ? selector
10214                 : function(el){
10215                     return el.is(selector);
10216                 };
10217
10218         me.each(function(el, self, i) {
10219             if (fn(el, i) !== false) {
10220                 els[els.length] = me.transformElement(el);
10221             }
10222         });
10223         
10224         me.elements = els;
10225         return me;
10226     },
10227
10228     
10229     indexOf : function(el){
10230         return Ext.Array.indexOf(this.elements, this.transformElement(el));
10231     },
10232
10233     
10234     replaceElement : function(el, replacement, domReplace){
10235         var index = !isNaN(el) ? el : this.indexOf(el),
10236             d;
10237         if(index > -1){
10238             replacement = Ext.getDom(replacement);
10239             if(domReplace){
10240                 d = this.elements[index];
10241                 d.parentNode.insertBefore(replacement, d);
10242                 Ext.removeNode(d);
10243             }
10244             this.elements.splice(index, 1, replacement);
10245         }
10246         return this;
10247     },
10248
10249     
10250     clear : function(){
10251         this.elements = [];
10252     }
10253 };
10254
10255 Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
10256
10257
10258 Ext.CompositeElementLite.importElementMethods = function() {
10259     var fnName,
10260         ElProto = Ext.core.Element.prototype,
10261         CelProto = Ext.CompositeElementLite.prototype;
10262
10263     for (fnName in ElProto) {
10264         if (typeof ElProto[fnName] == 'function'){
10265             (function(fnName) {
10266                 CelProto[fnName] = CelProto[fnName] || function() {
10267                     return this.invoke(fnName, arguments);
10268                 };
10269             }).call(CelProto, fnName);
10270
10271         }
10272     }
10273 };
10274
10275 Ext.CompositeElementLite.importElementMethods();
10276
10277 if(Ext.DomQuery){
10278     Ext.core.Element.selectorFunction = Ext.DomQuery.select;
10279 }
10280
10281
10282 Ext.core.Element.select = function(selector, root){
10283     var els;
10284     if(typeof selector == "string"){
10285         els = Ext.core.Element.selectorFunction(selector, root);
10286     }else if(selector.length !== undefined){
10287         els = selector;
10288     }else{
10289         Ext.Error.raise({
10290             sourceClass: "Ext.core.Element",
10291             sourceMethod: "select",
10292             selector: selector,
10293             root: root,
10294             msg: "Invalid selector specified: " + selector
10295         });
10296     }
10297     return new Ext.CompositeElementLite(els);
10298 };
10299
10300 Ext.select = Ext.core.Element.select;
10301
10302
10303 Ext.util.DelayedTask = function(fn, scope, args) {
10304     var me = this,
10305         id,
10306         call = function() {
10307             clearInterval(id);
10308             id = null;
10309             fn.apply(scope, args || []);
10310         };
10311
10312     
10313     this.delay = function(delay, newFn, newScope, newArgs) {
10314         me.cancel();
10315         fn = newFn || fn;
10316         scope = newScope || scope;
10317         args = newArgs || args;
10318         id = setInterval(call, delay);
10319     };
10320
10321     
10322     this.cancel = function(){
10323         if (id) {
10324             clearInterval(id);
10325             id = null;
10326         }
10327     };
10328 };
10329 Ext.require('Ext.util.DelayedTask', function() {
10330
10331     Ext.util.Event = Ext.extend(Object, (function() {
10332         function createBuffered(handler, listener, o, scope) {
10333             listener.task = new Ext.util.DelayedTask();
10334             return function() {
10335                 listener.task.delay(o.buffer, handler, scope, Ext.Array.toArray(arguments));
10336             };
10337         }
10338
10339         function createDelayed(handler, listener, o, scope) {
10340             return function() {
10341                 var task = new Ext.util.DelayedTask();
10342                 if (!listener.tasks) {
10343                     listener.tasks = [];
10344                 }
10345                 listener.tasks.push(task);
10346                 task.delay(o.delay || 10, handler, scope, Ext.Array.toArray(arguments));
10347             };
10348         }
10349
10350         function createSingle(handler, listener, o, scope) {
10351             return function() {
10352                 listener.ev.removeListener(listener.fn, scope);
10353                 return handler.apply(scope, arguments);
10354             };
10355         }
10356
10357         return {
10358             isEvent: true,
10359
10360             constructor: function(observable, name) {
10361                 this.name = name;
10362                 this.observable = observable;
10363                 this.listeners = [];
10364             },
10365
10366             addListener: function(fn, scope, options) {
10367                 var me = this,
10368                     listener;
10369                     scope = scope || me.observable;
10370
10371                 if (!fn) {
10372                     Ext.Error.raise({
10373                         sourceClass: Ext.getClassName(this.observable),
10374                         sourceMethod: "addListener",
10375                         msg: "The specified callback function is undefined"
10376                     });
10377                 }
10378
10379                 if (!me.isListening(fn, scope)) {
10380                     listener = me.createListener(fn, scope, options);
10381                     if (me.firing) {
10382                         
10383                         me.listeners = me.listeners.slice(0);
10384                     }
10385                     me.listeners.push(listener);
10386                 }
10387             },
10388
10389             createListener: function(fn, scope, o) {
10390                 o = o || {};
10391                 scope = scope || this.observable;
10392
10393                 var listener = {
10394                         fn: fn,
10395                         scope: scope,
10396                         o: o,
10397                         ev: this
10398                     },
10399                     handler = fn;
10400
10401                 
10402                 
10403                 if (o.single) {
10404                     handler = createSingle(handler, listener, o, scope);
10405                 }
10406                 if (o.delay) {
10407                     handler = createDelayed(handler, listener, o, scope);
10408                 }
10409                 if (o.buffer) {
10410                     handler = createBuffered(handler, listener, o, scope);
10411                 }
10412
10413                 listener.fireFn = handler;
10414                 return listener;
10415             },
10416
10417             findListener: function(fn, scope) {
10418                 var listeners = this.listeners,
10419                 i = listeners.length,
10420                 listener,
10421                 s;
10422
10423                 while (i--) {
10424                     listener = listeners[i];
10425                     if (listener) {
10426                         s = listener.scope;
10427                         if (listener.fn == fn && (s == scope || s == this.observable)) {
10428                             return i;
10429                         }
10430                     }
10431                 }
10432
10433                 return - 1;
10434             },
10435
10436             isListening: function(fn, scope) {
10437                 return this.findListener(fn, scope) !== -1;
10438             },
10439
10440             removeListener: function(fn, scope) {
10441                 var me = this,
10442                     index,
10443                     listener,
10444                     k;
10445                 index = me.findListener(fn, scope);
10446                 if (index != -1) {
10447                     listener = me.listeners[index];
10448
10449                     if (me.firing) {
10450                         me.listeners = me.listeners.slice(0);
10451                     }
10452
10453                     
10454                     if (listener.task) {
10455                         listener.task.cancel();
10456                         delete listener.task;
10457                     }
10458
10459                     
10460                     k = listener.tasks && listener.tasks.length;
10461                     if (k) {
10462                         while (k--) {
10463                             listener.tasks[k].cancel();
10464                         }
10465                         delete listener.tasks;
10466                     }
10467
10468                     
10469                     me.listeners.splice(index, 1);
10470                     return true;
10471                 }
10472
10473                 return false;
10474             },
10475
10476             
10477             clearListeners: function() {
10478                 var listeners = this.listeners,
10479                     i = listeners.length;
10480
10481                 while (i--) {
10482                     this.removeListener(listeners[i].fn, listeners[i].scope);
10483                 }
10484             },
10485
10486             fire: function() {
10487                 var me = this,
10488                     listeners = me.listeners,
10489                     count = listeners.length,
10490                     i,
10491                     args,
10492                     listener;
10493
10494                 if (count > 0) {
10495                     me.firing = true;
10496                     for (i = 0; i < count; i++) {
10497                         listener = listeners[i];
10498                         args = arguments.length ? Array.prototype.slice.call(arguments, 0) : [];
10499                         if (listener.o) {
10500                             args.push(listener.o);
10501                         }
10502                         if (listener && listener.fireFn.apply(listener.scope || me.observable, args) === false) {
10503                             return (me.firing = false);
10504                         }
10505                     }
10506                 }
10507                 me.firing = false;
10508                 return true;
10509             }
10510         };
10511     })());
10512 });
10513
10514
10515 Ext.EventManager = {
10516
10517     
10518
10519     
10520     hasBoundOnReady: false,
10521
10522     
10523     hasFiredReady: false,
10524
10525     
10526     readyTimeout: null,
10527
10528     
10529     hasOnReadyStateChange: false,
10530
10531     
10532     readyEvent: new Ext.util.Event(),
10533
10534     
10535     checkReadyState: function(){
10536         var me = Ext.EventManager;
10537
10538         if(window.attachEvent){
10539             
10540             if (window != top) {
10541                 return false;
10542             }
10543             try{
10544                 document.documentElement.doScroll('left');
10545             }catch(e){
10546                 return false;
10547             }
10548             me.fireDocReady();
10549             return true;
10550         }
10551         if (document.readyState == 'complete') {
10552             me.fireDocReady();
10553             return true;
10554         }
10555         me.readyTimeout = setTimeout(arguments.callee, 2);
10556         return false;
10557     },
10558
10559     
10560     bindReadyEvent: function(){
10561         var me = Ext.EventManager;
10562         if (me.hasBoundOnReady) {
10563             return;
10564         }
10565
10566         if (document.addEventListener) {
10567             document.addEventListener('DOMContentLoaded', me.fireDocReady, false);
10568             
10569             window.addEventListener('load', me.fireDocReady, false);
10570         } else {
10571             
10572             if (!me.checkReadyState()) {
10573                 document.attachEvent('onreadystatechange', me.checkReadyState);
10574                 me.hasOnReadyStateChange = true;
10575             }
10576             
10577             window.attachEvent('onload', me.fireDocReady, false);
10578         }
10579         me.hasBoundOnReady = true;
10580     },
10581
10582     
10583     fireDocReady: function(){
10584         var me = Ext.EventManager;
10585
10586         
10587         if (!me.hasFiredReady) {
10588             me.hasFiredReady = true;
10589
10590             if (document.addEventListener) {
10591                 document.removeEventListener('DOMContentLoaded', me.fireDocReady, false);
10592                 window.removeEventListener('load', me.fireDocReady, false);
10593             } else {
10594                 if (me.readyTimeout !== null) {
10595                     clearTimeout(me.readyTimeout);
10596                 }
10597                 if (me.hasOnReadyStateChange) {
10598                     document.detachEvent('onreadystatechange', me.checkReadyState);
10599                 }
10600                 window.detachEvent('onload', me.fireDocReady);
10601             }
10602             Ext.supports.init();
10603         }
10604         if (!Ext.isReady) {
10605             Ext.isReady = true;
10606             me.onWindowUnload();
10607             me.readyEvent.fire();
10608         }
10609     },
10610
10611     
10612     onDocumentReady: function(fn, scope, options){
10613         options = options || {};
10614         var me = Ext.EventManager,
10615             readyEvent = me.readyEvent;
10616
10617         
10618         options.single = true;
10619
10620         
10621         if (Ext.isReady) {
10622             readyEvent.addListener(fn, scope, options);
10623             readyEvent.fire();
10624         } else {
10625             options.delay = options.delay || 1;
10626             readyEvent.addListener(fn, scope, options);
10627             me.bindReadyEvent();
10628         }
10629     },
10630
10631
10632     
10633
10634     
10635     stoppedMouseDownEvent: new Ext.util.Event(),
10636
10637     
10638     propRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|freezeEvent)$/,
10639
10640     
10641     getId : function(element) {
10642         var skipGarbageCollection = false,
10643             id;
10644     
10645         element = Ext.getDom(element);
10646     
10647         if (element === document || element === window) {
10648             id = element === document ? Ext.documentId : Ext.windowId;
10649         }
10650         else {
10651             id = Ext.id(element);
10652         }
10653         
10654         if (element && (element.getElementById || element.navigator)) {
10655             skipGarbageCollection = true;
10656         }
10657     
10658         if (!Ext.cache[id]){
10659             Ext.core.Element.addToCache(new Ext.core.Element(element), id);
10660             if (skipGarbageCollection) {
10661                 Ext.cache[id].skipGarbageCollection = true;
10662             }
10663         }
10664         return id;
10665     },
10666
10667     
10668     prepareListenerConfig: function(element, config, isRemove){
10669         var me = this,
10670             propRe = me.propRe,
10671             key, value, args;
10672
10673         
10674         for (key in config) {
10675             if (config.hasOwnProperty(key)) {
10676                 
10677                 if (!propRe.test(key)) {
10678                     value = config[key];
10679                     
10680                     
10681                     if (Ext.isFunction(value)) {
10682                         
10683                         args = [element, key, value, config.scope, config];
10684                     } else {
10685                         
10686                         args = [element, key, value.fn, value.scope, value];
10687                     }
10688
10689                     if (isRemove === true) {
10690                         me.removeListener.apply(this, args);
10691                     } else {
10692                         me.addListener.apply(me, args);
10693                     }
10694                 }
10695             }
10696         }
10697     },
10698
10699     
10700     normalizeEvent: function(eventName, fn){
10701         if (/mouseenter|mouseleave/.test(eventName) && !Ext.supports.MouseEnterLeave) {
10702             if (fn) {
10703                 fn = Ext.Function.createInterceptor(fn, this.contains, this);
10704             }
10705             eventName = eventName == 'mouseenter' ? 'mouseover' : 'mouseout';
10706         } else if (eventName == 'mousewheel' && !Ext.supports.MouseWheel && !Ext.isOpera){
10707             eventName = 'DOMMouseScroll';
10708         }
10709         return {
10710             eventName: eventName,
10711             fn: fn
10712         };
10713     },
10714
10715     
10716     contains: function(event){
10717         var parent = event.browserEvent.currentTarget,
10718             child = this.getRelatedTarget(event);
10719
10720         if (parent && parent.firstChild) {
10721             while (child) {
10722                 if (child === parent) {
10723                     return false;
10724                 }
10725                 child = child.parentNode;
10726                 if (child && (child.nodeType != 1)) {
10727                     child = null;
10728                 }
10729             }
10730         }
10731         return true;
10732     },
10733
10734     
10735     addListener: function(element, eventName, fn, scope, options){
10736         
10737         if (Ext.isObject(eventName)) {
10738             this.prepareListenerConfig(element, eventName);
10739             return;
10740         }
10741
10742         var dom = Ext.getDom(element),
10743             bind,
10744             wrap;
10745
10746         if (!dom){
10747             Ext.Error.raise({
10748                 sourceClass: 'Ext.EventManager',
10749                 sourceMethod: 'addListener',
10750                 targetElement: element,
10751                 eventName: eventName,
10752                 msg: 'Error adding "' + eventName + '\" listener for nonexistent element "' + element + '"'
10753             });
10754         }
10755         if (!fn) {
10756             Ext.Error.raise({
10757                 sourceClass: 'Ext.EventManager',
10758                 sourceMethod: 'addListener',
10759                 targetElement: element,
10760                 eventName: eventName,
10761                 msg: 'Error adding "' + eventName + '\" listener. The handler function is undefined.'
10762             });
10763         }
10764
10765         
10766         options = options || {};
10767
10768         bind = this.normalizeEvent(eventName, fn);
10769         wrap = this.createListenerWrap(dom, eventName, bind.fn, scope, options);
10770
10771
10772         if (dom.attachEvent) {
10773             dom.attachEvent('on' + bind.eventName, wrap);
10774         } else {
10775             dom.addEventListener(bind.eventName, wrap, options.capture || false);
10776         }
10777
10778         if (dom == document && eventName == 'mousedown') {
10779             this.stoppedMouseDownEvent.addListener(wrap);
10780         }
10781
10782         
10783         this.getEventListenerCache(dom, eventName).push({
10784             fn: fn,
10785             wrap: wrap,
10786             scope: scope
10787         });
10788     },
10789
10790     
10791     removeListener : function(element, eventName, fn, scope) {
10792         
10793         if (Ext.isObject(eventName)) {
10794             this.prepareListenerConfig(element, eventName, true);
10795             return;
10796         }
10797
10798         var dom = Ext.getDom(element),
10799             cache = this.getEventListenerCache(dom, eventName),
10800             bindName = this.normalizeEvent(eventName).eventName,
10801             i = cache.length, j,
10802             listener, wrap, tasks;
10803
10804
10805         while (i--) {
10806             listener = cache[i];
10807
10808             if (listener && (!fn || listener.fn == fn) && (!scope || listener.scope === scope)) {
10809                 wrap = listener.wrap;
10810
10811                 
10812                 if (wrap.task) {
10813                     clearTimeout(wrap.task);
10814                     delete wrap.task;
10815                 }
10816
10817                 
10818                 j = wrap.tasks && wrap.tasks.length;
10819                 if (j) {
10820                     while (j--) {
10821                         clearTimeout(wrap.tasks[j]);
10822                     }
10823                     delete wrap.tasks;
10824                 }
10825
10826                 if (dom.detachEvent) {
10827                     dom.detachEvent('on' + bindName, wrap);
10828                 } else {
10829                     dom.removeEventListener(bindName, wrap, false);
10830                 }
10831
10832                 if (wrap && dom == document && eventName == 'mousedown') {
10833                     this.stoppedMouseDownEvent.removeListener(wrap);
10834                 }
10835
10836                 
10837                 cache.splice(i, 1);
10838             }
10839         }
10840     },
10841
10842     
10843     removeAll : function(element){
10844         var dom = Ext.getDom(element),
10845             cache, ev;
10846         if (!dom) {
10847             return;
10848         }
10849         cache = this.getElementEventCache(dom);
10850
10851         for (ev in cache) {
10852             if (cache.hasOwnProperty(ev)) {
10853                 this.removeListener(dom, ev);
10854             }
10855         }
10856         Ext.cache[dom.id].events = {};
10857     },
10858
10859     
10860     purgeElement : function(element, eventName) {
10861         var dom = Ext.getDom(element),
10862             i = 0, len;
10863
10864         if(eventName) {
10865             this.removeListener(dom, eventName);
10866         }
10867         else {
10868             this.removeAll(dom);
10869         }
10870
10871         if(dom && dom.childNodes) {
10872             for(len = element.childNodes.length; i < len; i++) {
10873                 this.purgeElement(element.childNodes[i], eventName);
10874             }
10875         }
10876     },
10877
10878     
10879     createListenerWrap : function(dom, ename, fn, scope, options) {
10880         options = !Ext.isObject(options) ? {} : options;
10881
10882         var f, gen;
10883
10884         return function wrap(e, args) {
10885             
10886             if (!gen) {
10887                 f = ['if(!Ext) {return;}'];
10888
10889                 if(options.buffer || options.delay || options.freezeEvent) {
10890                     f.push('e = new Ext.EventObjectImpl(e, ' + (options.freezeEvent ? 'true' : 'false' ) + ');');
10891                 } else {
10892                     f.push('e = Ext.EventObject.setEvent(e);');
10893                 }
10894
10895                 if (options.delegate) {
10896                     f.push('var t = e.getTarget("' + options.delegate + '", this);');
10897                     f.push('if(!t) {return;}');
10898                 } else {
10899                     f.push('var t = e.target;');
10900                 }
10901
10902                 if (options.target) {
10903                     f.push('if(e.target !== options.target) {return;}');
10904                 }
10905
10906                 if(options.stopEvent) {
10907                     f.push('e.stopEvent();');
10908                 } else {
10909                     if(options.preventDefault) {
10910                         f.push('e.preventDefault();');
10911                     }
10912                     if(options.stopPropagation) {
10913                         f.push('e.stopPropagation();');
10914                     }
10915                 }
10916
10917                 if(options.normalized === false) {
10918                     f.push('e = e.browserEvent;');
10919                 }
10920
10921                 if(options.buffer) {
10922                     f.push('(wrap.task && clearTimeout(wrap.task));');
10923                     f.push('wrap.task = setTimeout(function(){');
10924                 }
10925
10926                 if(options.delay) {
10927                     f.push('wrap.tasks = wrap.tasks || [];');
10928                     f.push('wrap.tasks.push(setTimeout(function(){');
10929                 }
10930
10931                 
10932                 f.push('fn.call(scope || dom, e, t, options);');
10933
10934                 if(options.single) {
10935                     f.push('Ext.EventManager.removeListener(dom, ename, fn, scope);');
10936                 }
10937
10938                 if(options.delay) {
10939                     f.push('}, ' + options.delay + '));');
10940                 }
10941
10942                 if(options.buffer) {
10943                     f.push('}, ' + options.buffer + ');');
10944                 }
10945
10946                 gen = Ext.functionFactory('e', 'options', 'fn', 'scope', 'ename', 'dom', 'wrap', 'args', f.join('\n'));
10947             }
10948
10949             gen.call(dom, e, options, fn, scope, ename, dom, wrap, args);
10950         };
10951     },
10952
10953     
10954     getEventListenerCache : function(element, eventName) {
10955         var eventCache = this.getElementEventCache(element);
10956         return eventCache[eventName] || (eventCache[eventName] = []);
10957     },
10958
10959     
10960     getElementEventCache : function(element) {
10961         var elementCache = Ext.cache[this.getId(element)];
10962         return elementCache.events || (elementCache.events = {});
10963     },
10964
10965     
10966     mouseLeaveRe: /(mouseout|mouseleave)/,
10967     mouseEnterRe: /(mouseover|mouseenter)/,
10968
10969     
10970     stopEvent: function(event) {
10971         this.stopPropagation(event);
10972         this.preventDefault(event);
10973     },
10974
10975     
10976     stopPropagation: function(event) {
10977         event = event.browserEvent || event;
10978         if (event.stopPropagation) {
10979             event.stopPropagation();
10980         } else {
10981             event.cancelBubble = true;
10982         }
10983     },
10984
10985     
10986     preventDefault: function(event) {
10987         event = event.browserEvent || event;
10988         if (event.preventDefault) {
10989             event.preventDefault();
10990         } else {
10991             event.returnValue = false;
10992             
10993             try {
10994               
10995               if (event.ctrlKey || event.keyCode > 111 && event.keyCode < 124) {
10996                   event.keyCode = -1;
10997               }
10998             } catch (e) {
10999                 
11000             }
11001         }
11002     },
11003
11004     
11005     getRelatedTarget: function(event) {
11006         event = event.browserEvent || event;
11007         var target = event.relatedTarget;
11008         if (!target) {
11009             if (this.mouseLeaveRe.test(event.type)) {
11010                 target = event.toElement;
11011             } else if (this.mouseEnterRe.test(event.type)) {
11012                 target = event.fromElement;
11013             }
11014         }
11015         return this.resolveTextNode(target);
11016     },
11017
11018     
11019     getPageX: function(event) {
11020         return this.getXY(event)[0];
11021     },
11022
11023     
11024     getPageY: function(event) {
11025         return this.getXY(event)[1];
11026     },
11027
11028     
11029     getPageXY: function(event) {
11030         event = event.browserEvent || event;
11031         var x = event.pageX,
11032             y = event.pageY,
11033             doc = document.documentElement,
11034             body = document.body;
11035
11036         
11037         if (!x && x !== 0) {
11038             x = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
11039             y = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
11040         }
11041         return [x, y];
11042     },
11043
11044     
11045     getTarget: function(event) {
11046         event = event.browserEvent || event;
11047         return this.resolveTextNode(event.target || event.srcElement);
11048     },
11049
11050     
11051     
11052     resolveTextNode: Ext.isGecko ?
11053         function(node) {
11054             if (!node) {
11055                 return;
11056             }
11057             
11058             var s = HTMLElement.prototype.toString.call(node);
11059             if (s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]') {
11060                 return;
11061             }
11062                 return node.nodeType == 3 ? node.parentNode: node;
11063             }: function(node) {
11064                 return node && node.nodeType == 3 ? node.parentNode: node;
11065             },
11066
11067     
11068
11069     
11070     curWidth: 0,
11071     curHeight: 0,
11072
11073     
11074     onWindowResize: function(fn, scope, options){
11075         var resize = this.resizeEvent;
11076         if(!resize){
11077             this.resizeEvent = resize = new Ext.util.Event();
11078             this.on(window, 'resize', this.fireResize, this, {buffer: 100});
11079         }
11080         resize.addListener(fn, scope, options);
11081     },
11082
11083     
11084     fireResize: function(){
11085         var me = this,
11086             w = Ext.core.Element.getViewWidth(),
11087             h = Ext.core.Element.getViewHeight();
11088
11089          
11090          if(me.curHeight != h || me.curWidth != w){
11091              me.curHeight = h;
11092              me.curWidth = w;
11093              me.resizeEvent.fire(w, h);
11094          }
11095     },
11096
11097     
11098     removeResizeListener: function(fn, scope){
11099         if (this.resizeEvent) {
11100             this.resizeEvent.removeListener(fn, scope);
11101         }
11102     },
11103
11104     onWindowUnload: function() {
11105         var unload = this.unloadEvent;
11106         if (!unload) {
11107             this.unloadEvent = unload = new Ext.util.Event();
11108             this.addListener(window, 'unload', this.fireUnload, this);
11109         }
11110     },
11111
11112     
11113     fireUnload: function() {
11114         
11115         try {
11116             this.removeUnloadListener();
11117             
11118             if (Ext.isGecko3) {
11119                 var gridviews = Ext.ComponentQuery.query('gridview'),
11120                     i = 0,
11121                     ln = gridviews.length;
11122                 for (; i < ln; i++) {
11123                     gridviews[i].scrollToTop();
11124                 }
11125             }
11126             
11127             var el,
11128                 cache = Ext.cache;
11129             for (el in cache) {
11130                 if (cache.hasOwnProperty(el)) {
11131                     Ext.EventManager.removeAll(el);
11132                 }
11133             }
11134         } catch(e) {
11135         }
11136     },
11137
11138     
11139     removeUnloadListener: function(){
11140         if (this.unloadEvent) {
11141             this.removeListener(window, 'unload', this.fireUnload);
11142         }
11143     },
11144
11145     
11146     useKeyDown: Ext.isWebKit ?
11147                    parseInt(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1], 10) >= 525 :
11148                    !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera),
11149
11150     
11151     getKeyEvent: function(){
11152         return this.useKeyDown ? 'keydown' : 'keypress';
11153     }
11154 };
11155
11156
11157 Ext.onReady = function(fn, scope, options) {
11158     Ext.Loader.onReady(fn, scope, true, options);
11159 };
11160
11161
11162 Ext.onDocumentReady = Ext.EventManager.onDocumentReady;
11163
11164
11165 Ext.EventManager.on = Ext.EventManager.addListener;
11166
11167
11168 Ext.EventManager.un = Ext.EventManager.removeListener;
11169
11170 (function(){
11171     var initExtCss = function() {
11172         
11173         var bd = document.body || document.getElementsByTagName('body')[0],
11174             baseCSSPrefix = Ext.baseCSSPrefix,
11175             cls = [],
11176             htmlCls = [],
11177             html;
11178
11179         if (!bd) {
11180             return false;
11181         }
11182
11183         html = bd.parentNode;
11184
11185         
11186         if (Ext.isIE) {
11187             cls.push(baseCSSPrefix + 'ie');
11188         }
11189         if (Ext.isIE6) {
11190             cls.push(baseCSSPrefix + 'ie6');
11191         }
11192         if (Ext.isIE7) {
11193             cls.push(baseCSSPrefix + 'ie7');
11194         }
11195         if (Ext.isIE8) {
11196             cls.push(baseCSSPrefix + 'ie8');
11197         }
11198         if (Ext.isIE9) {
11199             cls.push(baseCSSPrefix + 'ie9');
11200         }
11201         if (Ext.isGecko) {
11202             cls.push(baseCSSPrefix + 'gecko');
11203         }
11204         if (Ext.isGecko3) {
11205             cls.push(baseCSSPrefix + 'gecko3');
11206         }
11207         if (Ext.isGecko4) {
11208             cls.push(baseCSSPrefix + 'gecko4');
11209         }
11210         if (Ext.isOpera) {
11211             cls.push(baseCSSPrefix + 'opera');
11212         }
11213         if (Ext.isWebKit) {
11214             cls.push(baseCSSPrefix + 'webkit');
11215         }
11216         if (Ext.isSafari) {
11217             cls.push(baseCSSPrefix + 'safari');
11218         }
11219         if (Ext.isSafari2) {
11220             cls.push(baseCSSPrefix + 'safari2');
11221         }
11222         if (Ext.isSafari3) {
11223             cls.push(baseCSSPrefix + 'safari3');
11224         }
11225         if (Ext.isSafari4) {
11226             cls.push(baseCSSPrefix + 'safari4');
11227         }
11228         if (Ext.isChrome) {
11229             cls.push(baseCSSPrefix + 'chrome');
11230         }
11231         if (Ext.isMac) {
11232             cls.push(baseCSSPrefix + 'mac');
11233         }
11234         if (Ext.isLinux) {
11235             cls.push(baseCSSPrefix + 'linux');
11236         }
11237         if (!Ext.supports.CSS3BorderRadius) {
11238             cls.push(baseCSSPrefix + 'nbr');
11239         }
11240         if (!Ext.supports.CSS3LinearGradient) {
11241             cls.push(baseCSSPrefix + 'nlg');
11242         }
11243         if (!Ext.scopeResetCSS) {
11244             cls.push(baseCSSPrefix + 'reset');
11245         }
11246
11247         
11248         if (html) {
11249             if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
11250                 Ext.isBorderBox = false;
11251             }
11252             else {
11253                 Ext.isBorderBox = true;
11254             }
11255
11256             htmlCls.push(baseCSSPrefix + (Ext.isBorderBox ? 'border-box' : 'strict'));
11257             if (!Ext.isStrict) {
11258                 htmlCls.push(baseCSSPrefix + 'quirks');
11259                 if (Ext.isIE && !Ext.isStrict) {
11260                     Ext.isIEQuirks = true;
11261                 }
11262             }
11263             Ext.fly(html, '_internal').addCls(htmlCls);
11264         }
11265
11266         Ext.fly(bd, '_internal').addCls(cls);
11267         return true;
11268     };
11269
11270     Ext.onReady(initExtCss);
11271 })();
11272
11273
11274 Ext.define('Ext.EventObjectImpl', {
11275     uses: ['Ext.util.Point'],
11276
11277     
11278     BACKSPACE: 8,
11279     
11280     TAB: 9,
11281     
11282     NUM_CENTER: 12,
11283     
11284     ENTER: 13,
11285     
11286     RETURN: 13,
11287     
11288     SHIFT: 16,
11289     
11290     CTRL: 17,
11291     
11292     ALT: 18,
11293     
11294     PAUSE: 19,
11295     
11296     CAPS_LOCK: 20,
11297     
11298     ESC: 27,
11299     
11300     SPACE: 32,
11301     
11302     PAGE_UP: 33,
11303     
11304     PAGE_DOWN: 34,
11305     
11306     END: 35,
11307     
11308     HOME: 36,
11309     
11310     LEFT: 37,
11311     
11312     UP: 38,
11313     
11314     RIGHT: 39,
11315     
11316     DOWN: 40,
11317     
11318     PRINT_SCREEN: 44,
11319     
11320     INSERT: 45,
11321     
11322     DELETE: 46,
11323     
11324     ZERO: 48,
11325     
11326     ONE: 49,
11327     
11328     TWO: 50,
11329     
11330     THREE: 51,
11331     
11332     FOUR: 52,
11333     
11334     FIVE: 53,
11335     
11336     SIX: 54,
11337     
11338     SEVEN: 55,
11339     
11340     EIGHT: 56,
11341     
11342     NINE: 57,
11343     
11344     A: 65,
11345     
11346     B: 66,
11347     
11348     C: 67,
11349     
11350     D: 68,
11351     
11352     E: 69,
11353     
11354     F: 70,
11355     
11356     G: 71,
11357     
11358     H: 72,
11359     
11360     I: 73,
11361     
11362     J: 74,
11363     
11364     K: 75,
11365     
11366     L: 76,
11367     
11368     M: 77,
11369     
11370     N: 78,
11371     
11372     O: 79,
11373     
11374     P: 80,
11375     
11376     Q: 81,
11377     
11378     R: 82,
11379     
11380     S: 83,
11381     
11382     T: 84,
11383     
11384     U: 85,
11385     
11386     V: 86,
11387     
11388     W: 87,
11389     
11390     X: 88,
11391     
11392     Y: 89,
11393     
11394     Z: 90,
11395     
11396     CONTEXT_MENU: 93,
11397     
11398     NUM_ZERO: 96,
11399     
11400     NUM_ONE: 97,
11401     
11402     NUM_TWO: 98,
11403     
11404     NUM_THREE: 99,
11405     
11406     NUM_FOUR: 100,
11407     
11408     NUM_FIVE: 101,
11409     
11410     NUM_SIX: 102,
11411     
11412     NUM_SEVEN: 103,
11413     
11414     NUM_EIGHT: 104,
11415     
11416     NUM_NINE: 105,
11417     
11418     NUM_MULTIPLY: 106,
11419     
11420     NUM_PLUS: 107,
11421     
11422     NUM_MINUS: 109,
11423     
11424     NUM_PERIOD: 110,
11425     
11426     NUM_DIVISION: 111,
11427     
11428     F1: 112,
11429     
11430     F2: 113,
11431     
11432     F3: 114,
11433     
11434     F4: 115,
11435     
11436     F5: 116,
11437     
11438     F6: 117,
11439     
11440     F7: 118,
11441     
11442     F8: 119,
11443     
11444     F9: 120,
11445     
11446     F10: 121,
11447     
11448     F11: 122,
11449     
11450     F12: 123,
11451
11452     
11453     clickRe: /(dbl)?click/,
11454     
11455     safariKeys: {
11456         3: 13, 
11457         63234: 37, 
11458         63235: 39, 
11459         63232: 38, 
11460         63233: 40, 
11461         63276: 33, 
11462         63277: 34, 
11463         63272: 46, 
11464         63273: 36, 
11465         63275: 35 
11466     },
11467     
11468     btnMap: Ext.isIE ? {
11469         1: 0,
11470         4: 1,
11471         2: 2
11472     } : {
11473         0: 0,
11474         1: 1,
11475         2: 2
11476     },
11477
11478     constructor: function(event, freezeEvent){
11479         if (event) {
11480             this.setEvent(event.browserEvent || event, freezeEvent);
11481         }
11482     },
11483
11484     setEvent: function(event, freezeEvent){
11485         var me = this, button, options;
11486
11487         if (event == me || (event && event.browserEvent)) { 
11488             return event;
11489         }
11490         me.browserEvent = event;
11491         if (event) {
11492             
11493             button = event.button ? me.btnMap[event.button] : (event.which ? event.which - 1 : -1);
11494             if (me.clickRe.test(event.type) && button == -1) {
11495                 button = 0;
11496             }
11497             options = {
11498                 type: event.type,
11499                 button: button,
11500                 shiftKey: event.shiftKey,
11501                 
11502                 ctrlKey: event.ctrlKey || event.metaKey || false,
11503                 altKey: event.altKey,
11504                 
11505                 keyCode: event.keyCode,
11506                 charCode: event.charCode,
11507                 
11508                 target: Ext.EventManager.getTarget(event),
11509                 relatedTarget: Ext.EventManager.getRelatedTarget(event),
11510                 currentTarget: event.currentTarget,
11511                 xy: (freezeEvent ? me.getXY() : null)
11512             };
11513         } else {
11514             options = {
11515                 button: -1,
11516                 shiftKey: false,
11517                 ctrlKey: false,
11518                 altKey: false,
11519                 keyCode: 0,
11520                 charCode: 0,
11521                 target: null,
11522                 xy: [0, 0]
11523             };
11524         }
11525         Ext.apply(me, options);
11526         return me;
11527     },
11528
11529     
11530     stopEvent: function(){
11531         this.stopPropagation();
11532         this.preventDefault();
11533     },
11534
11535     
11536     preventDefault: function(){
11537         if (this.browserEvent) {
11538             Ext.EventManager.preventDefault(this.browserEvent);
11539         }
11540     },
11541
11542     
11543     stopPropagation: function(){
11544         var browserEvent = this.browserEvent;
11545
11546         if (browserEvent) {
11547             if (browserEvent.type == 'mousedown') {
11548                 Ext.EventManager.stoppedMouseDownEvent.fire(this);
11549             }
11550             Ext.EventManager.stopPropagation(browserEvent);
11551         }
11552     },
11553
11554     
11555     getCharCode: function(){
11556         return this.charCode || this.keyCode;
11557     },
11558
11559     
11560     getKey: function(){
11561         return this.normalizeKey(this.keyCode || this.charCode);
11562     },
11563
11564     
11565     normalizeKey: function(key){
11566         
11567         return Ext.isWebKit ? (this.safariKeys[key] || key) : key;
11568     },
11569
11570     
11571     getPageX: function(){
11572         return this.getX();
11573     },
11574
11575     
11576     getPageY: function(){
11577         return this.getY();
11578     },
11579     
11580     
11581     getX: function() {
11582         return this.getXY()[0];
11583     },    
11584     
11585     
11586     getY: function() {
11587         return this.getXY()[1];
11588     },
11589         
11590     
11591     getXY: function() {
11592         if (!this.xy) {
11593             
11594             this.xy = Ext.EventManager.getPageXY(this.browserEvent);
11595         }
11596         return this.xy;
11597     },
11598
11599     
11600     getTarget : function(selector, maxDepth, returnEl){
11601         if (selector) {
11602             return Ext.fly(this.target).findParent(selector, maxDepth, returnEl);
11603         }
11604         return returnEl ? Ext.get(this.target) : this.target;
11605     },
11606
11607     
11608     getRelatedTarget : function(selector, maxDepth, returnEl){
11609         if (selector) {
11610             return Ext.fly(this.relatedTarget).findParent(selector, maxDepth, returnEl);
11611         }
11612         return returnEl ? Ext.get(this.relatedTarget) : this.relatedTarget;
11613     },
11614
11615     
11616     getWheelDelta : function(){
11617         var event = this.browserEvent,
11618             delta = 0;
11619
11620         if (event.wheelDelta) { 
11621             delta = event.wheelDelta / 120;
11622         } else if (event.detail){ 
11623             delta = -event.detail / 3;
11624         }
11625         return delta;
11626     },
11627
11628     
11629     within : function(el, related, allowEl){
11630         if(el){
11631             var t = related ? this.getRelatedTarget() : this.getTarget(),
11632                 result;
11633
11634             if (t) {
11635                 result = Ext.fly(el).contains(t);
11636                 if (!result && allowEl) {
11637                     result = t == Ext.getDom(el);
11638                 }
11639                 return result;
11640             }
11641         }
11642         return false;
11643     },
11644
11645     
11646     isNavKeyPress : function(){
11647         var me = this,
11648             k = this.normalizeKey(me.keyCode);
11649
11650        return (k >= 33 && k <= 40) ||  
11651        k == me.RETURN ||
11652        k == me.TAB ||
11653        k == me.ESC;
11654     },
11655
11656     
11657     isSpecialKey : function(){
11658         var k = this.normalizeKey(this.keyCode);
11659         return (this.type == 'keypress' && this.ctrlKey) ||
11660         this.isNavKeyPress() ||
11661         (k == this.BACKSPACE) || 
11662         (k >= 16 && k <= 20) || 
11663         (k >= 44 && k <= 46);   
11664     },
11665
11666     
11667     getPoint : function(){
11668         var xy = this.getXY();
11669         return Ext.create('Ext.util.Point', xy[0], xy[1]);
11670     },
11671
11672    
11673     hasModifier : function(){
11674         return this.ctrlKey || this.altKey || this.shiftKey || this.metaKey;
11675     },
11676
11677     
11678     injectEvent: function () {
11679         var API,
11680             dispatchers = {}; 
11681
11682         
11683
11684         
11685         
11686
11687         if (!Ext.isIE && document.createEvent) { 
11688             API = {
11689                 createHtmlEvent: function (doc, type, bubbles, cancelable) {
11690                     var event = doc.createEvent('HTMLEvents');
11691
11692                     event.initEvent(type, bubbles, cancelable);
11693                     return event;
11694                 },
11695
11696                 createMouseEvent: function (doc, type, bubbles, cancelable, detail,
11697                                             clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
11698                                             button, relatedTarget) {
11699                     var event = doc.createEvent('MouseEvents'),
11700                         view = doc.defaultView || window;
11701
11702                     if (event.initMouseEvent) {
11703                         event.initMouseEvent(type, bubbles, cancelable, view, detail,
11704                                     clientX, clientY, clientX, clientY, ctrlKey, altKey,
11705                                     shiftKey, metaKey, button, relatedTarget);
11706                     } else { 
11707                         event = doc.createEvent('UIEvents');
11708                         event.initEvent(type, bubbles, cancelable);
11709                         event.view = view;
11710                         event.detail = detail;
11711                         event.screenX = clientX;
11712                         event.screenY = clientY;
11713                         event.clientX = clientX;
11714                         event.clientY = clientY;
11715                         event.ctrlKey = ctrlKey;
11716                         event.altKey = altKey;
11717                         event.metaKey = metaKey;
11718                         event.shiftKey = shiftKey;
11719                         event.button = button;
11720                         event.relatedTarget = relatedTarget;
11721                     }
11722
11723                     return event;
11724                 },
11725
11726                 createUIEvent: function (doc, type, bubbles, cancelable, detail) {
11727                     var event = doc.createEvent('UIEvents'),
11728                         view = doc.defaultView || window;
11729
11730                     event.initUIEvent(type, bubbles, cancelable, view, detail);
11731                     return event;
11732                 },
11733
11734                 fireEvent: function (target, type, event) {
11735                     target.dispatchEvent(event);
11736                 },
11737
11738                 fixTarget: function (target) {
11739                     
11740                     if (target == window && !target.dispatchEvent) {
11741                         return document;
11742                     }
11743
11744                     return target;
11745                 }
11746             }
11747         } else if (document.createEventObject) { 
11748             var crazyIEButtons = { 0: 1, 1: 4, 2: 2 };
11749
11750             API = {
11751                 createHtmlEvent: function (doc, type, bubbles, cancelable) {
11752                     var event = doc.createEventObject();
11753                     event.bubbles = bubbles;
11754                     event.cancelable = cancelable;
11755                     return event;
11756                 },
11757
11758                 createMouseEvent: function (doc, type, bubbles, cancelable, detail,
11759                                             clientX, clientY, ctrlKey, altKey, shiftKey, metaKey,
11760                                             button, relatedTarget) {
11761                     var event = doc.createEventObject();
11762                     event.bubbles = bubbles;
11763                     event.cancelable = cancelable;
11764                     event.detail = detail;
11765                     event.screenX = clientX;
11766                     event.screenY = clientY;
11767                     event.clientX = clientX;
11768                     event.clientY = clientY;
11769                     event.ctrlKey = ctrlKey;
11770                     event.altKey = altKey;
11771                     event.shiftKey = shiftKey;
11772                     event.metaKey = metaKey;
11773                     event.button = crazyIEButtons[button] || button;
11774                     event.relatedTarget = relatedTarget; 
11775                     return event;
11776                 },
11777
11778                 createUIEvent: function (doc, type, bubbles, cancelable, detail) {
11779                     var event = doc.createEventObject();
11780                     event.bubbles = bubbles;
11781                     event.cancelable = cancelable;
11782                     return event;
11783                 },
11784
11785                 fireEvent: function (target, type, event) {
11786                     target.fireEvent('on' + type, event);
11787                 },
11788
11789                 fixTarget: function (target) {
11790                     if (target == document) {
11791                         
11792                         
11793                         return document.documentElement;
11794                     }
11795
11796                     return target;
11797                 }
11798             };
11799         }
11800
11801         
11802         
11803
11804         Ext.Object.each({
11805                 load:   [false, false],
11806                 unload: [false, false],
11807                 select: [true, false],
11808                 change: [true, false],
11809                 submit: [true, true],
11810                 reset:  [true, false],
11811                 resize: [true, false],
11812                 scroll: [true, false]
11813             },
11814             function (name, value) {
11815                 var bubbles = value[0], cancelable = value[1];
11816                 dispatchers[name] = function (targetEl, srcEvent) {
11817                     var e = API.createHtmlEvent(name, bubbles, cancelable);
11818                     API.fireEvent(targetEl, name, e);
11819                 };
11820             });
11821
11822         
11823         
11824
11825         function createMouseEventDispatcher (type, detail) {
11826             var cancelable = (type != 'mousemove');
11827             return function (targetEl, srcEvent) {
11828                 var xy = srcEvent.getXY(),
11829                     e = API.createMouseEvent(targetEl.ownerDocument, type, true, cancelable,
11830                                 detail, xy[0], xy[1], srcEvent.ctrlKey, srcEvent.altKey,
11831                                 srcEvent.shiftKey, srcEvent.metaKey, srcEvent.button,
11832                                 srcEvent.relatedTarget);
11833                 API.fireEvent(targetEl, type, e);
11834             };
11835         }
11836
11837         Ext.each(['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mousemove', 'mouseout'],
11838             function (eventName) {
11839                 dispatchers[eventName] = createMouseEventDispatcher(eventName, 1);
11840             });
11841
11842         
11843         
11844
11845         Ext.Object.each({
11846                 focusin:  [true, false],
11847                 focusout: [true, false],
11848                 activate: [true, true],
11849                 focus:    [false, false],
11850                 blur:     [false, false]
11851             },
11852             function (name, value) {
11853                 var bubbles = value[0], cancelable = value[1];
11854                 dispatchers[name] = function (targetEl, srcEvent) {
11855                     var e = API.createUIEvent(targetEl.ownerDocument, name, bubbles, cancelable, 1);
11856                     API.fireEvent(targetEl, name, e);
11857                 };
11858             });
11859
11860         
11861         if (!API) {
11862             
11863
11864             dispatchers = {}; 
11865
11866             API = {
11867                 fixTarget: function (t) {
11868                     return t;
11869                 }
11870             };
11871         }
11872
11873         function cannotInject (target, srcEvent) {
11874             
11875         }
11876
11877         return function (target) {
11878             var me = this,
11879                 dispatcher = dispatchers[me.type] || cannotInject,
11880                 t = target ? (target.dom || target) : me.getTarget();
11881
11882             t = API.fixTarget(t);
11883             dispatcher(t, me);
11884         };
11885     }() 
11886
11887 }, function() {
11888
11889 Ext.EventObject = new Ext.EventObjectImpl();
11890
11891 });
11892
11893
11894
11895 (function(){
11896     var doc = document,
11897         activeElement = null,
11898         isCSS1 = doc.compatMode == "CSS1Compat",
11899         ELEMENT = Ext.core.Element,
11900         fly = function(el){
11901             if (!_fly) {
11902                 _fly = new Ext.core.Element.Flyweight();
11903             }
11904             _fly.dom = el;
11905             return _fly;
11906         }, _fly;
11907
11908     
11909     
11910     
11911     if (!('activeElement' in doc) && doc.addEventListener) {
11912         doc.addEventListener('focus',
11913             function (ev) {
11914                 if (ev && ev.target) {
11915                     activeElement = (ev.target == doc) ? null : ev.target;
11916                 }
11917             }, true);
11918     }
11919
11920     
11921     function makeSelectionRestoreFn (activeEl, start, end) {
11922         return function () {
11923             activeEl.selectionStart = start;
11924             activeEl.selectionEnd = end;
11925         };
11926     }
11927
11928     Ext.apply(ELEMENT, {
11929         isAncestor : function(p, c) {
11930             var ret = false;
11931
11932             p = Ext.getDom(p);
11933             c = Ext.getDom(c);
11934             if (p && c) {
11935                 if (p.contains) {
11936                     return p.contains(c);
11937                 } else if (p.compareDocumentPosition) {
11938                     return !!(p.compareDocumentPosition(c) & 16);
11939                 } else {
11940                     while ((c = c.parentNode)) {
11941                         ret = c == p || ret;
11942                     }
11943                 }
11944             }
11945             return ret;
11946         },
11947
11948         
11949         getActiveElement: function () {
11950             return doc.activeElement || activeElement;
11951         },
11952
11953         
11954         getRightMarginFixCleaner: function (target) {
11955             var supports = Ext.supports,
11956                 hasInputBug = supports.DisplayChangeInputSelectionBug,
11957                 hasTextAreaBug = supports.DisplayChangeTextAreaSelectionBug;
11958
11959             if (hasInputBug || hasTextAreaBug) {
11960                 var activeEl = doc.activeElement || activeElement, 
11961                     tag = activeEl && activeEl.tagName,
11962                     start,
11963                     end;
11964
11965                 if ((hasTextAreaBug && tag == 'TEXTAREA') ||
11966                     (hasInputBug && tag == 'INPUT' && activeEl.type == 'text')) {
11967                     if (ELEMENT.isAncestor(target, activeEl)) {
11968                         start = activeEl.selectionStart;
11969                         end = activeEl.selectionEnd;
11970
11971                         if (Ext.isNumber(start) && Ext.isNumber(end)) { 
11972                             
11973                             
11974                             
11975                             
11976                             return makeSelectionRestoreFn(activeEl, start, end);
11977                         }
11978                     }
11979                 }
11980             }
11981
11982             return Ext.emptyFn; 
11983         },
11984
11985         getViewWidth : function(full) {
11986             return full ? ELEMENT.getDocumentWidth() : ELEMENT.getViewportWidth();
11987         },
11988
11989         getViewHeight : function(full) {
11990             return full ? ELEMENT.getDocumentHeight() : ELEMENT.getViewportHeight();
11991         },
11992
11993         getDocumentHeight: function() {
11994             return Math.max(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, ELEMENT.getViewportHeight());
11995         },
11996
11997         getDocumentWidth: function() {
11998             return Math.max(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, ELEMENT.getViewportWidth());
11999         },
12000
12001         getViewportHeight: function(){
12002             return Ext.isIE ?
12003                    (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :
12004                    self.innerHeight;
12005         },
12006
12007         getViewportWidth : function() {
12008             return (!Ext.isStrict && !Ext.isOpera) ? doc.body.clientWidth :
12009                    Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;
12010         },
12011
12012         getY : function(el) {
12013             return ELEMENT.getXY(el)[1];
12014         },
12015
12016         getX : function(el) {
12017             return ELEMENT.getXY(el)[0];
12018         },
12019
12020         getXY : function(el) {
12021             var p,
12022                 pe,
12023                 b,
12024                 bt,
12025                 bl,
12026                 dbd,
12027                 x = 0,
12028                 y = 0,
12029                 scroll,
12030                 hasAbsolute,
12031                 bd = (doc.body || doc.documentElement),
12032                 ret = [0,0];
12033
12034             el = Ext.getDom(el);
12035
12036             if(el != bd){
12037                 hasAbsolute = fly(el).isStyle("position", "absolute");
12038
12039                 if (el.getBoundingClientRect) {
12040                     b = el.getBoundingClientRect();
12041                     scroll = fly(document).getScroll();
12042                     ret = [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
12043                 } else {
12044                     p = el;
12045
12046                     while (p) {
12047                         pe = fly(p);
12048                         x += p.offsetLeft;
12049                         y += p.offsetTop;
12050
12051                         hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");
12052
12053                         if (Ext.isGecko) {
12054                             y += bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
12055                             x += bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
12056
12057                             if (p != el && !pe.isStyle('overflow','visible')) {
12058                                 x += bl;
12059                                 y += bt;
12060                             }
12061                         }
12062                         p = p.offsetParent;
12063                     }
12064
12065                     if (Ext.isSafari && hasAbsolute) {
12066                         x -= bd.offsetLeft;
12067                         y -= bd.offsetTop;
12068                     }
12069
12070                     if (Ext.isGecko && !hasAbsolute) {
12071                         dbd = fly(bd);
12072                         x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
12073                         y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
12074                     }
12075
12076                     p = el.parentNode;
12077                     while (p && p != bd) {
12078                         if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {
12079                             x -= p.scrollLeft;
12080                             y -= p.scrollTop;
12081                         }
12082                         p = p.parentNode;
12083                     }
12084                     ret = [x,y];
12085                 }
12086             }
12087             return ret;
12088         },
12089
12090         setXY : function(el, xy) {
12091             (el = Ext.fly(el, '_setXY')).position();
12092
12093             var pts = el.translatePoints(xy),
12094                 style = el.dom.style,
12095                 pos;
12096
12097             for (pos in pts) {
12098                 if (!isNaN(pts[pos])) {
12099                     style[pos] = pts[pos] + "px";
12100                 }
12101             }
12102         },
12103
12104         setX : function(el, x) {
12105             ELEMENT.setXY(el, [x, false]);
12106         },
12107
12108         setY : function(el, y) {
12109             ELEMENT.setXY(el, [false, y]);
12110         },
12111
12112         
12113         serializeForm: function(form) {
12114             var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements,
12115                 hasSubmit = false,
12116                 encoder = encodeURIComponent,
12117                 name,
12118                 data = '',
12119                 type,
12120                 hasValue;
12121
12122             Ext.each(fElements, function(element){
12123                 name = element.name;
12124                 type = element.type;
12125
12126                 if (!element.disabled && name) {
12127                     if (/select-(one|multiple)/i.test(type)) {
12128                         Ext.each(element.options, function(opt){
12129                             if (opt.selected) {
12130                                 hasValue = opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttributeNode('value').specified;
12131                                 data += Ext.String.format("{0}={1}&", encoder(name), encoder(hasValue ? opt.value : opt.text));
12132                             }
12133                         });
12134                     } else if (!(/file|undefined|reset|button/i.test(type))) {
12135                         if (!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)) {
12136                             data += encoder(name) + '=' + encoder(element.value) + '&';
12137                             hasSubmit = /submit/i.test(type);
12138                         }
12139                     }
12140                 }
12141             });
12142             return data.substr(0, data.length - 1);
12143         }
12144     });
12145 })();
12146
12147
12148
12149 Ext.core.Element.addMethods({
12150
12151     
12152     monitorMouseLeave: function(delay, handler, scope) {
12153         var me = this,
12154             timer,
12155             listeners = {
12156                 mouseleave: function(e) {
12157                     timer = setTimeout(Ext.Function.bind(handler, scope||me, [e]), delay);
12158                 },
12159                 mouseenter: function() {
12160                     clearTimeout(timer);
12161                 },
12162                 freezeEvent: true
12163             };
12164
12165         me.on(listeners);
12166         return listeners;
12167     },
12168
12169     
12170     swallowEvent : function(eventName, preventDefault) {
12171         var me = this;
12172         function fn(e) {
12173             e.stopPropagation();
12174             if (preventDefault) {
12175                 e.preventDefault();
12176             }
12177         }
12178         
12179         if (Ext.isArray(eventName)) {
12180             Ext.each(eventName, function(e) {
12181                  me.on(e, fn);
12182             });
12183             return me;
12184         }
12185         me.on(eventName, fn);
12186         return me;
12187     },
12188
12189     
12190     relayEvent : function(eventName, observable) {
12191         this.on(eventName, function(e) {
12192             observable.fireEvent(eventName, e);
12193         });
12194     },
12195
12196     
12197     clean : function(forceReclean) {
12198         var me  = this,
12199             dom = me.dom,
12200             n   = dom.firstChild,
12201             nx,
12202             ni  = -1;
12203
12204         if (Ext.core.Element.data(dom, 'isCleaned') && forceReclean !== true) {
12205             return me;
12206         }
12207
12208         while (n) {
12209             nx = n.nextSibling;
12210             if (n.nodeType == 3) {
12211                 
12212                 if (!(/\S/.test(n.nodeValue))) {
12213                     dom.removeChild(n);
12214                 
12215                 } else if (nx && nx.nodeType == 3) {
12216                     n.appendData(Ext.String.trim(nx.data));
12217                     dom.removeChild(nx);
12218                     nx = n.nextSibling;
12219                     n.nodeIndex = ++ni;
12220                 }
12221             } else {
12222                 
12223                 Ext.fly(n).clean();
12224                 n.nodeIndex = ++ni;
12225             }
12226             n = nx;
12227         }
12228
12229         Ext.core.Element.data(dom, 'isCleaned', true);
12230         return me;
12231     },
12232
12233     
12234     load : function(options) {
12235         this.getLoader().load(options);
12236         return this;
12237     },
12238
12239     
12240     getLoader : function() {
12241         var dom = this.dom,
12242             data = Ext.core.Element.data,
12243             loader = data(dom, 'loader');
12244             
12245         if (!loader) {
12246             loader = Ext.create('Ext.ElementLoader', {
12247                 target: this
12248             });
12249             data(dom, 'loader', loader);
12250         }
12251         return loader;
12252     },
12253
12254     
12255     update : function(html, loadScripts, callback) {
12256         var me = this,
12257             id,
12258             dom,
12259             interval;
12260             
12261         if (!me.dom) {
12262             return me;
12263         }
12264         html = html || '';
12265         dom = me.dom;
12266
12267         if (loadScripts !== true) {
12268             dom.innerHTML = html;
12269             Ext.callback(callback, me);
12270             return me;
12271         }
12272
12273         id  = Ext.id();
12274         html += '<span id="' + id + '"></span>';
12275
12276         interval = setInterval(function(){
12277             if (!document.getElementById(id)) {
12278                 return false;    
12279             }
12280             clearInterval(interval);
12281             var DOC    = document,
12282                 hd     = DOC.getElementsByTagName("head")[0],
12283                 re     = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
12284                 srcRe  = /\ssrc=([\'\"])(.*?)\1/i,
12285                 typeRe = /\stype=([\'\"])(.*?)\1/i,
12286                 match,
12287                 attrs,
12288                 srcMatch,
12289                 typeMatch,
12290                 el,
12291                 s;
12292
12293             while ((match = re.exec(html))) {
12294                 attrs = match[1];
12295                 srcMatch = attrs ? attrs.match(srcRe) : false;
12296                 if (srcMatch && srcMatch[2]) {
12297                    s = DOC.createElement("script");
12298                    s.src = srcMatch[2];
12299                    typeMatch = attrs.match(typeRe);
12300                    if (typeMatch && typeMatch[2]) {
12301                        s.type = typeMatch[2];
12302                    }
12303                    hd.appendChild(s);
12304                 } else if (match[2] && match[2].length > 0) {
12305                     if (window.execScript) {
12306                        window.execScript(match[2]);
12307                     } else {
12308                        window.eval(match[2]);
12309                     }
12310                 }
12311             }
12312             
12313             el = DOC.getElementById(id);
12314             if (el) {
12315                 Ext.removeNode(el);
12316             }
12317             Ext.callback(callback, me);
12318         }, 20);
12319         dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, '');
12320         return me;
12321     },
12322
12323     
12324     removeAllListeners : function() {
12325         this.removeAnchor();
12326         Ext.EventManager.removeAll(this.dom);
12327         return this;
12328     },
12329
12330     
12331     createProxy : function(config, renderTo, matchBox) {
12332         config = (typeof config == 'object') ? config : {tag : "div", cls: config};
12333
12334         var me = this,
12335             proxy = renderTo ? Ext.core.DomHelper.append(renderTo, config, true) :
12336                                Ext.core.DomHelper.insertBefore(me.dom, config, true);
12337
12338         proxy.setVisibilityMode(Ext.core.Element.DISPLAY);
12339         proxy.hide();
12340         if (matchBox && me.setBox && me.getBox) { 
12341            proxy.setBox(me.getBox());
12342         }
12343         return proxy;
12344     }
12345 });
12346 Ext.core.Element.prototype.clearListeners = Ext.core.Element.prototype.removeAllListeners;
12347
12348
12349 Ext.core.Element.addMethods({
12350     
12351     getAnchorXY : function(anchor, local, s){
12352         
12353         
12354         anchor = (anchor || "tl").toLowerCase();
12355         s = s || {};
12356
12357         var me = this,
12358             vp = me.dom == document.body || me.dom == document,
12359             w = s.width || vp ? Ext.core.Element.getViewWidth() : me.getWidth(),
12360             h = s.height || vp ? Ext.core.Element.getViewHeight() : me.getHeight(),
12361             xy,
12362             r = Math.round,
12363             o = me.getXY(),
12364             scroll = me.getScroll(),
12365             extraX = vp ? scroll.left : !local ? o[0] : 0,
12366             extraY = vp ? scroll.top : !local ? o[1] : 0,
12367             hash = {
12368                 c  : [r(w * 0.5), r(h * 0.5)],
12369                 t  : [r(w * 0.5), 0],
12370                 l  : [0, r(h * 0.5)],
12371                 r  : [w, r(h * 0.5)],
12372                 b  : [r(w * 0.5), h],
12373                 tl : [0, 0],
12374                 bl : [0, h],
12375                 br : [w, h],
12376                 tr : [w, 0]
12377             };
12378
12379         xy = hash[anchor];
12380         return [xy[0] + extraX, xy[1] + extraY];
12381     },
12382
12383     
12384     anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
12385         var me = this,
12386             dom = me.dom,
12387             scroll = !Ext.isEmpty(monitorScroll),
12388             action = function(){
12389                 Ext.fly(dom).alignTo(el, alignment, offsets, animate);
12390                 Ext.callback(callback, Ext.fly(dom));
12391             },
12392             anchor = this.getAnchor();
12393
12394         
12395         this.removeAnchor();
12396         Ext.apply(anchor, {
12397             fn: action,
12398             scroll: scroll
12399         });
12400
12401         Ext.EventManager.onWindowResize(action, null);
12402
12403         if(scroll){
12404             Ext.EventManager.on(window, 'scroll', action, null,
12405                 {buffer: !isNaN(monitorScroll) ? monitorScroll : 50});
12406         }
12407         action.call(me); 
12408         return me;
12409     },
12410
12411     
12412     removeAnchor : function(){
12413         var me = this,
12414             anchor = this.getAnchor();
12415
12416         if(anchor && anchor.fn){
12417             Ext.EventManager.removeResizeListener(anchor.fn);
12418             if(anchor.scroll){
12419                 Ext.EventManager.un(window, 'scroll', anchor.fn);
12420             }
12421             delete anchor.fn;
12422         }
12423         return me;
12424     },
12425
12426     
12427     getAnchor : function(){
12428         var data = Ext.core.Element.data,
12429             dom = this.dom;
12430             if (!dom) {
12431                 return;
12432             }
12433             var anchor = data(dom, '_anchor');
12434
12435         if(!anchor){
12436             anchor = data(dom, '_anchor', {});
12437         }
12438         return anchor;
12439     },
12440
12441     getAlignVector: function(el, spec, offset) {
12442         var me = this,
12443             side = {t:"top", l:"left", r:"right", b: "bottom"},
12444             thisRegion = me.getRegion(),
12445             elRegion;
12446
12447         el = Ext.get(el);
12448         if(!el || !el.dom){
12449             Ext.Error.raise({
12450                 sourceClass: 'Ext.core.Element',
12451                 sourceMethod: 'getAlignVector',
12452                 msg: 'Attempted to align an element that doesn\'t exist'
12453             });
12454         }
12455
12456         elRegion = el.getRegion();
12457     },
12458
12459     
12460     getAlignToXY : function(el, p, o){
12461         el = Ext.get(el);
12462
12463         if(!el || !el.dom){
12464             Ext.Error.raise({
12465                 sourceClass: 'Ext.core.Element',
12466                 sourceMethod: 'getAlignToXY',
12467                 msg: 'Attempted to align an element that doesn\'t exist'
12468             });
12469         }
12470
12471         o = o || [0,0];
12472         p = (!p || p == "?" ? "tl-bl?" : (!(/-/).test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();
12473
12474         var me = this,
12475             d = me.dom,
12476             a1,
12477             a2,
12478             x,
12479             y,
12480             
12481             w,
12482             h,
12483             r,
12484             dw = Ext.core.Element.getViewWidth() -10, 
12485             dh = Ext.core.Element.getViewHeight()-10, 
12486             p1y,
12487             p1x,
12488             p2y,
12489             p2x,
12490             swapY,
12491             swapX,
12492             doc = document,
12493             docElement = doc.documentElement,
12494             docBody = doc.body,
12495             scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
12496             scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
12497             c = false, 
12498             p1 = "",
12499             p2 = "",
12500             m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
12501
12502         if(!m){
12503             Ext.Error.raise({
12504                 sourceClass: 'Ext.core.Element',
12505                 sourceMethod: 'getAlignToXY',
12506                 el: el,
12507                 position: p,
12508                 offset: o,
12509                 msg: 'Attemmpted to align an element with an invalid position: "' + p + '"'
12510             });
12511         }
12512
12513         p1 = m[1];
12514         p2 = m[2];
12515         c = !!m[3];
12516
12517         
12518         
12519         a1 = me.getAnchorXY(p1, true);
12520         a2 = el.getAnchorXY(p2, false);
12521
12522         x = a2[0] - a1[0] + o[0];
12523         y = a2[1] - a1[1] + o[1];
12524
12525         if(c){
12526            w = me.getWidth();
12527            h = me.getHeight();
12528            r = el.getRegion();
12529            
12530            
12531            
12532            p1y = p1.charAt(0);
12533            p1x = p1.charAt(p1.length-1);
12534            p2y = p2.charAt(0);
12535            p2x = p2.charAt(p2.length-1);
12536            swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
12537            swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
12538
12539
12540            if (x + w > dw + scrollX) {
12541                 x = swapX ? r.left-w : dw+scrollX-w;
12542            }
12543            if (x < scrollX) {
12544                x = swapX ? r.right : scrollX;
12545            }
12546            if (y + h > dh + scrollY) {
12547                 y = swapY ? r.top-h : dh+scrollY-h;
12548             }
12549            if (y < scrollY){
12550                y = swapY ? r.bottom : scrollY;
12551            }
12552         }
12553         return [x,y];
12554     },
12555
12556     
12557     alignTo : function(element, position, offsets, animate){
12558         var me = this;
12559         return me.setXY(me.getAlignToXY(element, position, offsets),
12560                         me.anim && !!animate ? me.anim(animate) : false);
12561     },
12562
12563     
12564     adjustForConstraints : function(xy, parent) {
12565         var vector = this.getConstrainVector(parent, xy);
12566         if (vector) {
12567             xy[0] += vector[0];
12568             xy[1] += vector[1];
12569         }
12570         return xy;
12571     },
12572
12573     
12574     getConstrainVector: function(constrainTo, proposedPosition) {
12575         if (!(constrainTo instanceof Ext.util.Region)) {
12576             constrainTo = Ext.get(constrainTo).getViewRegion();
12577         }
12578         var thisRegion = this.getRegion(),
12579             vector = [0, 0],
12580             shadowSize = this.shadow && this.shadow.offset,
12581             overflowed = false;
12582
12583         
12584         if (proposedPosition) {
12585             thisRegion.translateBy(proposedPosition[0] - thisRegion.x, proposedPosition[1] - thisRegion.y);
12586         }
12587
12588         
12589         
12590         if (shadowSize) {
12591             constrainTo.adjust(0, -shadowSize, -shadowSize, shadowSize);
12592         }
12593
12594         
12595         if (thisRegion.right > constrainTo.right) {
12596             overflowed = true;
12597             vector[0] = (constrainTo.right - thisRegion.right);    
12598         }
12599         if (thisRegion.left + vector[0] < constrainTo.left) {
12600             overflowed = true;
12601             vector[0] = (constrainTo.left - thisRegion.left);      
12602         }
12603
12604         
12605         if (thisRegion.bottom > constrainTo.bottom) {
12606             overflowed = true;
12607             vector[1] = (constrainTo.bottom - thisRegion.bottom);  
12608         }
12609         if (thisRegion.top + vector[1] < constrainTo.top) {
12610             overflowed = true;
12611             vector[1] = (constrainTo.top - thisRegion.top);        
12612         }
12613         return overflowed ? vector : false;
12614     },
12615
12616     
12617     getCenterXY : function(){
12618         return this.getAlignToXY(document, 'c-c');
12619     },
12620
12621     
12622     center : function(centerIn){
12623         return this.alignTo(centerIn || document, 'c-c');
12624     }
12625 });
12626
12627
12628 (function(){
12629
12630 var ELEMENT = Ext.core.Element,
12631     LEFT = "left",
12632     RIGHT = "right",
12633     TOP = "top",
12634     BOTTOM = "bottom",
12635     POSITION = "position",
12636     STATIC = "static",
12637     RELATIVE = "relative",
12638     AUTO = "auto",
12639     ZINDEX = "z-index";
12640
12641 Ext.override(Ext.core.Element, {
12642     
12643     getX : function(){
12644         return ELEMENT.getX(this.dom);
12645     },
12646
12647     
12648     getY : function(){
12649         return ELEMENT.getY(this.dom);
12650     },
12651
12652     
12653     getXY : function(){
12654         return ELEMENT.getXY(this.dom);
12655     },
12656
12657     
12658     getOffsetsTo : function(el){
12659         var o = this.getXY(),
12660             e = Ext.fly(el, '_internal').getXY();
12661         return [o[0]-e[0],o[1]-e[1]];
12662     },
12663
12664     
12665     setX : function(x, animate){
12666         return this.setXY([x, this.getY()], animate);
12667     },
12668
12669     
12670     setY : function(y, animate){
12671         return this.setXY([this.getX(), y], animate);
12672     },
12673
12674     
12675     setLeft : function(left){
12676         this.setStyle(LEFT, this.addUnits(left));
12677         return this;
12678     },
12679
12680     
12681     setTop : function(top){
12682         this.setStyle(TOP, this.addUnits(top));
12683         return this;
12684     },
12685
12686     
12687     setRight : function(right){
12688         this.setStyle(RIGHT, this.addUnits(right));
12689         return this;
12690     },
12691
12692     
12693     setBottom : function(bottom){
12694         this.setStyle(BOTTOM, this.addUnits(bottom));
12695         return this;
12696     },
12697
12698     
12699     setXY: function(pos, animate) {
12700         var me = this;
12701         if (!animate || !me.anim) {
12702             ELEMENT.setXY(me.dom, pos);
12703         }
12704         else {
12705             if (!Ext.isObject(animate)) {
12706                 animate = {};
12707             }
12708             me.animate(Ext.applyIf({ to: { x: pos[0], y: pos[1] } }, animate));
12709         }
12710         return me;
12711     },
12712
12713     
12714     setLocation : function(x, y, animate){
12715         return this.setXY([x, y], animate);
12716     },
12717
12718     
12719     moveTo : function(x, y, animate){
12720         return this.setXY([x, y], animate);
12721     },
12722
12723     
12724     getLeft : function(local){
12725         return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
12726     },
12727
12728     
12729     getRight : function(local){
12730         var me = this;
12731         return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
12732     },
12733
12734     
12735     getTop : function(local) {
12736         return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
12737     },
12738
12739     
12740     getBottom : function(local){
12741         var me = this;
12742         return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
12743     },
12744
12745     
12746     position : function(pos, zIndex, x, y) {
12747         var me = this;
12748
12749         if (!pos && me.isStyle(POSITION, STATIC)){
12750             me.setStyle(POSITION, RELATIVE);
12751         } else if(pos) {
12752             me.setStyle(POSITION, pos);
12753         }
12754         if (zIndex){
12755             me.setStyle(ZINDEX, zIndex);
12756         }
12757         if (x || y) {
12758             me.setXY([x || false, y || false]);
12759         }
12760     },
12761
12762     
12763     clearPositioning : function(value){
12764         value = value || '';
12765         this.setStyle({
12766             left : value,
12767             right : value,
12768             top : value,
12769             bottom : value,
12770             "z-index" : "",
12771             position : STATIC
12772         });
12773         return this;
12774     },
12775
12776     
12777     getPositioning : function(){
12778         var l = this.getStyle(LEFT);
12779         var t = this.getStyle(TOP);
12780         return {
12781             "position" : this.getStyle(POSITION),
12782             "left" : l,
12783             "right" : l ? "" : this.getStyle(RIGHT),
12784             "top" : t,
12785             "bottom" : t ? "" : this.getStyle(BOTTOM),
12786             "z-index" : this.getStyle(ZINDEX)
12787         };
12788     },
12789
12790     
12791     setPositioning : function(pc){
12792         var me = this,
12793             style = me.dom.style;
12794
12795         me.setStyle(pc);
12796
12797         if(pc.right == AUTO){
12798             style.right = "";
12799         }
12800         if(pc.bottom == AUTO){
12801             style.bottom = "";
12802         }
12803
12804         return me;
12805     },
12806
12807     
12808     translatePoints: function(x, y) {
12809         if (Ext.isArray(x)) {
12810              y = x[1];
12811              x = x[0];
12812         }
12813         var me = this,
12814             relative = me.isStyle(POSITION, RELATIVE),
12815             o = me.getXY(),
12816             left = parseInt(me.getStyle(LEFT), 10),
12817             top = parseInt(me.getStyle(TOP), 10);
12818
12819         if (!Ext.isNumber(left)) {
12820             left = relative ? 0 : me.dom.offsetLeft;
12821         }
12822         if (!Ext.isNumber(top)) {
12823             top = relative ? 0 : me.dom.offsetTop;
12824         }
12825         left = (Ext.isNumber(x)) ? x - o[0] + left : undefined;
12826         top = (Ext.isNumber(y)) ? y - o[1] + top : undefined;
12827         return {
12828             left: left,
12829             top: top
12830         };
12831     },
12832
12833     
12834     setBox: function(box, adjust, animate) {
12835         var me = this,
12836             w = box.width,
12837             h = box.height;
12838         if ((adjust && !me.autoBoxAdjust) && !me.isBorderBox()) {
12839             w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
12840             h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
12841         }
12842         me.setBounds(box.x, box.y, w, h, animate);
12843         return me;
12844     },
12845
12846     
12847     getBox: function(contentBox, local) {
12848         var me = this,
12849             xy,
12850             left,
12851             top,
12852             getBorderWidth = me.getBorderWidth,
12853             getPadding = me.getPadding,
12854             l, r, t, b, w, h, bx;
12855         if (!local) {
12856             xy = me.getXY();
12857         } else {
12858             left = parseInt(me.getStyle("left"), 10) || 0;
12859             top = parseInt(me.getStyle("top"), 10) || 0;
12860             xy = [left, top];
12861         }
12862         w = me.getWidth();
12863         h = me.getHeight();
12864         if (!contentBox) {
12865             bx = {
12866                 x: xy[0],
12867                 y: xy[1],
12868                 0: xy[0],
12869                 1: xy[1],
12870                 width: w,
12871                 height: h
12872             };
12873         } else {
12874             l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
12875             r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
12876             t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
12877             b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
12878             bx = {
12879                 x: xy[0] + l,
12880                 y: xy[1] + t,
12881                 0: xy[0] + l,
12882                 1: xy[1] + t,
12883                 width: w - (l + r),
12884                 height: h - (t + b)
12885             };
12886         }
12887         bx.right = bx.x + bx.width;
12888         bx.bottom = bx.y + bx.height;
12889         return bx;
12890     },
12891
12892     
12893     move: function(direction, distance, animate) {
12894         var me = this,
12895             xy = me.getXY(),
12896             x = xy[0],
12897             y = xy[1],
12898             left = [x - distance, y],
12899             right = [x + distance, y],
12900             top = [x, y - distance],
12901             bottom = [x, y + distance],
12902             hash = {
12903                 l: left,
12904                 left: left,
12905                 r: right,
12906                 right: right,
12907                 t: top,
12908                 top: top,
12909                 up: top,
12910                 b: bottom,
12911                 bottom: bottom,
12912                 down: bottom
12913             };
12914
12915         direction = direction.toLowerCase();
12916         me.moveTo(hash[direction][0], hash[direction][1], animate);
12917     },
12918
12919     
12920     setLeftTop: function(left, top) {
12921         var me = this,
12922             style = me.dom.style;
12923         style.left = me.addUnits(left);
12924         style.top = me.addUnits(top);
12925         return me;
12926     },
12927
12928     
12929     getRegion: function() {
12930         return this.getPageBox(true);
12931     },
12932
12933     
12934     getViewRegion: function() {
12935         var me = this,
12936             isBody = me.dom === document.body,
12937             scroll, pos, top, left, width, height;
12938             
12939         
12940         if (isBody) {
12941             scroll = me.getScroll();
12942             left = scroll.left;
12943             top = scroll.top;
12944             width = Ext.core.Element.getViewportWidth();
12945             height = Ext.core.Element.getViewportHeight();
12946         }
12947         else {
12948             pos = me.getXY();
12949             left = pos[0] + me.getBorderWidth('l') + me.getPadding('l');
12950             top = pos[1] + me.getBorderWidth('t') + me.getPadding('t');
12951             width = me.getWidth(true);
12952             height = me.getHeight(true);
12953         }
12954
12955         return Ext.create('Ext.util.Region', top, left + width, top + height, left);
12956     },
12957
12958     
12959     getPageBox : function(getRegion) {
12960         var me = this,
12961             el = me.dom,
12962             isDoc = el === document.body,
12963             w = isDoc ? Ext.core.Element.getViewWidth()  : el.offsetWidth,
12964             h = isDoc ? Ext.core.Element.getViewHeight() : el.offsetHeight,
12965             xy = me.getXY(),
12966             t = xy[1],
12967             r = xy[0] + w,
12968             b = xy[1] + h,
12969             l = xy[0];
12970
12971         if (getRegion) {
12972             return Ext.create('Ext.util.Region', t, r, b, l);
12973         }
12974         else {
12975             return {
12976                 left: l,
12977                 top: t,
12978                 width: w,
12979                 height: h,
12980                 right: r,
12981                 bottom: b
12982             };
12983         }
12984     },
12985
12986     
12987     setBounds: function(x, y, width, height, animate) {
12988         var me = this;
12989         if (!animate || !me.anim) {
12990             me.setSize(width, height);
12991             me.setLocation(x, y);
12992         } else {
12993             if (!Ext.isObject(animate)) {
12994                 animate = {};
12995             }
12996             me.animate(Ext.applyIf({
12997                 to: {
12998                     x: x,
12999                     y: y,
13000                     width: me.adjustWidth(width),
13001                     height: me.adjustHeight(height)
13002                 }
13003             }, animate));
13004         }
13005         return me;
13006     },
13007
13008     
13009     setRegion: function(region, animate) {
13010         return this.setBounds(region.left, region.top, region.right - region.left, region.bottom - region.top, animate);
13011     }
13012 });
13013 })();
13014
13015
13016 Ext.override(Ext.core.Element, {
13017     
13018     isScrollable : function(){
13019         var dom = this.dom;
13020         return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
13021     },
13022
13023     
13024     getScroll : function() {
13025         var d = this.dom, 
13026             doc = document,
13027             body = doc.body,
13028             docElement = doc.documentElement,
13029             l,
13030             t,
13031             ret;
13032
13033         if (d == doc || d == body) {
13034             if (Ext.isIE && Ext.isStrict) {
13035                 l = docElement.scrollLeft; 
13036                 t = docElement.scrollTop;
13037             } else {
13038                 l = window.pageXOffset;
13039                 t = window.pageYOffset;
13040             }
13041             ret = {
13042                 left: l || (body ? body.scrollLeft : 0), 
13043                 top : t || (body ? body.scrollTop : 0)
13044             };
13045         } else {
13046             ret = {
13047                 left: d.scrollLeft, 
13048                 top : d.scrollTop
13049             };
13050         }
13051         
13052         return ret;
13053     },
13054     
13055     
13056     scrollTo : function(side, value, animate) {
13057         
13058         var top = /top/i.test(side),
13059             me = this,
13060             dom = me.dom,
13061             obj = {},
13062             prop;
13063         if (!animate || !me.anim) {
13064             
13065             prop = 'scroll' + (top ? 'Top' : 'Left');
13066             dom[prop] = value;
13067         }
13068         else {
13069             if (!Ext.isObject(animate)) {
13070                 animate = {};
13071             }
13072             obj['scroll' + (top ? 'Top' : 'Left')] = value;
13073             me.animate(Ext.applyIf({
13074                 to: obj
13075             }, animate));
13076         }
13077         return me;
13078     },
13079
13080     
13081     scrollIntoView : function(container, hscroll) {
13082         container = Ext.getDom(container) || Ext.getBody().dom;
13083         var el = this.dom,
13084             offsets = this.getOffsetsTo(container),
13085             
13086             left = offsets[0] + container.scrollLeft,
13087             top = offsets[1] + container.scrollTop,
13088             bottom = top + el.offsetHeight,
13089             right = left + el.offsetWidth,
13090             
13091             ctClientHeight = container.clientHeight,
13092             ctScrollTop = parseInt(container.scrollTop, 10),
13093             ctScrollLeft = parseInt(container.scrollLeft, 10),
13094             ctBottom = ctScrollTop + ctClientHeight,
13095             ctRight = ctScrollLeft + container.clientWidth;
13096
13097         if (el.offsetHeight > ctClientHeight || top < ctScrollTop) {
13098             container.scrollTop = top;
13099         } else if (bottom > ctBottom) {
13100             container.scrollTop = bottom - ctClientHeight;
13101         }
13102         
13103         container.scrollTop = container.scrollTop;
13104
13105         if (hscroll !== false) {
13106             if (el.offsetWidth > container.clientWidth || left < ctScrollLeft) {
13107                 container.scrollLeft = left;
13108             }
13109             else if (right > ctRight) {
13110                 container.scrollLeft = right - container.clientWidth;
13111             }
13112             container.scrollLeft = container.scrollLeft;
13113         }
13114         return this;
13115     },
13116
13117     
13118     scrollChildIntoView : function(child, hscroll) {
13119         Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
13120     },
13121
13122     
13123      scroll : function(direction, distance, animate) {
13124         if (!this.isScrollable()) {
13125             return false;
13126         }
13127         var el = this.dom,
13128             l = el.scrollLeft, t = el.scrollTop,
13129             w = el.scrollWidth, h = el.scrollHeight,
13130             cw = el.clientWidth, ch = el.clientHeight,
13131             scrolled = false, v,
13132             hash = {
13133                 l: Math.min(l + distance, w-cw),
13134                 r: v = Math.max(l - distance, 0),
13135                 t: Math.max(t - distance, 0),
13136                 b: Math.min(t + distance, h-ch)
13137             };
13138             hash.d = hash.b;
13139             hash.u = hash.t;
13140
13141         direction = direction.substr(0, 1);
13142         if ((v = hash[direction]) > -1) {
13143             scrolled = true;
13144             this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.anim(animate));
13145         }
13146         return scrolled;
13147     }
13148 });
13149
13150 Ext.core.Element.addMethods(
13151     function() {
13152         var VISIBILITY      = "visibility",
13153             DISPLAY         = "display",
13154             HIDDEN          = "hidden",
13155             NONE            = "none",
13156             XMASKED         = Ext.baseCSSPrefix + "masked",
13157             XMASKEDRELATIVE = Ext.baseCSSPrefix + "masked-relative",
13158             data            = Ext.core.Element.data;
13159
13160         return {
13161             
13162             isVisible : function(deep) {
13163                 var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE),
13164                     p   = this.dom.parentNode;
13165
13166                 if (deep !== true || !vis) {
13167                     return vis;
13168                 }
13169
13170                 while (p && !(/^body/i.test(p.tagName))) {
13171                     if (!Ext.fly(p, '_isVisible').isVisible()) {
13172                         return false;
13173                     }
13174                     p = p.parentNode;
13175                 }
13176                 return true;
13177             },
13178
13179             
13180             isDisplayed : function() {
13181                 return !this.isStyle(DISPLAY, NONE);
13182             },
13183
13184             
13185             enableDisplayMode : function(display) {
13186                 this.setVisibilityMode(Ext.core.Element.DISPLAY);
13187
13188                 if (!Ext.isEmpty(display)) {
13189                     data(this.dom, 'originalDisplay', display);
13190                 }
13191
13192                 return this;
13193             },
13194
13195             
13196             mask : function(msg, msgCls) {
13197                 var me  = this,
13198                     dom = me.dom,
13199                     setExpression = dom.style.setExpression,
13200                     dh  = Ext.core.DomHelper,
13201                     EXTELMASKMSG = Ext.baseCSSPrefix + "mask-msg",
13202                     el,
13203                     mask;
13204
13205                 if (!(/^body/i.test(dom.tagName) && me.getStyle('position') == 'static')) {
13206                     me.addCls(XMASKEDRELATIVE);
13207                 }
13208                 el = data(dom, 'maskMsg');
13209                 if (el) {
13210                     el.remove();
13211                 }
13212                 el = data(dom, 'mask');
13213                 if (el) {
13214                     el.remove();
13215                 }
13216
13217                 mask = dh.append(dom, {cls : Ext.baseCSSPrefix + "mask"}, true);
13218                 data(dom, 'mask', mask);
13219
13220                 me.addCls(XMASKED);
13221                 mask.setDisplayed(true);
13222
13223                 if (typeof msg == 'string') {
13224                     var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
13225                     data(dom, 'maskMsg', mm);
13226                     mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
13227                     mm.dom.firstChild.innerHTML = msg;
13228                     mm.setDisplayed(true);
13229                     mm.center(me);
13230                 }
13231                 
13232                 
13233                 
13234                 
13235                 
13236                 if (!Ext.supports.IncludePaddingInWidthCalculation && setExpression) {
13237                     mask.dom.style.setExpression('width', 'this.parentNode.offsetWidth + "px"');
13238                 }
13239
13240                 
13241                 
13242                 if (!Ext.supports.IncludePaddingInHeightCalculation && setExpression) {
13243                     mask.dom.style.setExpression('height', 'this.parentNode.offsetHeight + "px"');
13244                 }
13245                 
13246                 else if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') {
13247                     mask.setSize(undefined, me.getHeight());
13248                 }
13249                 return mask;
13250             },
13251
13252             
13253             unmask : function() {
13254                 var me      = this,
13255                     dom     = me.dom,
13256                     mask    = data(dom, 'mask'),
13257                     maskMsg = data(dom, 'maskMsg');
13258
13259                 if (mask) {
13260                     
13261                     if (mask.dom.style.clearExpression) {
13262                         mask.dom.style.clearExpression('width');
13263                         mask.dom.style.clearExpression('height');
13264                     }
13265                     if (maskMsg) {
13266                         maskMsg.remove();
13267                         data(dom, 'maskMsg', undefined);
13268                     }
13269
13270                     mask.remove();
13271                     data(dom, 'mask', undefined);
13272                     me.removeCls([XMASKED, XMASKEDRELATIVE]);
13273                 }
13274             },
13275             
13276             isMasked : function() {
13277                 var me = this,
13278                     mask = data(me.dom, 'mask'),
13279                     maskMsg = data(me.dom, 'maskMsg');
13280
13281                 if (mask && mask.isVisible()) {
13282                     if (maskMsg) {
13283                         maskMsg.center(me);
13284                     }
13285                     return true;
13286                 }
13287                 return false;
13288             },
13289
13290             
13291             createShim : function() {
13292                 var el = document.createElement('iframe'),
13293                     shim;
13294
13295                 el.frameBorder = '0';
13296                 el.className = Ext.baseCSSPrefix + 'shim';
13297                 el.src = Ext.SSL_SECURE_URL;
13298                 shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
13299                 shim.autoBoxAdjust = false;
13300                 return shim;
13301             }
13302         };
13303     }()
13304 );
13305
13306 Ext.core.Element.addMethods({
13307     
13308     addKeyListener : function(key, fn, scope){
13309         var config;
13310         if(typeof key != 'object' || Ext.isArray(key)){
13311             config = {
13312                 key: key,
13313                 fn: fn,
13314                 scope: scope
13315             };
13316         }else{
13317             config = {
13318                 key : key.key,
13319                 shift : key.shift,
13320                 ctrl : key.ctrl,
13321                 alt : key.alt,
13322                 fn: fn,
13323                 scope: scope
13324             };
13325         }
13326         return Ext.create('Ext.util.KeyMap', this, config);
13327     },
13328
13329     
13330     addKeyMap : function(config){
13331         return Ext.create('Ext.util.KeyMap', this, config);
13332     }
13333 });
13334
13335
13336
13337 Ext.CompositeElementLite.importElementMethods();
13338
13339
13340 Ext.apply(Ext.CompositeElementLite.prototype, {
13341     addElements : function(els, root){
13342         if(!els){
13343             return this;
13344         }
13345         if(typeof els == "string"){
13346             els = Ext.core.Element.selectorFunction(els, root);
13347         }
13348         var yels = this.elements;
13349         Ext.each(els, function(e) {
13350             yels.push(Ext.get(e));
13351         });
13352         return this;
13353     },
13354
13355     
13356     first : function(){
13357         return this.item(0);
13358     },
13359
13360     
13361     last : function(){
13362         return this.item(this.getCount()-1);
13363     },
13364
13365     
13366     contains : function(el){
13367         return this.indexOf(el) != -1;
13368     },
13369
13370     
13371     removeElement : function(keys, removeDom){
13372         var me = this,
13373             els = this.elements,
13374             el;
13375         Ext.each(keys, function(val){
13376             if ((el = (els[val] || els[val = me.indexOf(val)]))) {
13377                 if(removeDom){
13378                     if(el.dom){
13379                         el.remove();
13380                     }else{
13381                         Ext.removeNode(el);
13382                     }
13383                 }
13384                 els.splice(val, 1);
13385             }
13386         });
13387         return this;
13388     }
13389 });
13390
13391
13392 Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
13393     
13394     constructor : function(els, root){
13395         this.elements = [];
13396         this.add(els, root);
13397     },
13398     
13399     
13400     getElement : function(el){
13401         
13402         return el;
13403     },
13404     
13405     
13406     transformElement : function(el){
13407         return Ext.get(el);
13408     }
13409
13410     
13411
13412     
13413
13414     
13415 });
13416
13417
13418 Ext.core.Element.select = function(selector, unique, root){
13419     var els;
13420     if(typeof selector == "string"){
13421         els = Ext.core.Element.selectorFunction(selector, root);
13422     }else if(selector.length !== undefined){
13423         els = selector;
13424     }else{
13425         Ext.Error.raise({
13426             sourceClass: "Ext.core.Element",
13427             sourceMethod: "select",
13428             selector: selector,
13429             unique: unique,
13430             root: root,
13431             msg: "Invalid selector specified: " + selector
13432         });
13433     }
13434     return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
13435 };
13436
13437
13438 Ext.select = Ext.core.Element.select;
13439
13440
13441
13442
13443
13444 Ext.define('Ext.util.Observable', {
13445
13446     
13447
13448     requires: ['Ext.util.Event'],
13449
13450     statics: {
13451         
13452         releaseCapture: function(o) {
13453             o.fireEvent = this.prototype.fireEvent;
13454         },
13455
13456         
13457         capture: function(o, fn, scope) {
13458             o.fireEvent = Ext.Function.createInterceptor(o.fireEvent, fn, scope);
13459         },
13460
13461         
13462         observe: function(cls, listeners) {
13463             if (cls) {
13464                 if (!cls.isObservable) {
13465                     Ext.applyIf(cls, new this());
13466                     this.capture(cls.prototype, cls.fireEvent, cls);
13467                 }
13468                 if (Ext.isObject(listeners)) {
13469                     cls.on(listeners);
13470                 }
13471                 return cls;
13472             }
13473         }
13474     },
13475
13476     
13477
13478     
13479     
13480     isObservable: true,
13481
13482     constructor: function(config) {
13483         var me = this;
13484
13485         Ext.apply(me, config);
13486         if (me.listeners) {
13487             me.on(me.listeners);
13488             delete me.listeners;
13489         }
13490         me.events = me.events || {};
13491
13492         if (me.bubbleEvents) {
13493             me.enableBubble(me.bubbleEvents);
13494         }
13495     },
13496
13497     
13498     eventOptionsRe : /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|element|vertical|horizontal)$/,
13499
13500     
13501     addManagedListener : function(item, ename, fn, scope, options) {
13502         var me = this,
13503             managedListeners = me.managedListeners = me.managedListeners || [],
13504             config;
13505
13506         if (Ext.isObject(ename)) {
13507             options = ename;
13508             for (ename in options) {
13509                 if (options.hasOwnProperty(ename)) {
13510                     config = options[ename];
13511                     if (!me.eventOptionsRe.test(ename)) {
13512                         me.addManagedListener(item, ename, config.fn || config, config.scope || options.scope, config.fn ? config : options);
13513                     }
13514                 }
13515             }
13516         }
13517         else {
13518             managedListeners.push({
13519                 item: item,
13520                 ename: ename,
13521                 fn: fn,
13522                 scope: scope,
13523                 options: options
13524             });
13525
13526             item.on(ename, fn, scope, options);
13527         }
13528     },
13529
13530     
13531      removeManagedListener : function(item, ename, fn, scope) {
13532         var me = this,
13533             options,
13534             config,
13535             managedListeners,
13536             length,
13537             i;
13538
13539         if (Ext.isObject(ename)) {
13540             options = ename;
13541             for (ename in options) {
13542                 if (options.hasOwnProperty(ename)) {
13543                     config = options[ename];
13544                     if (!me.eventOptionsRe.test(ename)) {
13545                         me.removeManagedListener(item, ename, config.fn || config, config.scope || options.scope);
13546                     }
13547                 }
13548             }
13549         }
13550
13551         managedListeners = me.managedListeners ? me.managedListeners.slice() : [];
13552
13553         for (i = 0, length = managedListeners.length; i < length; i++) {
13554             me.removeManagedListenerItem(false, managedListeners[i], item, ename, fn, scope);
13555         }
13556     },
13557
13558     
13559     fireEvent: function() {
13560         var me = this,
13561             args = Ext.Array.toArray(arguments),
13562             ename = args[0].toLowerCase(),
13563             ret = true,
13564             event = me.events[ename],
13565             queue = me.eventQueue,
13566             parent;
13567
13568         if (me.eventsSuspended === true) {
13569             if (queue) {
13570                 queue.push(args);
13571             }
13572         } else if (event && Ext.isObject(event) && event.bubble) {
13573             if (event.fire.apply(event, args.slice(1)) === false) {
13574                 return false;
13575             }
13576             parent = me.getBubbleTarget && me.getBubbleTarget();
13577             if (parent && parent.isObservable) {
13578                 if (!parent.events[ename] || !Ext.isObject(parent.events[ename]) || !parent.events[ename].bubble) {
13579                     parent.enableBubble(ename);
13580                 }
13581                 return parent.fireEvent.apply(parent, args);
13582             }
13583         } else if (event && Ext.isObject(event)) {
13584             args.shift();
13585             ret = event.fire.apply(event, args);
13586         }
13587         return ret;
13588     },
13589
13590     
13591     addListener: function(ename, fn, scope, options) {
13592         var me = this,
13593             config,
13594             event;
13595
13596         if (Ext.isObject(ename)) {
13597             options = ename;
13598             for (ename in options) {
13599                 if (options.hasOwnProperty(ename)) {
13600                     config = options[ename];
13601                     if (!me.eventOptionsRe.test(ename)) {
13602                         me.addListener(ename, config.fn || config, config.scope || options.scope, config.fn ? config : options);
13603                     }
13604                 }
13605             }
13606         }
13607         else {
13608             ename = ename.toLowerCase();
13609             me.events[ename] = me.events[ename] || true;
13610             event = me.events[ename] || true;
13611             if (Ext.isBoolean(event)) {
13612                 me.events[ename] = event = new Ext.util.Event(me, ename);
13613             }
13614             event.addListener(fn, scope, Ext.isObject(options) ? options : {});
13615         }
13616     },
13617
13618     
13619     removeListener: function(ename, fn, scope) {
13620         var me = this,
13621             config,
13622             event,
13623             options;
13624
13625         if (Ext.isObject(ename)) {
13626             options = ename;
13627             for (ename in options) {
13628                 if (options.hasOwnProperty(ename)) {
13629                     config = options[ename];
13630                     if (!me.eventOptionsRe.test(ename)) {
13631                         me.removeListener(ename, config.fn || config, config.scope || options.scope);
13632                     }
13633                 }
13634             }
13635         } else {
13636             ename = ename.toLowerCase();
13637             event = me.events[ename];
13638             if (event && event.isEvent) {
13639                 event.removeListener(fn, scope);
13640             }
13641         }
13642     },
13643
13644     
13645     clearListeners: function() {
13646         var events = this.events,
13647             event,
13648             key;
13649
13650         for (key in events) {
13651             if (events.hasOwnProperty(key)) {
13652                 event = events[key];
13653                 if (event.isEvent) {
13654                     event.clearListeners();
13655                 }
13656             }
13657         }
13658
13659         this.clearManagedListeners();
13660     },
13661
13662     purgeListeners : function() {
13663         if (Ext.global.console) {
13664             Ext.global.console.warn('Observable: purgeListeners has been deprecated. Please use clearListeners.');
13665         }
13666         return this.clearListeners.apply(this, arguments);
13667     },
13668
13669     
13670     clearManagedListeners : function() {
13671         var managedListeners = this.managedListeners || [],
13672             i = 0,
13673             len = managedListeners.length;
13674
13675         for (; i < len; i++) {
13676             this.removeManagedListenerItem(true, managedListeners[i]);
13677         }
13678
13679         this.managedListeners = [];
13680     },
13681     
13682     
13683     removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
13684         if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
13685             managedListener.item.un(managedListener.ename, managedListener.fn, managedListener.scope);
13686             if (!isClear) {
13687                 Ext.Array.remove(this.managedListeners, managedListener);
13688             }    
13689         }
13690     },
13691
13692     purgeManagedListeners : function() {
13693         if (Ext.global.console) {
13694             Ext.global.console.warn('Observable: purgeManagedListeners has been deprecated. Please use clearManagedListeners.');
13695         }
13696         return this.clearManagedListeners.apply(this, arguments);
13697     },
13698
13699     
13700     addEvents: function(o) {
13701         var me = this,
13702             args,
13703             len,
13704             i;
13705             
13706             me.events = me.events || {};
13707         if (Ext.isString(o)) {
13708             args = arguments;
13709             i = args.length;
13710             
13711             while (i--) {
13712                 me.events[args[i]] = me.events[args[i]] || true;
13713             }
13714         } else {
13715             Ext.applyIf(me.events, o);
13716         }
13717     },
13718
13719     
13720     hasListener: function(ename) {
13721         var event = this.events[ename.toLowerCase()];
13722         return event && event.isEvent === true && event.listeners.length > 0;
13723     },
13724
13725     
13726     suspendEvents: function(queueSuspended) {
13727         this.eventsSuspended = true;
13728         if (queueSuspended && !this.eventQueue) {
13729             this.eventQueue = [];
13730         }
13731     },
13732
13733     
13734     resumeEvents: function() {
13735         var me = this,
13736             queued = me.eventQueue || [];
13737
13738         me.eventsSuspended = false;
13739         delete me.eventQueue;
13740
13741         Ext.each(queued,
13742         function(e) {
13743             me.fireEvent.apply(me, e);
13744         });
13745     },
13746
13747     
13748     relayEvents : function(origin, events, prefix) {
13749         prefix = prefix || '';
13750         var me = this,
13751             len = events.length,
13752             i = 0,
13753             oldName,
13754             newName;
13755
13756         for (; i < len; i++) {
13757             oldName = events[i].substr(prefix.length);
13758             newName = prefix + oldName;
13759             me.events[newName] = me.events[newName] || true;
13760             origin.on(oldName, me.createRelayer(newName));
13761         }
13762     },
13763
13764     
13765     createRelayer: function(newName){
13766         var me = this;
13767         return function(){
13768             return me.fireEvent.apply(me, [newName].concat(Array.prototype.slice.call(arguments, 0, -1)));
13769         };
13770     },
13771
13772     
13773     enableBubble: function(events) {
13774         var me = this;
13775         if (!Ext.isEmpty(events)) {
13776             events = Ext.isArray(events) ? events: Ext.Array.toArray(arguments);
13777             Ext.each(events,
13778             function(ename) {
13779                 ename = ename.toLowerCase();
13780                 var ce = me.events[ename] || true;
13781                 if (Ext.isBoolean(ce)) {
13782                     ce = new Ext.util.Event(me, ename);
13783                     me.events[ename] = ce;
13784                 }
13785                 ce.bubble = true;
13786             });
13787         }
13788     }
13789 }, function() {
13790     
13791
13792     
13793
13794     this.createAlias({
13795         on: 'addListener',
13796         un: 'removeListener',
13797         mon: 'addManagedListener',
13798         mun: 'removeManagedListener'
13799     });
13800
13801     
13802     this.observeClass = this.observe;
13803
13804     Ext.apply(Ext.util.Observable.prototype, function(){
13805         
13806         
13807         
13808         function getMethodEvent(method){
13809             var e = (this.methodEvents = this.methodEvents || {})[method],
13810                 returnValue,
13811                 v,
13812                 cancel,
13813                 obj = this;
13814
13815             if (!e) {
13816                 this.methodEvents[method] = e = {};
13817                 e.originalFn = this[method];
13818                 e.methodName = method;
13819                 e.before = [];
13820                 e.after = [];
13821
13822                 var makeCall = function(fn, scope, args){
13823                     if((v = fn.apply(scope || obj, args)) !== undefined){
13824                         if (typeof v == 'object') {
13825                             if(v.returnValue !== undefined){
13826                                 returnValue = v.returnValue;
13827                             }else{
13828                                 returnValue = v;
13829                             }
13830                             cancel = !!v.cancel;
13831                         }
13832                         else
13833                             if (v === false) {
13834                                 cancel = true;
13835                             }
13836                             else {
13837                                 returnValue = v;
13838                             }
13839                     }
13840                 };
13841
13842                 this[method] = function(){
13843                     var args = Array.prototype.slice.call(arguments, 0),
13844                         b, i, len;
13845                     returnValue = v = undefined;
13846                     cancel = false;
13847
13848                     for(i = 0, len = e.before.length; i < len; i++){
13849                         b = e.before[i];
13850                         makeCall(b.fn, b.scope, args);
13851                         if (cancel) {
13852                             return returnValue;
13853                         }
13854                     }
13855
13856                     if((v = e.originalFn.apply(obj, args)) !== undefined){
13857                         returnValue = v;
13858                     }
13859
13860                     for(i = 0, len = e.after.length; i < len; i++){
13861                         b = e.after[i];
13862                         makeCall(b.fn, b.scope, args);
13863                         if (cancel) {
13864                             return returnValue;
13865                         }
13866                     }
13867                     return returnValue;
13868                 };
13869             }
13870             return e;
13871         }
13872
13873         return {
13874             
13875             
13876             
13877             beforeMethod : function(method, fn, scope){
13878                 getMethodEvent.call(this, method).before.push({
13879                     fn: fn,
13880                     scope: scope
13881                 });
13882             },
13883
13884             
13885             afterMethod : function(method, fn, scope){
13886                 getMethodEvent.call(this, method).after.push({
13887                     fn: fn,
13888                     scope: scope
13889                 });
13890             },
13891
13892             removeMethodListener: function(method, fn, scope){
13893                 var e = this.getMethodEvent(method),
13894                     i, len;
13895                 for(i = 0, len = e.before.length; i < len; i++){
13896                     if(e.before[i].fn == fn && e.before[i].scope == scope){
13897                         e.before.splice(i, 1);
13898                         return;
13899                     }
13900                 }
13901                 for(i = 0, len = e.after.length; i < len; i++){
13902                     if(e.after[i].fn == fn && e.after[i].scope == scope){
13903                         e.after.splice(i, 1);
13904                         return;
13905                     }
13906                 }
13907             },
13908
13909             toggleEventLogging: function(toggle) {
13910                 Ext.util.Observable[toggle ? 'capture' : 'releaseCapture'](this, function(en) {
13911                     if (Ext.isDefined(Ext.global.console)) {
13912                         Ext.global.console.log(en, arguments);
13913                     }
13914                 });
13915             }
13916         };
13917     }());
13918 });
13919
13920
13921 Ext.define('Ext.util.Animate', {
13922
13923     uses: ['Ext.fx.Manager', 'Ext.fx.Anim'],
13924
13925     
13926     animate: function(animObj) {
13927         var me = this;
13928         if (Ext.fx.Manager.hasFxBlock(me.id)) {
13929             return me;
13930         }
13931         Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(animObj)));
13932         return this;
13933     },
13934
13935     
13936     anim: function(config) {
13937         if (!Ext.isObject(config)) {
13938             return (config) ? {} : false;
13939         }
13940
13941         var me = this;
13942
13943         if (config.stopAnimation) {
13944             me.stopAnimation();
13945         }
13946
13947         Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));
13948
13949         return Ext.apply({
13950             target: me,
13951             paused: true
13952         }, config);
13953     },
13954
13955     
13956     stopFx: Ext.Function.alias(Ext.util.Animate, 'stopAnimation'),
13957
13958     
13959     stopAnimation: function() {
13960         Ext.fx.Manager.stopAnimation(this.id);
13961         return this;
13962     },
13963
13964     
13965     syncFx: function() {
13966         Ext.fx.Manager.setFxDefaults(this.id, {
13967             concurrent: true
13968         });
13969         return this;
13970     },
13971
13972     
13973     sequenceFx: function() {
13974         Ext.fx.Manager.setFxDefaults(this.id, {
13975             concurrent: false
13976         });
13977         return this;
13978     },
13979
13980     
13981     hasActiveFx: Ext.Function.alias(Ext.util.Animate, 'getActiveAnimation'),
13982
13983     
13984     getActiveAnimation: function() {
13985         return Ext.fx.Manager.getActiveAnimation(this.id);
13986     }
13987 });
13988
13989
13990 Ext.applyIf(Ext.core.Element.prototype, Ext.util.Animate.prototype);
13991
13992 Ext.define('Ext.state.Provider', {
13993     mixins: {
13994         observable: 'Ext.util.Observable'
13995     },
13996     
13997     
13998     prefix: 'ext-',
13999     
14000     constructor : function(config){
14001         config = config || {};
14002         var me = this;
14003         Ext.apply(me, config);
14004         
14005         me.addEvents("statechange");
14006         me.state = {};
14007         me.mixins.observable.constructor.call(me);
14008     },
14009     
14010     
14011     get : function(name, defaultValue){
14012         return typeof this.state[name] == "undefined" ?
14013             defaultValue : this.state[name];
14014     },
14015
14016     
14017     clear : function(name){
14018         var me = this;
14019         delete me.state[name];
14020         me.fireEvent("statechange", me, name, null);
14021     },
14022
14023     
14024     set : function(name, value){
14025         var me = this;
14026         me.state[name] = value;
14027         me.fireEvent("statechange", me, name, value);
14028     },
14029
14030     
14031     decodeValue : function(value){
14032
14033         
14034         
14035         
14036         
14037         
14038         
14039         
14040
14041         var me = this,
14042             re = /^(a|n|d|b|s|o|e)\:(.*)$/,
14043             matches = re.exec(unescape(value)),
14044             all,
14045             type,
14046             value,
14047             keyValue;
14048             
14049         if(!matches || !matches[1]){
14050             return; 
14051         }
14052         
14053         type = matches[1];
14054         value = matches[2];
14055         switch (type) {
14056             case 'e':
14057                 return null;
14058             case 'n':
14059                 return parseFloat(value);
14060             case 'd':
14061                 return new Date(Date.parse(value));
14062             case 'b':
14063                 return (value == '1');
14064             case 'a':
14065                 all = [];
14066                 if(value != ''){
14067                     Ext.each(value.split('^'), function(val){
14068                         all.push(me.decodeValue(val));
14069                     }, me);
14070                 }
14071                 return all;
14072            case 'o':
14073                 all = {};
14074                 if(value != ''){
14075                     Ext.each(value.split('^'), function(val){
14076                         keyValue = val.split('=');
14077                         all[keyValue[0]] = me.decodeValue(keyValue[1]);
14078                     }, me);
14079                 }
14080                 return all;
14081            default:
14082                 return value;
14083         }
14084     },
14085
14086     
14087     encodeValue : function(value){
14088         var flat = '',
14089             i = 0,
14090             enc,
14091             len,
14092             key;
14093             
14094         if (value == null) {
14095             return 'e:1';    
14096         } else if(typeof value == 'number') {
14097             enc = 'n:' + value;
14098         } else if(typeof value == 'boolean') {
14099             enc = 'b:' + (value ? '1' : '0');
14100         } else if(Ext.isDate(value)) {
14101             enc = 'd:' + value.toGMTString();
14102         } else if(Ext.isArray(value)) {
14103             for (len = value.length; i < len; i++) {
14104                 flat += this.encodeValue(value[i]);
14105                 if (i != len - 1) {
14106                     flat += '^';
14107                 }
14108             }
14109             enc = 'a:' + flat;
14110         } else if (typeof value == 'object') {
14111             for (key in value) {
14112                 if (typeof value[key] != 'function' && value[key] !== undefined) {
14113                     flat += key + '=' + this.encodeValue(value[key]) + '^';
14114                 }
14115             }
14116             enc = 'o:' + flat.substring(0, flat.length-1);
14117         } else {
14118             enc = 's:' + value;
14119         }
14120         return escape(enc);
14121     }
14122 });
14123
14124 Ext.define('Ext.util.HashMap', {
14125
14126     
14127
14128     mixins: {
14129         observable: 'Ext.util.Observable'
14130     },
14131
14132     constructor: function(config) {
14133         var me = this;
14134
14135         me.addEvents(
14136             
14137             'add',
14138             
14139             'clear',
14140             
14141             'remove',
14142             
14143             'replace'
14144         );
14145
14146         me.mixins.observable.constructor.call(me, config);
14147         me.clear(true);
14148     },
14149
14150     
14151     getCount: function() {
14152         return this.length;
14153     },
14154
14155     
14156     getData: function(key, value) {
14157         
14158         if (value === undefined) {
14159             value = key;
14160             key = this.getKey(value);
14161         }
14162
14163         return [key, value];
14164     },
14165
14166     
14167     getKey: function(o) {
14168         return o.id;
14169     },
14170
14171     
14172     add: function(key, value) {
14173         var me = this,
14174             data;
14175
14176         if (arguments.length === 1) {
14177             value = key;
14178             key = me.getKey(value);
14179         }
14180
14181         if (me.containsKey(key)) {
14182             me.replace(key, value);
14183         }
14184
14185         data = me.getData(key, value);
14186         key = data[0];
14187         value = data[1];
14188         me.map[key] = value;
14189         ++me.length;
14190         me.fireEvent('add', me, key, value);
14191         return value;
14192     },
14193
14194     
14195     replace: function(key, value) {
14196         var me = this,
14197             map = me.map,
14198             old;
14199
14200         if (!me.containsKey(key)) {
14201             me.add(key, value);
14202         }
14203         old = map[key];
14204         map[key] = value;
14205         me.fireEvent('replace', me, key, value, old);
14206         return value;
14207     },
14208
14209     
14210     remove: function(o) {
14211         var key = this.findKey(o);
14212         if (key !== undefined) {
14213             return this.removeAtKey(key);
14214         }
14215         return false;
14216     },
14217
14218     
14219     removeAtKey: function(key) {
14220         var me = this,
14221             value;
14222
14223         if (me.containsKey(key)) {
14224             value = me.map[key];
14225             delete me.map[key];
14226             --me.length;
14227             me.fireEvent('remove', me, key, value);
14228             return true;
14229         }
14230         return false;
14231     },
14232
14233     
14234     get: function(key) {
14235         return this.map[key];
14236     },
14237
14238     
14239     clear: function( initial) {
14240         var me = this;
14241         me.map = {};
14242         me.length = 0;
14243         if (initial !== true) {
14244             me.fireEvent('clear', me);
14245         }
14246         return me;
14247     },
14248
14249     
14250     containsKey: function(key) {
14251         return this.map[key] !== undefined;
14252     },
14253
14254     
14255     contains: function(value) {
14256         return this.containsKey(this.findKey(value));
14257     },
14258
14259     
14260     getKeys: function() {
14261         return this.getArray(true);
14262     },
14263
14264     
14265     getValues: function() {
14266         return this.getArray(false);
14267     },
14268
14269     
14270     getArray: function(isKey) {
14271         var arr = [],
14272             key,
14273             map = this.map;
14274         for (key in map) {
14275             if (map.hasOwnProperty(key)) {
14276                 arr.push(isKey ? key: map[key]);
14277             }
14278         }
14279         return arr;
14280     },
14281
14282     
14283     each: function(fn, scope) {
14284         
14285         var items = Ext.apply({}, this.map),
14286             key,
14287             length = this.length;
14288
14289         scope = scope || this;
14290         for (key in items) {
14291             if (items.hasOwnProperty(key)) {
14292                 if (fn.call(scope, key, items[key], length) === false) {
14293                     break;
14294                 }
14295             }
14296         }
14297         return this;
14298     },
14299
14300     
14301     clone: function() {
14302         var hash = new this.self(),
14303             map = this.map,
14304             key;
14305
14306         hash.suspendEvents();
14307         for (key in map) {
14308             if (map.hasOwnProperty(key)) {
14309                 hash.add(key, map[key]);
14310             }
14311         }
14312         hash.resumeEvents();
14313         return hash;
14314     },
14315
14316     
14317     findKey: function(value) {
14318         var key,
14319             map = this.map;
14320
14321         for (key in map) {
14322             if (map.hasOwnProperty(key) && map[key] === value) {
14323                 return key;
14324             }
14325         }
14326         return undefined;
14327     }
14328 });
14329
14330
14331
14332 Ext.define('Ext.Template', {
14333
14334     
14335
14336     requires: ['Ext.core.DomHelper', 'Ext.util.Format'],
14337
14338     statics: {
14339         
14340         from: function(el, config) {
14341             el = Ext.getDom(el);
14342             return new this(el.value || el.innerHTML, config || '');
14343         }
14344     },
14345
14346     
14347
14348     constructor: function(html) {
14349         var me = this,
14350             args = arguments,
14351             buffer = [],
14352             i = 0,
14353             length = args.length,
14354             value;
14355
14356         me.initialConfig = {};
14357
14358         if (length > 1) {
14359             for (; i < length; i++) {
14360                 value = args[i];
14361                 if (typeof value == 'object') {
14362                     Ext.apply(me.initialConfig, value);
14363                     Ext.apply(me, value);
14364                 } else {
14365                     buffer.push(value);
14366                 }
14367             }
14368             html = buffer.join('');
14369         } else {
14370             if (Ext.isArray(html)) {
14371                 buffer.push(html.join(''));
14372             } else {
14373                 buffer.push(html);
14374             }
14375         }
14376
14377         
14378         me.html = buffer.join('');
14379
14380         if (me.compiled) {
14381             me.compile();
14382         }
14383     },
14384     isTemplate: true,
14385     
14386     disableFormats: false,
14387
14388     re: /\{([\w\-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
14389     
14390     applyTemplate: function(values) {
14391         var me = this,
14392             useFormat = me.disableFormats !== true,
14393             fm = Ext.util.Format,
14394             tpl = me;
14395
14396         if (me.compiled) {
14397             return me.compiled(values);
14398         }
14399         function fn(m, name, format, args) {
14400             if (format && useFormat) {
14401                 if (args) {
14402                     args = [values[name]].concat(Ext.functionFactory('return ['+ args +'];')());
14403                 } else {
14404                     args = [values[name]];
14405                 }
14406                 if (format.substr(0, 5) == "this.") {
14407                     return tpl[format.substr(5)].apply(tpl, args);
14408                 }
14409                 else {
14410                     return fm[format].apply(fm, args);
14411                 }
14412             }
14413             else {
14414                 return values[name] !== undefined ? values[name] : "";
14415             }
14416         }
14417         return me.html.replace(me.re, fn);
14418     },
14419
14420     
14421     set: function(html, compile) {
14422         var me = this;
14423         me.html = html;
14424         me.compiled = null;
14425         return compile ? me.compile() : me;
14426     },
14427
14428     compileARe: /\\/g,
14429     compileBRe: /(\r\n|\n)/g,
14430     compileCRe: /'/g,
14431     /**
14432      * Compiles the template into an internal function, eliminating the RegEx overhead.
14433      * @return {Ext.Template} this
14434      * @hide repeat doc
14435      */
14436     compile: function() {
14437         var me = this,
14438             fm = Ext.util.Format,
14439             useFormat = me.disableFormats !== true,
14440             body, bodyReturn;
14441
14442         function fn(m, name, format, args) {
14443             if (format && useFormat) {
14444                 args = args ? ',' + args: "";
14445                 if (format.substr(0, 5) != "this.") {
14446                     format = "fm." + format + '(';
14447                 }
14448                 else {
14449                     format = 'this.' + format.substr(5) + '(';
14450                 }
14451             }
14452             else {
14453                 args = '';
14454                 format = "(values['" + name + "'] == undefined ? '' : ";
14455             }
14456             return "'," + format + "values['" + name + "']" + args + ") ,'";
14457         }
14458
14459         bodyReturn = me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn);
14460         body = "this.compiled = function(values){ return ['" + bodyReturn + "'].join('');};";
14461         eval(body);
14462         return me;
14463     },
14464
14465     /**
14466      * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
14467      * @param {Mixed} el The context element
14468      * @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'})
14469      * @param {Boolean} returnElement (optional) true to return a Ext.core.Element (defaults to undefined)
14470      * @return {HTMLElement/Ext.core.Element} The new node or Element
14471      */
14472     insertFirst: function(el, values, returnElement) {
14473         return this.doInsert('afterBegin', el, values, returnElement);
14474     },
14475
14476     /**
14477      * Applies the supplied values to the template and inserts the new node(s) before el.
14478      * @param {Mixed} el The context element
14479      * @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'})
14480      * @param {Boolean} returnElement (optional) true to return a Ext.core.Element (defaults to undefined)
14481      * @return {HTMLElement/Ext.core.Element} The new node or Element
14482      */
14483     insertBefore: function(el, values, returnElement) {
14484         return this.doInsert('beforeBegin', el, values, returnElement);
14485     },
14486
14487     /**
14488      * Applies the supplied values to the template and inserts the new node(s) after el.
14489      * @param {Mixed} el The context element
14490      * @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'})
14491      * @param {Boolean} returnElement (optional) true to return a Ext.core.Element (defaults to undefined)
14492      * @return {HTMLElement/Ext.core.Element} The new node or Element
14493      */
14494     insertAfter: function(el, values, returnElement) {
14495         return this.doInsert('afterEnd', el, values, returnElement);
14496     },
14497
14498     /**
14499      * Applies the supplied <code>values</code> to the template and appends
14500      * the new node(s) to the specified <code>el</code>.
14501      * <p>For example usage {@link #Template see the constructor}.</p>
14502      * @param {Mixed} el The context element
14503      * @param {Object/Array} values
14504      * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
14505      * or an object (i.e. <code>{foo: 'bar'}</code>).
14506      * @param {Boolean} returnElement (optional) true to return an Ext.core.Element (defaults to undefined)
14507      * @return {HTMLElement/Ext.core.Element} The new node or Element
14508      */
14509     append: function(el, values, returnElement) {
14510         return this.doInsert('beforeEnd', el, values, returnElement);
14511     },
14512
14513     doInsert: function(where, el, values, returnEl) {
14514         el = Ext.getDom(el);
14515         var newNode = Ext.core.DomHelper.insertHtml(where, el, this.applyTemplate(values));
14516         return returnEl ? Ext.get(newNode, true) : newNode;
14517     },
14518
14519     /**
14520      * Applies the supplied values to the template and overwrites the content of el with the new node(s).
14521      * @param {Mixed} el The context element
14522      * @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'})
14523      * @param {Boolean} returnElement (optional) true to return a Ext.core.Element (defaults to undefined)
14524      * @return {HTMLElement/Ext.core.Element} The new node or Element
14525      */
14526     overwrite: function(el, values, returnElement) {
14527         el = Ext.getDom(el);
14528         el.innerHTML = this.applyTemplate(values);
14529         return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
14530     }
14531 }, function() {
14532
14533     /**
14534      * Alias for {@link #applyTemplate}
14535      * Returns an HTML fragment of this template with the specified <code>values</code> applied.
14536      * @param {Object/Array} values
14537      * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
14538      * or an object (i.e. <code>{foo: 'bar'}</code>).
14539      * @return {String} The HTML fragment
14540      * @member Ext.Template
14541      * @method apply
14542      */
14543     this.createAlias('apply', 'applyTemplate');
14544 });
14545
14546 /**
14547  * @class Ext.ComponentQuery
14548  * @extends Object
14549  *
14550  * Provides searching of Components within Ext.ComponentManager (globally) or a specific
14551  * Ext.container.Container on the document with a similar syntax to a CSS selector.
14552  *
14553  * Components can be retrieved by using their {@link Ext.Component xtype} with an optional . prefix
14554 <ul>
14555     <li>component or .component</li>
14556     <li>gridpanel or .gridpanel</li>
14557 </ul>
14558  *
14559  * An itemId or id must be prefixed with a #
14560 <ul>
14561     <li>#myContainer</li>
14562 </ul>
14563  *
14564  *
14565  * Attributes must be wrapped in brackets
14566 <ul>
14567     <li>component[autoScroll]</li>
14568     <li>panel[title="Test"]</li>
14569 </ul>
14570  *
14571  * Member expressions from candidate Components may be tested. If the expression returns a <i>truthy</i> value,
14572  * the candidate Component will be included in the query:<pre><code>
14573 var disabledFields = myFormPanel.query("{isDisabled()}");
14574 </code></pre>
14575  *
14576  * Pseudo classes may be used to filter results in the same way as in {@link Ext.DomQuery DomQuery}:<code><pre>
14577 // Function receives array and returns a filtered array.
14578 Ext.ComponentQuery.pseudos.invalid = function(items) {
14579     var i = 0, l = items.length, c, result = [];
14580     for (; i < l; i++) {
14581         if (!(c = items[i]).isValid()) {
14582             result.push(c);
14583         }
14584     }
14585     return result;
14586 };
14587
14588 var invalidFields = myFormPanel.query('field:invalid');
14589 if (invalidFields.length) {
14590     invalidFields[0].getEl().scrollIntoView(myFormPanel.body);
14591     for (var i = 0, l = invalidFields.length; i < l; i++) {
14592         invalidFields[i].getEl().frame("red");
14593     }
14594 }
14595 </pre></code>
14596  * <p>
14597  * Default pseudos include:<br />
14598  * - not
14599  * </p>
14600  *
14601  * Queries return an array of components.
14602  * Here are some example queries.
14603 <pre><code>
14604     // retrieve all Ext.Panels in the document by xtype
14605     var panelsArray = Ext.ComponentQuery.query('panel');
14606
14607     // retrieve all Ext.Panels within the container with an id myCt
14608     var panelsWithinmyCt = Ext.ComponentQuery.query('#myCt panel');
14609
14610     // retrieve all direct children which are Ext.Panels within myCt
14611     var directChildPanel = Ext.ComponentQuery.query('#myCt > panel');
14612
14613     // retrieve all gridpanels and listviews
14614     var gridsAndLists = Ext.ComponentQuery.query('gridpanel, listview');
14615 </code></pre>
14616
14617 For easy access to queries based from a particular Container see the {@link Ext.container.Container#query},
14618 {@link Ext.container.Container#down} and {@link Ext.container.Container#child} methods. Also see
14619 {@link Ext.Component#up}.
14620  * @singleton
14621  */
14622 Ext.define('Ext.ComponentQuery', {
14623     singleton: true,
14624     uses: ['Ext.ComponentManager']
14625 }, function() {
14626
14627     var cq = this,
14628
14629         // A function source code pattern with a placeholder which accepts an expression which yields a truth value when applied
14630         // as a member on each item in the passed array.
14631         filterFnPattern = [
14632             'var r = [],',
14633                 'i = 0,',
14634                 'it = items,',
14635                 'l = it.length,',
14636                 'c;',
14637             'for (; i < l; i++) {',
14638                 'c = it[i];',
14639                 'if (c.{0}) {',
14640                    'r.push(c);',
14641                 '}',
14642             '}',
14643             'return r;'
14644         ].join(''),
14645
14646         filterItems = function(items, operation) {
14647             // Argument list for the operation is [ itemsArray, operationArg1, operationArg2...]
14648             // The operation's method loops over each item in the candidate array and
14649             // returns an array of items which match its criteria
14650             return operation.method.apply(this, [ items ].concat(operation.args));
14651         },
14652
14653         getItems = function(items, mode) {
14654             var result = [],
14655                 i = 0,
14656                 length = items.length,
14657                 candidate,
14658                 deep = mode !== '>';
14659                 
14660             for (; i < length; i++) {
14661                 candidate = items[i];
14662                 if (candidate.getRefItems) {
14663                     result = result.concat(candidate.getRefItems(deep));
14664                 }
14665             }
14666             return result;
14667         },
14668
14669         getAncestors = function(items) {
14670             var result = [],
14671                 i = 0,
14672                 length = items.length,
14673                 candidate;
14674             for (; i < length; i++) {
14675                 candidate = items[i];
14676                 while (!!(candidate = (candidate.ownerCt || candidate.floatParent))) {
14677                     result.push(candidate);
14678                 }
14679             }
14680             return result;
14681         },
14682
14683         // Filters the passed candidate array and returns only items which match the passed xtype
14684         filterByXType = function(items, xtype, shallow) {
14685             if (xtype === '*') {
14686                 return items.slice();
14687             }
14688             else {
14689                 var result = [],
14690                     i = 0,
14691                     length = items.length,
14692                     candidate;
14693                 for (; i < length; i++) {
14694                     candidate = items[i];
14695                     if (candidate.isXType(xtype, shallow)) {
14696                         result.push(candidate);
14697                     }
14698                 }
14699                 return result;
14700             }
14701         },
14702
14703         // Filters the passed candidate array and returns only items which have the passed className
14704         filterByClassName = function(items, className) {
14705             var EA = Ext.Array,
14706                 result = [],
14707                 i = 0,
14708                 length = items.length,
14709                 candidate;
14710             for (; i < length; i++) {
14711                 candidate = items[i];
14712                 if (candidate.el ? candidate.el.hasCls(className) : EA.contains(candidate.initCls(), className)) {
14713                     result.push(candidate);
14714                 }
14715             }
14716             return result;
14717         },
14718
14719         // Filters the passed candidate array and returns only items which have the specified property match
14720         filterByAttribute = function(items, property, operator, value) {
14721             var result = [],
14722                 i = 0,
14723                 length = items.length,
14724                 candidate;
14725             for (; i < length; i++) {
14726                 candidate = items[i];
14727                 if (!value ? !!candidate[property] : (String(candidate[property]) === value)) {
14728                     result.push(candidate);
14729                 }
14730             }
14731             return result;
14732         },
14733
14734         // Filters the passed candidate array and returns only items which have the specified itemId or id
14735         filterById = function(items, id) {
14736             var result = [],
14737                 i = 0,
14738                 length = items.length,
14739                 candidate;
14740             for (; i < length; i++) {
14741                 candidate = items[i];
14742                 if (candidate.getItemId() === id) {
14743                     result.push(candidate);
14744                 }
14745             }
14746             return result;
14747         },
14748
14749         // Filters the passed candidate array and returns only items which the named pseudo class matcher filters in
14750         filterByPseudo = function(items, name, value) {
14751             return cq.pseudos[name](items, value);
14752         },
14753
14754         // Determines leading mode
14755         // > for direct child, and ^ to switch to ownerCt axis
14756         modeRe = /^(\s?([>\^])\s?|\s|$)/,
14757
14758         // Matches a token with possibly (true|false) appended for the "shallow" parameter
14759         tokenRe = /^(#)?([\w\-]+|\*)(?:\((true|false)\))?/,
14760
14761         matchers = [{
14762             // Checks for .xtype with possibly (true|false) appended for the "shallow" parameter
14763             re: /^\.([\w\-]+)(?:\((true|false)\))?/,
14764             method: filterByXType
14765         },{
14766             // checks for [attribute=value]
14767             re: /^(?:[\[](?:@)?([\w\-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]])/,
14768             method: filterByAttribute
14769         }, {
14770             // checks for #cmpItemId
14771             re: /^#([\w\-]+)/,
14772             method: filterById
14773         }, {
14774             // checks for :<pseudo_class>(<selector>)
14775             re: /^\:([\w\-]+)(?:\(((?:\{[^\}]+\})|(?:(?!\{)[^\s>\/]*?(?!\})))\))?/,
14776             method: filterByPseudo
14777         }, {
14778             // checks for {<member_expression>}
14779             re: /^(?:\{([^\}]+)\})/,
14780             method: filterFnPattern
14781         }];
14782
14783     /**
14784      * @class Ext.ComponentQuery.Query
14785      * @extends Object
14786      * @private
14787      */
14788     cq.Query = Ext.extend(Object, {
14789         constructor: function(cfg) {
14790             cfg = cfg || {};
14791             Ext.apply(this, cfg);
14792         },
14793
14794         /**
14795          * @private
14796          * Executes this Query upon the selected root.
14797          * The root provides the initial source of candidate Component matches which are progressively
14798          * filtered by iterating through this Query's operations cache.
14799          * If no root is provided, all registered Components are searched via the ComponentManager.
14800          * root may be a Container who's descendant Components are filtered
14801          * root may be a Component with an implementation of getRefItems which provides some nested Components such as the
14802          * docked items within a Panel.
14803          * root may be an array of candidate Components to filter using this Query.
14804          */
14805         execute : function(root) {
14806             var operations = this.operations,
14807                 i = 0,
14808                 length = operations.length,
14809                 operation,
14810                 workingItems;
14811
14812             // no root, use all Components in the document
14813             if (!root) {
14814                 workingItems = Ext.ComponentManager.all.getArray();
14815             }
14816             // Root is a candidate Array
14817             else if (Ext.isArray(root)) {
14818                 workingItems = root;
14819             }
14820
14821             // We are going to loop over our operations and take care of them
14822             // one by one.
14823             for (; i < length; i++) {
14824                 operation = operations[i];
14825
14826                 // The mode operation requires some custom handling.
14827                 // All other operations essentially filter down our current
14828                 // working items, while mode replaces our current working
14829                 // items by getting children from each one of our current
14830                 // working items. The type of mode determines the type of
14831                 // children we get. (e.g. > only gets direct children)
14832                 if (operation.mode === '^') {
14833                     workingItems = getAncestors(workingItems || [root]);
14834                 }
14835                 else if (operation.mode) {
14836                     workingItems = getItems(workingItems || [root], operation.mode);
14837                 }
14838                 else {
14839                     workingItems = filterItems(workingItems || getItems([root]), operation);
14840                 }
14841
14842                 // If this is the last operation, it means our current working
14843                 // items are the final matched items. Thus return them!
14844                 if (i === length -1) {
14845                     return workingItems;
14846                 }
14847             }
14848             return [];
14849         },
14850
14851         is: function(component) {
14852             var operations = this.operations,
14853                 components = Ext.isArray(component) ? component : [component],
14854                 originalLength = components.length,
14855                 lastOperation = operations[operations.length-1],
14856                 ln, i;
14857
14858             components = filterItems(components, lastOperation);
14859             if (components.length === originalLength) {
14860                 if (operations.length > 1) {
14861                     for (i = 0, ln = components.length; i < ln; i++) {
14862                         if (Ext.Array.indexOf(this.execute(), components[i]) === -1) {
14863                             return false;
14864                         }
14865                     }
14866                 }
14867                 return true;
14868             }
14869             return false;
14870         }
14871     });
14872
14873     Ext.apply(this, {
14874
14875         // private cache of selectors and matching ComponentQuery.Query objects
14876         cache: {},
14877
14878         // private cache of pseudo class filter functions
14879         pseudos: {
14880             not: function(components, selector){
14881                 var CQ = Ext.ComponentQuery,
14882                     i = 0,
14883                     length = components.length,
14884                     results = [],
14885                     index = -1,
14886                     component;
14887                 
14888                 for(; i < length; ++i) {
14889                     component = components[i];
14890                     if (!CQ.is(component, selector)) {
14891                         results[++index] = component;
14892                     }
14893                 }
14894                 return results;
14895             }
14896         },
14897
14898         /**
14899          * <p>Returns an array of matched Components from within the passed root object.</p>
14900          * <p>This method filters returned Components in a similar way to how CSS selector based DOM
14901          * queries work using a textual selector string.</p>
14902          * <p>See class summary for details.</p>
14903          * @param selector The selector string to filter returned Components
14904          * @param root <p>The Container within which to perform the query. If omitted, all Components
14905          * within the document are included in the search.</p>
14906          * <p>This parameter may also be an array of Components to filter according to the selector.</p>
14907          * @returns {Array} The matched Components.
14908          * @member Ext.ComponentQuery
14909          */
14910         query: function(selector, root) {
14911             var selectors = selector.split(','),
14912                 length = selectors.length,
14913                 i = 0,
14914                 results = [],
14915                 noDupResults = [], 
14916                 dupMatcher = {}, 
14917                 query, resultsLn, cmp;
14918
14919             for (; i < length; i++) {
14920                 selector = Ext.String.trim(selectors[i]);
14921                 query = this.cache[selector];
14922                 if (!query) {
14923                     this.cache[selector] = query = this.parse(selector);
14924                 }
14925                 results = results.concat(query.execute(root));
14926             }
14927
14928             // multiple selectors, potential to find duplicates
14929             // lets filter them out.
14930             if (length > 1) {
14931                 resultsLn = results.length;
14932                 for (i = 0; i < resultsLn; i++) {
14933                     cmp = results[i];
14934                     if (!dupMatcher[cmp.id]) {
14935                         noDupResults.push(cmp);
14936                         dupMatcher[cmp.id] = true;
14937                     }
14938                 }
14939                 results = noDupResults;
14940             }
14941             return results;
14942         },
14943
14944         /**
14945          * Tests whether the passed Component matches the selector string.
14946          * @param component The Component to test
14947          * @param selector The selector string to test against.
14948          * @return {Boolean} True if the Component matches the selector.
14949          * @member Ext.ComponentQuery
14950          */
14951         is: function(component, selector) {
14952             if (!selector) {
14953                 return true;
14954             }
14955             var query = this.cache[selector];
14956             if (!query) {
14957                 this.cache[selector] = query = this.parse(selector);
14958             }
14959             return query.is(component);
14960         },
14961
14962         parse: function(selector) {
14963             var operations = [],
14964                 length = matchers.length,
14965                 lastSelector,
14966                 tokenMatch,
14967                 matchedChar,
14968                 modeMatch,
14969                 selectorMatch,
14970                 i, matcher, method;
14971
14972             // We are going to parse the beginning of the selector over and
14973             // over again, slicing off the selector any portions we converted into an
14974             // operation, until it is an empty string.
14975             while (selector && lastSelector !== selector) {
14976                 lastSelector = selector;
14977
14978                 // First we check if we are dealing with a token like #, * or an xtype
14979                 tokenMatch = selector.match(tokenRe);
14980
14981                 if (tokenMatch) {
14982                     matchedChar = tokenMatch[1];
14983
14984                     // If the token is prefixed with a # we push a filterById operation to our stack
14985                     if (matchedChar === '#') {
14986                         operations.push({
14987                             method: filterById,
14988                             args: [Ext.String.trim(tokenMatch[2])]
14989                         });
14990                     }
14991                     // If the token is prefixed with a . we push a filterByClassName operation to our stack
14992                     // FIXME: Not enabled yet. just needs \. adding to the tokenRe prefix
14993                     else if (matchedChar === '.') {
14994                         operations.push({
14995                             method: filterByClassName,
14996                             args: [Ext.String.trim(tokenMatch[2])]
14997                         });
14998                     }
14999                     // If the token is a * or an xtype string, we push a filterByXType
15000                     // operation to the stack.
15001                     else {
15002                         operations.push({
15003                             method: filterByXType,
15004                             args: [Ext.String.trim(tokenMatch[2]), Boolean(tokenMatch[3])]
15005                         });
15006                     }
15007
15008                     // Now we slice of the part we just converted into an operation
15009                     selector = selector.replace(tokenMatch[0], '');
15010                 }
15011
15012                 // If the next part of the query is not a space or > or ^, it means we
15013                 // are going to check for more things that our current selection
15014                 // has to comply to.
15015                 while (!(modeMatch = selector.match(modeRe))) {
15016                     // Lets loop over each type of matcher and execute it
15017                     // on our current selector.
15018                     for (i = 0; selector && i < length; i++) {
15019                         matcher = matchers[i];
15020                         selectorMatch = selector.match(matcher.re);
15021                         method = matcher.method;
15022
15023                         // If we have a match, add an operation with the method
15024                         // associated with this matcher, and pass the regular
15025                         // expression matches are arguments to the operation.
15026                         if (selectorMatch) {
15027                             operations.push({
15028                                 method: Ext.isString(matcher.method)
15029                                     // Turn a string method into a function by formatting the string with our selector matche expression
15030                                     // A new method is created for different match expressions, eg {id=='textfield-1024'}
15031                                     // Every expression may be different in different selectors.
15032                                     ? Ext.functionFactory('items', Ext.String.format.apply(Ext.String, [method].concat(selectorMatch.slice(1))))
15033                                     : matcher.method,
15034                                 args: selectorMatch.slice(1)
15035                             });
15036                             selector = selector.replace(selectorMatch[0], '');
15037                             break; // Break on match
15038                         }
15039                         // Exhausted all matches: It's an error
15040                         if (i === (length - 1)) {
15041                             Ext.Error.raise('Invalid ComponentQuery selector: "' + arguments[0] + '"');
15042                         }
15043                     }
15044                 }
15045
15046                 // Now we are going to check for a mode change. This means a space
15047                 // or a > to determine if we are going to select all the children
15048                 // of the currently matched items, or a ^ if we are going to use the
15049                 // ownerCt axis as the candidate source.
15050                 if (modeMatch[1]) { // Assignment, and test for truthiness!
15051                     operations.push({
15052                         mode: modeMatch[2]||modeMatch[1]
15053                     });
15054                     selector = selector.replace(modeMatch[0], '');
15055                 }
15056             }
15057
15058             //  Now that we have all our operations in an array, we are going
15059             // to create a new Query using these operations.
15060             return new cq.Query({
15061                 operations: operations
15062             });
15063         }
15064     });
15065 });
15066 /**
15067  * @class Ext.util.Filter
15068  * @extends Object
15069  * <p>Represents a filter that can be applied to a {@link Ext.util.MixedCollection MixedCollection}. Can either simply
15070  * filter on a property/value pair or pass in a filter function with custom logic. Filters are always used in the context
15071  * of MixedCollections, though {@link Ext.data.Store Store}s frequently create them when filtering and searching on their
15072  * records. Example usage:</p>
15073 <pre><code>
15074 //set up a fictional MixedCollection containing a few people to filter on
15075 var allNames = new Ext.util.MixedCollection();
15076 allNames.addAll([
15077     {id: 1, name: 'Ed',    age: 25},
15078     {id: 2, name: 'Jamie', age: 37},
15079     {id: 3, name: 'Abe',   age: 32},
15080     {id: 4, name: 'Aaron', age: 26},
15081     {id: 5, name: 'David', age: 32}
15082 ]);
15083
15084 var ageFilter = new Ext.util.Filter({
15085     property: 'age',
15086     value   : 32
15087 });
15088
15089 var longNameFilter = new Ext.util.Filter({
15090     filterFn: function(item) {
15091         return item.name.length > 4;
15092     }
15093 });
15094
15095 //a new MixedCollection with the 3 names longer than 4 characters
15096 var longNames = allNames.filter(longNameFilter);
15097
15098 //a new MixedCollection with the 2 people of age 24:
15099 var youngFolk = allNames.filter(ageFilter);
15100 </code></pre>
15101  * @constructor
15102  * @param {Object} config Config object
15103  */
15104 Ext.define('Ext.util.Filter', {
15105
15106     /* Begin Definitions */
15107
15108     /* End Definitions */
15109     /**
15110      * @cfg {String} property The property to filter on. Required unless a {@link #filter} is passed
15111      */
15112     
15113     /**
15114      * @cfg {Function} filterFn A custom filter function which is passed each item in the {@link Ext.util.MixedCollection} 
15115      * in turn. Should return true to accept each item or false to reject it
15116      */
15117     
15118     /**
15119      * @cfg {Boolean} anyMatch True to allow any match - no regex start/end line anchors will be added. Defaults to false
15120      */
15121     anyMatch: false,
15122     
15123     /**
15124      * @cfg {Boolean} exactMatch True to force exact match (^ and $ characters added to the regex). Defaults to false.
15125      * Ignored if anyMatch is true.
15126      */
15127     exactMatch: false,
15128     
15129     /**
15130      * @cfg {Boolean} caseSensitive True to make the regex case sensitive (adds 'i' switch to regex). Defaults to false.
15131      */
15132     caseSensitive: false,
15133     
15134     /**
15135      * @cfg {String} root Optional root property. This is mostly useful when filtering a Store, in which case we set the
15136      * root to 'data' to make the filter pull the {@link #property} out of the data object of each item
15137      */
15138     
15139     constructor: function(config) {
15140         Ext.apply(this, config);
15141         
15142         //we're aliasing filter to filterFn mostly for API cleanliness reasons, despite the fact it dirties the code here.
15143         //Ext.util.Sorter takes a sorterFn property but allows .sort to be called - we do the same here
15144         this.filter = this.filter || this.filterFn;
15145         
15146         if (this.filter == undefined) {
15147             if (this.property == undefined || this.value == undefined) {
15148                 // Commented this out temporarily because it stops us using string ids in models. TODO: Remove this once
15149                 // Model has been updated to allow string ids
15150                 
15151                 // Ext.Error.raise("A Filter requires either a property or a filterFn to be set");
15152             } else {
15153                 this.filter = this.createFilterFn();
15154             }
15155             
15156             this.filterFn = this.filter;
15157         }
15158     },
15159     
15160     /**
15161      * @private
15162      * Creates a filter function for the configured property/value/anyMatch/caseSensitive options for this Filter
15163      */
15164     createFilterFn: function() {
15165         var me       = this,
15166             matcher  = me.createValueMatcher(),
15167             property = me.property;
15168         
15169         return function(item) {
15170             return matcher.test(me.getRoot.call(me, item)[property]);
15171         };
15172     },
15173     
15174     /**
15175      * @private
15176      * Returns the root property of the given item, based on the configured {@link #root} property
15177      * @param {Object} item The item
15178      * @return {Object} The root property of the object
15179      */
15180     getRoot: function(item) {
15181         return this.root == undefined ? item : item[this.root];
15182     },
15183     
15184     /**
15185      * @private
15186      * Returns a regular expression based on the given value and matching options
15187      */
15188     createValueMatcher : function() {
15189         var me            = this,
15190             value         = me.value,
15191             anyMatch      = me.anyMatch,
15192             exactMatch    = me.exactMatch,
15193             caseSensitive = me.caseSensitive,
15194             escapeRe      = Ext.String.escapeRegex;
15195         
15196         if (!value.exec) { // not a regex
15197             value = String(value);
15198
15199             if (anyMatch === true) {
15200                 value = escapeRe(value);
15201             } else {
15202                 value = '^' + escapeRe(value);
15203                 if (exactMatch === true) {
15204                     value += '$';
15205                 }
15206             }
15207             value = new RegExp(value, caseSensitive ? '' : 'i');
15208          }
15209          
15210          return value;
15211     }
15212 });
15213 /**
15214  * @class Ext.util.Sorter
15215  * @extends Object
15216  * Represents a single sorter that can be applied to a Store
15217  */
15218 Ext.define('Ext.util.Sorter', {
15219
15220     /**
15221      * @cfg {String} property The property to sort by. Required unless {@link #sorter} is provided
15222      */
15223     
15224     /**
15225      * @cfg {Function} sorterFn A specific sorter function to execute. Can be passed instead of {@link #property}
15226      */
15227     
15228     /**
15229      * @cfg {String} root Optional root property. This is mostly useful when sorting a Store, in which case we set the
15230      * root to 'data' to make the filter pull the {@link #property} out of the data object of each item
15231      */
15232     
15233     /**
15234      * @cfg {Function} transform A function that will be run on each value before
15235      * it is compared in the sorter. The function will receive a single argument,
15236      * the value.
15237      */
15238     
15239     /**
15240      * @cfg {String} direction The direction to sort by. Defaults to ASC
15241      */
15242     direction: "ASC",
15243     
15244     constructor: function(config) {
15245         var me = this;
15246         
15247         Ext.apply(me, config);
15248         
15249         if (me.property == undefined && me.sorterFn == undefined) {
15250             Ext.Error.raise("A Sorter requires either a property or a sorter function");
15251         }
15252         
15253         me.updateSortFunction();
15254     },
15255     
15256     /**
15257      * @private
15258      * Creates and returns a function which sorts an array by the given property and direction
15259      * @return {Function} A function which sorts by the property/direction combination provided
15260      */
15261     createSortFunction: function(sorterFn) {
15262         var me        = this,
15263             property  = me.property,
15264             direction = me.direction || "ASC",
15265             modifier  = direction.toUpperCase() == "DESC" ? -1 : 1;
15266         
15267         //create a comparison function. Takes 2 objects, returns 1 if object 1 is greater,
15268         //-1 if object 2 is greater or 0 if they are equal
15269         return function(o1, o2) {
15270             return modifier * sorterFn.call(me, o1, o2);
15271         };
15272     },
15273     
15274     /**
15275      * @private
15276      * Basic default sorter function that just compares the defined property of each object
15277      */
15278     defaultSorterFn: function(o1, o2) {
15279         var me = this,
15280             transform = me.transform,
15281             v1 = me.getRoot(o1)[me.property],
15282             v2 = me.getRoot(o2)[me.property];
15283             
15284         if (transform) {
15285             v1 = transform(v1);
15286             v2 = transform(v2);
15287         }
15288
15289         return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
15290     },
15291     
15292     /**
15293      * @private
15294      * Returns the root property of the given item, based on the configured {@link #root} property
15295      * @param {Object} item The item
15296      * @return {Object} The root property of the object
15297      */
15298     getRoot: function(item) {
15299         return this.root == undefined ? item : item[this.root];
15300     },
15301     
15302     // @TODO: Add docs for these three methods
15303     setDirection: function(direction) {
15304         var me = this;
15305         me.direction = direction;
15306         me.updateSortFunction();
15307     },
15308     
15309     toggle: function() {
15310         var me = this;
15311         me.direction = Ext.String.toggle(me.direction, "ASC", "DESC");
15312         me.updateSortFunction();
15313     },
15314     
15315     updateSortFunction: function() {
15316         var me = this;
15317         me.sort = me.createSortFunction(me.sorterFn || me.defaultSorterFn);
15318     }
15319 });
15320 /**
15321  * @class Ext.ElementLoader
15322  * A class used to load remote content to an Element. Sample usage:
15323  * <pre><code>
15324 Ext.get('el').load({
15325     url: 'myPage.php',
15326     scripts: true,
15327     params: {
15328         id: 1
15329     }
15330 });
15331  * </code></pre>
15332  * <p>
15333  * In general this class will not be instanced directly, rather the {@link Ext.core.Element#load} method
15334  * will be used.
15335  * </p>
15336  */
15337 Ext.define('Ext.ElementLoader', {
15338
15339     /* Begin Definitions */
15340
15341     mixins: {
15342         observable: 'Ext.util.Observable'
15343     },
15344
15345     uses: [
15346         'Ext.data.Connection',
15347         'Ext.Ajax'
15348     ],
15349     
15350     statics: {
15351         Renderer: {
15352             Html: function(loader, response, active){
15353                 loader.getTarget().update(response.responseText, active.scripts === true);
15354                 return true;
15355             }
15356         }     
15357     },
15358
15359     /* End Definitions */
15360
15361     /**
15362      * @cfg {String} url The url to retrieve the content from. Defaults to <tt>null</tt>.
15363      */
15364     url: null,
15365
15366     /**
15367      * @cfg {Object} params Any params to be attached to the Ajax request. These parameters will
15368      * be overridden by any params in the load options. Defaults to <tt>null</tt>.
15369      */
15370     params: null,
15371
15372     /**
15373      * @cfg {Object} baseParams Params that will be attached to every request. These parameters
15374      * will not be overridden by any params in the load options. Defaults to <tt>null</tt>.
15375      */
15376     baseParams: null,
15377
15378     /**
15379      * @cfg {Boolean/Object} autoLoad True to have the loader make a request as soon as it is created. Defaults to <tt>false</tt>.
15380      * This argument can also be a set of options that will be passed to {@link #load} is called.
15381      */
15382     autoLoad: false,
15383
15384     /**
15385      * @cfg {Mixed} target The target element for the loader. It can be the DOM element, the id or an Ext.Element.
15386      */
15387     target: null,
15388
15389     /**
15390      * @cfg {Mixed} loadMask True or a string to show when the element is loading.
15391      */
15392     loadMask: false,
15393
15394     /**
15395      * @cfg {Object} ajaxOptions Any additional options to be passed to the request, for example timeout or headers. Defaults to <tt>null</tt>.
15396      */
15397     ajaxOptions: null,
15398     
15399     /**
15400      * @cfg {Boolean} scripts True to parse any inline script tags in the response.
15401      */
15402     scripts: false,
15403
15404     /**
15405      * @cfg {Function} success A function to be called when a load request is successful.
15406      */
15407
15408     /**
15409      * @cfg {Function} failure A function to be called when a load request fails.
15410      */
15411
15412     /**
15413      * @cfg {Object} scope The scope to execute the {@link #success} and {@link #failure} functions in.
15414      */
15415     
15416     /**
15417      * @cfg {Function} renderer A custom function to render the content to the element. The passed parameters
15418      * are
15419      * <ul>
15420      * <li>The loader</li>
15421      * <li>The response</li>
15422      * <li>The active request</li>
15423      * </ul>
15424      */
15425
15426     isLoader: true,
15427
15428     constructor: function(config) {
15429         var me = this,
15430             autoLoad;
15431         
15432         config = config || {};
15433         Ext.apply(me, config);
15434         me.setTarget(me.target);
15435         me.addEvents(
15436             /**
15437              * @event beforeload
15438              * Fires before a load request is made to the server.
15439              * Returning false from an event listener can prevent the load
15440              * from occurring.
15441              * @param {Ext.ElementLoader} this
15442              * @param {Object} options The options passed to the request
15443              */
15444             'beforeload',
15445
15446             /**
15447              * @event exception
15448              * Fires after an unsuccessful load.
15449              * @param {Ext.ElementLoader} this
15450              * @param {Object} response The response from the server
15451              * @param {Object} options The options passed to the request
15452              */
15453             'exception',
15454
15455             /**
15456              * @event exception
15457              * Fires after a successful load.
15458              * @param {Ext.ElementLoader} this
15459              * @param {Object} response The response from the server
15460              * @param {Object} options The options passed to the request
15461              */
15462             'load'
15463         );
15464
15465         // don't pass config because we have already applied it.
15466         me.mixins.observable.constructor.call(me);
15467
15468         if (me.autoLoad) {
15469             autoLoad = me.autoLoad;
15470             if (autoLoad === true) {
15471                 autoLoad = {};
15472             }
15473             me.load(autoLoad);
15474         }
15475     },
15476
15477     /**
15478      * Set an {Ext.Element} as the target of this loader. Note that if the target is changed,
15479      * any active requests will be aborted.
15480      * @param {Mixed} target The element
15481      */
15482     setTarget: function(target){
15483         var me = this;
15484         target = Ext.get(target);
15485         if (me.target && me.target != target) {
15486             me.abort();
15487         }
15488         me.target = target;
15489     },
15490
15491     /**
15492      * Get the target of this loader.
15493      * @return {Ext.Component} target The target, null if none exists.
15494      */
15495     getTarget: function(){
15496         return this.target || null;
15497     },
15498
15499     /**
15500      * Aborts the active load request
15501      */
15502     abort: function(){
15503         var active = this.active;
15504         if (active !== undefined) {
15505             Ext.Ajax.abort(active.request);
15506             if (active.mask) {
15507                 this.removeMask();
15508             }
15509             delete this.active;
15510         }
15511     },
15512     
15513     /**
15514      * Remove the mask on the target
15515      * @private
15516      */
15517     removeMask: function(){
15518         this.target.unmask();
15519     },
15520     
15521     /**
15522      * Add the mask on the target
15523      * @private
15524      * @param {Mixed} mask The mask configuration
15525      */
15526     addMask: function(mask){
15527         this.target.mask(mask === true ? null : mask);
15528     },
15529
15530     /**
15531      * Load new data from the server.
15532      * @param {Object} options The options for the request. They can be any configuration option that can be specified for
15533      * the class, with the exception of the target option. Note that any options passed to the method will override any
15534      * class defaults.
15535      */
15536     load: function(options) {
15537         if (!this.target) {
15538             Ext.Error.raise('A valid target is required when loading content');
15539         }
15540
15541         options = Ext.apply({}, options);
15542
15543         var me = this,
15544             target = me.target,
15545             mask = Ext.isDefined(options.loadMask) ? options.loadMask : me.loadMask,
15546             params = Ext.apply({}, options.params),
15547             ajaxOptions = Ext.apply({}, options.ajaxOptions),
15548             callback = options.callback || me.callback,
15549             scope = options.scope || me.scope || me,
15550             request;
15551
15552         Ext.applyIf(ajaxOptions, me.ajaxOptions);
15553         Ext.applyIf(options, ajaxOptions);
15554
15555         Ext.applyIf(params, me.params);
15556         Ext.apply(params, me.baseParams);
15557
15558         Ext.applyIf(options, {
15559             url: me.url
15560         });
15561
15562         if (!options.url) {
15563             Ext.Error.raise('You must specify the URL from which content should be loaded');
15564         }
15565
15566         Ext.apply(options, {
15567             scope: me,
15568             params: params,
15569             callback: me.onComplete
15570         });
15571
15572         if (me.fireEvent('beforeload', me, options) === false) {
15573             return;
15574         }
15575
15576         if (mask) {
15577             me.addMask(mask);
15578         }
15579
15580         request = Ext.Ajax.request(options);
15581         me.active = {
15582             request: request,
15583             options: options,
15584             mask: mask,
15585             scope: scope,
15586             callback: callback,
15587             success: options.success || me.success,
15588             failure: options.failure || me.failure,
15589             renderer: options.renderer || me.renderer,
15590             scripts: Ext.isDefined(options.scripts) ? options.scripts : me.scripts
15591         };
15592         me.setOptions(me.active, options);
15593     },
15594     
15595     /**
15596      * Set any additional options on the active request
15597      * @private
15598      * @param {Object} active The active request
15599      * @param {Object} options The initial options
15600      */
15601     setOptions: Ext.emptyFn,
15602
15603     /**
15604      * Parse the response after the request completes
15605      * @private
15606      * @param {Object} options Ajax options
15607      * @param {Boolean} success Success status of the request
15608      * @param {Object} response The response object
15609      */
15610     onComplete: function(options, success, response) {
15611         var me = this,
15612             active = me.active,
15613             scope = active.scope,
15614             renderer = me.getRenderer(active.renderer);
15615
15616
15617         if (success) {
15618             success = renderer.call(me, me, response, active);
15619         }
15620
15621         if (success) {
15622             Ext.callback(active.success, scope, [me, response, options]);
15623             me.fireEvent('load', me, response, options);
15624         } else {
15625             Ext.callback(active.failure, scope, [me, response, options]);
15626             me.fireEvent('exception', me, response, options);
15627         }
15628         Ext.callback(active.callback, scope, [me, success, response, options]);
15629
15630         if (active.mask) {
15631             me.removeMask();
15632         }
15633
15634         delete me.active;
15635     },
15636
15637     /**
15638      * Gets the renderer to use
15639      * @private
15640      * @param {String/Function} renderer The renderer to use
15641      * @return {Function} A rendering function to use.
15642      */
15643     getRenderer: function(renderer){
15644         if (Ext.isFunction(renderer)) {
15645             return renderer;
15646         }
15647         return this.statics().Renderer.Html;
15648     },
15649     
15650     /**
15651      * Automatically refreshes the content over a specified period.
15652      * @param {Number} interval The interval to refresh in ms.
15653      * @param {Object} options (optional) The options to pass to the load method. See {@link #load}
15654      */
15655     startAutoRefresh: function(interval, options){
15656         var me = this;
15657         me.stopAutoRefresh();
15658         me.autoRefresh = setInterval(function(){
15659             me.load(options);
15660         }, interval);
15661     },
15662     
15663     /**
15664      * Clears any auto refresh. See {@link #startAutoRefresh}.
15665      */
15666     stopAutoRefresh: function(){
15667         clearInterval(this.autoRefresh);
15668         delete this.autoRefresh;
15669     },
15670     
15671     /**
15672      * Checks whether the loader is automatically refreshing. See {@link #startAutoRefresh}.
15673      * @return {Boolean} True if the loader is automatically refreshing
15674      */
15675     isAutoRefreshing: function(){
15676         return Ext.isDefined(this.autoRefresh);
15677     },
15678
15679     /**
15680      * Destroys the loader. Any active requests will be aborted.
15681      */
15682     destroy: function(){
15683         var me = this;
15684         me.stopAutoRefresh();
15685         delete me.target;
15686         me.abort();
15687         me.clearListeners();
15688     }
15689 });
15690
15691 /**
15692  * @class Ext.layout.Layout
15693  * @extends Object
15694  * @private
15695  * Base Layout class - extended by ComponentLayout and ContainerLayout
15696  */
15697
15698 Ext.define('Ext.layout.Layout', {
15699
15700     /* Begin Definitions */
15701
15702     /* End Definitions */
15703
15704     isLayout: true,
15705     initialized: false,
15706
15707     statics: {
15708         create: function(layout, defaultType) {
15709             var type;
15710             if (layout instanceof Ext.layout.Layout) {
15711                 return Ext.createByAlias('layout.' + layout);
15712             } else {
15713                 if (Ext.isObject(layout)) {
15714                     type = layout.type;
15715                 }
15716                 else {
15717                     type = layout || defaultType;
15718                     layout = {};
15719                 }
15720                 return Ext.createByAlias('layout.' + type, layout || {});
15721             }
15722         }
15723     },
15724
15725     constructor : function(config) {
15726         this.id = Ext.id(null, this.type + '-');
15727         Ext.apply(this, config);
15728     },
15729
15730     /**
15731      * @private
15732      */
15733     layout : function() {
15734         var me = this;
15735         me.layoutBusy = true;
15736         me.initLayout();
15737
15738         if (me.beforeLayout.apply(me, arguments) !== false) {
15739             me.layoutCancelled = false;
15740             me.onLayout.apply(me, arguments);
15741             me.childrenChanged = false;
15742             me.owner.needsLayout = false;
15743             me.layoutBusy = false;
15744             me.afterLayout.apply(me, arguments);
15745         }
15746         else {
15747             me.layoutCancelled = true;
15748         }
15749         me.layoutBusy = false;
15750         me.doOwnerCtLayouts();
15751     },
15752
15753     beforeLayout : function() {
15754         this.renderItems(this.getLayoutItems(), this.getRenderTarget());
15755         return true;
15756     },
15757
15758     /**
15759      * @private
15760      * Iterates over all passed items, ensuring they are rendered.  If the items are already rendered,
15761      * also determines if the items are in the proper place dom.
15762      */
15763     renderItems : function(items, target) {
15764         var ln = items.length,
15765             i = 0,
15766             item;
15767
15768         for (; i < ln; i++) {
15769             item = items[i];
15770             if (item && !item.rendered) {
15771                 this.renderItem(item, target, i);
15772             }
15773             else if (!this.isValidParent(item, target, i)) {
15774                 this.moveItem(item, target, i);
15775             }
15776         }
15777     },
15778
15779     // @private - Validates item is in the proper place in the dom.
15780     isValidParent : function(item, target, position) {
15781         var dom = item.el ? item.el.dom : Ext.getDom(item);
15782         if (dom && target && target.dom) {
15783             if (Ext.isNumber(position) && dom !== target.dom.childNodes[position]) {
15784                 return false;
15785             }
15786             return (dom.parentNode == (target.dom || target));
15787         }
15788         return false;
15789     },
15790
15791     /**
15792      * @private
15793      * Renders the given Component into the target Element.
15794      * @param {Ext.Component} item The Component to render
15795      * @param {Ext.core.Element} target The target Element
15796      * @param {Number} position The position within the target to render the item to
15797      */
15798     renderItem : function(item, target, position) {
15799         if (!item.rendered) {
15800             item.render(target, position);
15801             this.configureItem(item);
15802             this.childrenChanged = true;
15803         }
15804     },
15805
15806     /**
15807      * @private
15808      * Moved Component to the provided target instead.
15809      */
15810     moveItem : function(item, target, position) {
15811         // Make sure target is a dom element
15812         target = target.dom || target;
15813         if (typeof position == 'number') {
15814             position = target.childNodes[position];
15815         }
15816         target.insertBefore(item.el.dom, position || null);
15817         item.container = Ext.get(target);
15818         this.configureItem(item);
15819         this.childrenChanged = true;
15820     },
15821
15822     /**
15823      * @private
15824      * Adds the layout's targetCls if necessary and sets
15825      * initialized flag when complete.
15826      */
15827     initLayout : function() {
15828         if (!this.initialized && !Ext.isEmpty(this.targetCls)) {
15829             this.getTarget().addCls(this.targetCls);
15830         }
15831         this.initialized = true;
15832     },
15833
15834     // @private Sets the layout owner
15835     setOwner : function(owner) {
15836         this.owner = owner;
15837     },
15838
15839     // @private - Returns empty array
15840     getLayoutItems : function() {
15841         return [];
15842     },
15843
15844     /**
15845      * @private
15846      * Applies itemCls
15847      */
15848     configureItem: function(item) {
15849         var me = this,
15850             el = item.el,
15851             owner = me.owner;
15852             
15853         if (me.itemCls) {
15854             el.addCls(me.itemCls);
15855         }
15856         if (owner.itemCls) {
15857             el.addCls(owner.itemCls);
15858         }
15859     },
15860     
15861     // Placeholder empty functions for subclasses to extend
15862     onLayout : Ext.emptyFn,
15863     afterLayout : Ext.emptyFn,
15864     onRemove : Ext.emptyFn,
15865     onDestroy : Ext.emptyFn,
15866     doOwnerCtLayouts : Ext.emptyFn,
15867
15868     /**
15869      * @private
15870      * Removes itemCls
15871      */
15872     afterRemove : function(item) {
15873         var me = this,
15874             el = item.el,
15875             owner = me.owner;
15876             
15877         if (item.rendered) {
15878             if (me.itemCls) {
15879                 el.removeCls(me.itemCls);
15880             }
15881             if (owner.itemCls) {
15882                 el.removeCls(owner.itemCls);
15883             }
15884         }
15885     },
15886
15887     /*
15888      * Destroys this layout. This is a template method that is empty by default, but should be implemented
15889      * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
15890      * @protected
15891      */
15892     destroy : function() {
15893         if (!Ext.isEmpty(this.targetCls)) {
15894             var target = this.getTarget();
15895             if (target) {
15896                 target.removeCls(this.targetCls);
15897             }
15898         }
15899         this.onDestroy();
15900     }
15901 });
15902 /**
15903  * @class Ext.layout.component.Component
15904  * @extends Ext.layout.Layout
15905  * @private
15906  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Component#componentLayout layout}</b></tt>
15907  * configuration property.  See <tt><b>{@link Ext.Component#componentLayout}</b></tt> for additional details.</p>
15908  */
15909
15910 Ext.define('Ext.layout.component.Component', {
15911
15912     /* Begin Definitions */
15913
15914     extend: 'Ext.layout.Layout',
15915
15916     /* End Definitions */
15917
15918     type: 'component',
15919
15920     monitorChildren: true,
15921
15922     initLayout : function() {
15923         var me = this,
15924             owner = me.owner,
15925             ownerEl = owner.el;
15926
15927         if (!me.initialized) {
15928             if (owner.frameSize) {
15929                 me.frameSize = owner.frameSize;
15930             }
15931             else {
15932                 owner.frameSize = me.frameSize = {
15933                     top: 0,
15934                     left: 0,
15935                     bottom: 0,
15936                     right: 0
15937                 }; 
15938             }
15939         }
15940         me.callParent(arguments);
15941     },
15942
15943     beforeLayout : function(width, height, isSetSize, layoutOwner) {
15944         this.callParent(arguments);
15945
15946         var me = this,
15947             owner = me.owner,
15948             ownerCt = owner.ownerCt,
15949             layout = owner.layout,
15950             isVisible = owner.isVisible(true),
15951             ownerElChild = owner.el.child,
15952             layoutCollection;
15953
15954         /*
15955          * Do not layout calculatedSized components for fixedLayouts unless the ownerCt == layoutOwner
15956          * fixedLayouts means layouts which are never auto/auto in the sizing that comes from their ownerCt.
15957          * Currently 3 layouts MAY be auto/auto (Auto, Border, and Box)
15958          * The reason for not allowing component layouts is to stop component layouts from things such as Updater and
15959          * form Validation.
15960          */
15961         if (!isSetSize && !(Ext.isNumber(width) && Ext.isNumber(height)) && ownerCt && ownerCt.layout && ownerCt.layout.fixedLayout && ownerCt != layoutOwner) {
15962             me.doContainerLayout();
15963             return false;
15964         }
15965
15966         // If an ownerCt is hidden, add my reference onto the layoutOnShow stack.  Set the needsLayout flag.
15967         // If the owner itself is a directly hidden floater, set the needsLayout object on that for when it is shown.
15968         if (!isVisible && (owner.hiddenAncestor || owner.floating)) {
15969             if (owner.hiddenAncestor) {
15970                 layoutCollection = owner.hiddenAncestor.layoutOnShow;
15971                 layoutCollection.remove(owner);
15972                 layoutCollection.add(owner);
15973             }
15974             owner.needsLayout = {
15975                 width: width,
15976                 height: height,
15977                 isSetSize: false
15978             };
15979         }
15980
15981         if (isVisible && this.needsLayout(width, height)) {
15982             me.rawWidth = width;
15983             me.rawHeight = height;
15984             return owner.beforeComponentLayout(width, height, isSetSize, layoutOwner);
15985         }
15986         else {
15987             return false;
15988         }
15989     },
15990
15991     /**
15992     * Check if the new size is different from the current size and only
15993     * trigger a layout if it is necessary.
15994     * @param {Mixed} width The new width to set.
15995     * @param {Mixed} height The new height to set.
15996     */
15997     needsLayout : function(width, height) {
15998         this.lastComponentSize = this.lastComponentSize || {
15999             width: -Infinity,
16000             height: -Infinity
16001         };
16002         return (this.childrenChanged || this.lastComponentSize.width !== width || this.lastComponentSize.height !== height);
16003     },
16004
16005     /**
16006     * Set the size of any element supporting undefined, null, and values.
16007     * @param {Mixed} width The new width to set.
16008     * @param {Mixed} height The new height to set.
16009     */
16010     setElementSize: function(el, width, height) {
16011         if (width !== undefined && height !== undefined) {
16012             el.setSize(width, height);
16013         }
16014         else if (height !== undefined) {
16015             el.setHeight(height);
16016         }
16017         else if (width !== undefined) {
16018             el.setWidth(width);
16019         }
16020     },
16021
16022     /**
16023      * Returns the owner component's resize element.
16024      * @return {Ext.core.Element}
16025      */
16026      getTarget : function() {
16027          return this.owner.el;
16028      },
16029
16030     /**
16031      * <p>Returns the element into which rendering must take place. Defaults to the owner Component's encapsulating element.</p>
16032      * May be overridden in Component layout managers which implement an inner element.
16033      * @return {Ext.core.Element}
16034      */
16035     getRenderTarget : function() {
16036         return this.owner.el;
16037     },
16038
16039     /**
16040     * Set the size of the target element.
16041     * @param {Mixed} width The new width to set.
16042     * @param {Mixed} height The new height to set.
16043     */
16044     setTargetSize : function(width, height) {
16045         var me = this;
16046         me.setElementSize(me.owner.el, width, height);
16047
16048         if (me.owner.frameBody) {
16049             var targetInfo = me.getTargetInfo(),
16050                 padding = targetInfo.padding,
16051                 border = targetInfo.border,
16052                 frameSize = me.frameSize;
16053
16054             me.setElementSize(me.owner.frameBody,
16055                 Ext.isNumber(width) ? (width - frameSize.left - frameSize.right - padding.left - padding.right - border.left - border.right) : width,
16056                 Ext.isNumber(height) ? (height - frameSize.top - frameSize.bottom - padding.top - padding.bottom - border.top - border.bottom) : height
16057             );
16058         }
16059
16060         me.autoSized = {
16061             width: !Ext.isNumber(width),
16062             height: !Ext.isNumber(height)
16063         };
16064
16065         me.lastComponentSize = {
16066             width: width,
16067             height: height
16068         };
16069     },
16070
16071     getTargetInfo : function() {
16072         if (!this.targetInfo) {
16073             var target = this.getTarget(),
16074                 body = this.owner.getTargetEl();
16075
16076             this.targetInfo = {
16077                 padding: {
16078                     top: target.getPadding('t'),
16079                     right: target.getPadding('r'),
16080                     bottom: target.getPadding('b'),
16081                     left: target.getPadding('l')
16082                 },
16083                 border: {
16084                     top: target.getBorderWidth('t'),
16085                     right: target.getBorderWidth('r'),
16086                     bottom: target.getBorderWidth('b'),
16087                     left: target.getBorderWidth('l')
16088                 },
16089                 bodyMargin: {
16090                     top: body.getMargin('t'),
16091                     right: body.getMargin('r'),
16092                     bottom: body.getMargin('b'),
16093                     left: body.getMargin('l')
16094                 } 
16095             };
16096         }
16097         return this.targetInfo;
16098     },
16099
16100     // Start laying out UP the ownerCt's layout when flagged to do so.
16101     doOwnerCtLayouts: function() {
16102         var owner = this.owner,
16103             ownerCt = owner.ownerCt,
16104             ownerCtComponentLayout, ownerCtContainerLayout;
16105
16106         if (!ownerCt) {
16107             return;
16108         }
16109
16110         ownerCtComponentLayout = ownerCt.componentLayout;
16111         ownerCtContainerLayout = ownerCt.layout;
16112
16113         if (!owner.floating && ownerCtComponentLayout && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
16114             if (!ownerCt.suspendLayout && ownerCtContainerLayout && !ownerCtContainerLayout.layoutBusy) {
16115                 // AutoContainer Layout and Dock with auto in some dimension
16116                 if (ownerCtContainerLayout.bindToOwnerCtComponent === true) {
16117                     ownerCt.doComponentLayout();
16118                 }
16119                 // Box Layouts
16120                 else if (ownerCtContainerLayout.bindToOwnerCtContainer === true) {
16121                     ownerCtContainerLayout.layout();
16122                 }
16123             }
16124         }
16125     },
16126
16127     doContainerLayout: function() {
16128         var me = this,
16129             owner = me.owner,
16130             ownerCt = owner.ownerCt,
16131             layout = owner.layout,
16132             ownerCtComponentLayout;
16133
16134         // Run the container layout if it exists (layout for child items)
16135         // **Unless automatic laying out is suspended, or the layout is currently running**
16136         if (!owner.suspendLayout && layout && layout.isLayout && !layout.layoutBusy) {
16137             layout.layout();
16138         }
16139
16140         // Tell the ownerCt that it's child has changed and can be re-layed by ignoring the lastComponentSize cache.
16141         if (ownerCt && ownerCt.componentLayout) {
16142             ownerCtComponentLayout = ownerCt.componentLayout;
16143             if (!owner.floating && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
16144                 ownerCtComponentLayout.childrenChanged = true;
16145             }
16146         }
16147     },
16148
16149     afterLayout : function(width, height, isSetSize, layoutOwner) {
16150         this.doContainerLayout();
16151         this.owner.afterComponentLayout(width, height, isSetSize, layoutOwner);
16152     }
16153 });
16154
16155 /**
16156  * @class Ext.state.Manager
16157  * This is the global state manager. By default all components that are "state aware" check this class
16158  * for state information if you don't pass them a custom state provider. In order for this class
16159  * to be useful, it must be initialized with a provider when your application initializes. Example usage:
16160  <pre><code>
16161 // in your initialization function
16162 init : function(){
16163    Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
16164    var win = new Window(...);
16165    win.restoreState();
16166 }
16167  </code></pre>
16168  * This class passes on calls from components to the underlying {@link Ext.state.Provider} so that
16169  * there is a common interface that can be used without needing to refer to a specific provider instance
16170  * in every component.
16171  * @singleton
16172  * @docauthor Evan Trimboli <evan@sencha.com>
16173  */
16174 Ext.define('Ext.state.Manager', {
16175     singleton: true,
16176     requires: ['Ext.state.Provider'],
16177     constructor: function() {
16178         this.provider = Ext.create('Ext.state.Provider');
16179     },
16180     
16181     
16182     /**
16183      * Configures the default state provider for your application
16184      * @param {Provider} stateProvider The state provider to set
16185      */
16186     setProvider : function(stateProvider){
16187         this.provider = stateProvider;
16188     },
16189
16190     /**
16191      * Returns the current value for a key
16192      * @param {String} name The key name
16193      * @param {Mixed} defaultValue The default value to return if the key lookup does not match
16194      * @return {Mixed} The state data
16195      */
16196     get : function(key, defaultValue){
16197         return this.provider.get(key, defaultValue);
16198     },
16199
16200     /**
16201      * Sets the value for a key
16202      * @param {String} name The key name
16203      * @param {Mixed} value The state data
16204      */
16205      set : function(key, value){
16206         this.provider.set(key, value);
16207     },
16208
16209     /**
16210      * Clears a value from the state
16211      * @param {String} name The key name
16212      */
16213     clear : function(key){
16214         this.provider.clear(key);
16215     },
16216
16217     /**
16218      * Gets the currently configured state provider
16219      * @return {Provider} The state provider
16220      */
16221     getProvider : function(){
16222         return this.provider;
16223     }
16224 });
16225 /**
16226  * @class Ext.state.Stateful
16227  * A mixin for being able to save the state of an object to an underlying 
16228  * {@link Ext.state.Provider}.
16229  */
16230 Ext.define('Ext.state.Stateful', {
16231     
16232     /* Begin Definitions */
16233    
16234    mixins: {
16235         observable: 'Ext.util.Observable'
16236     },
16237     
16238     requires: ['Ext.state.Manager'],
16239     
16240     /* End Definitions */
16241     
16242     /**
16243      * @cfg {Boolean} stateful
16244      * <p>A flag which causes the object to attempt to restore the state of
16245      * internal properties from a saved state on startup. The object must have
16246      * a <code>{@link #stateId}</code> for state to be managed. 
16247      * Auto-generated ids are not guaranteed to be stable across page loads and 
16248      * cannot be relied upon to save and restore the same state for a object.<p>
16249      * <p>For state saving to work, the state manager's provider must have been
16250      * set to an implementation of {@link Ext.state.Provider} which overrides the
16251      * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get}
16252      * methods to save and recall name/value pairs. A built-in implementation,
16253      * {@link Ext.state.CookieProvider} is available.</p>
16254      * <p>To set the state provider for the current page:</p>
16255      * <pre><code>
16256 Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
16257     expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
16258 }));
16259      * </code></pre>
16260      * <p>A stateful object attempts to save state when one of the events
16261      * listed in the <code>{@link #stateEvents}</code> configuration fires.</p>
16262      * <p>To save state, a stateful object first serializes its state by
16263      * calling <b><code>{@link #getState}</code></b>. By default, this function does
16264      * nothing. The developer must provide an implementation which returns an
16265      * object hash which represents the restorable state of the object.</p>
16266      * <p>The value yielded by getState is passed to {@link Ext.state.Manager#set}
16267      * which uses the configured {@link Ext.state.Provider} to save the object
16268      * keyed by the <code>{@link stateId}</code></p>.
16269      * <p>During construction, a stateful object attempts to <i>restore</i>
16270      * its state by calling {@link Ext.state.Manager#get} passing the
16271      * <code>{@link #stateId}</code></p>
16272      * <p>The resulting object is passed to <b><code>{@link #applyState}</code></b>.
16273      * The default implementation of <code>{@link #applyState}</code> simply copies
16274      * properties into the object, but a developer may override this to support
16275      * more behaviour.</p>
16276      * <p>You can perform extra processing on state save and restore by attaching
16277      * handlers to the {@link #beforestaterestore}, {@link #staterestore},
16278      * {@link #beforestatesave} and {@link #statesave} events.</p>
16279      */
16280     stateful: true,
16281     
16282     /**
16283      * @cfg {String} stateId
16284      * The unique id for this object to use for state management purposes.
16285      * <p>See {@link #stateful} for an explanation of saving and restoring state.</p>
16286      */
16287     
16288     /**
16289      * @cfg {Array} stateEvents
16290      * <p>An array of events that, when fired, should trigger this object to
16291      * save its state (defaults to none). <code>stateEvents</code> may be any type
16292      * of event supported by this object, including browser or custom events
16293      * (e.g., <tt>['click', 'customerchange']</tt>).</p>
16294      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
16295      * restoring object state.</p>
16296      */
16297     
16298     /**
16299      * @cfg {Number} saveBuffer A buffer to be applied if many state events are fired within
16300      * a short period. Defaults to 100.
16301      */
16302     saveDelay: 100,
16303     
16304     autoGenIdRe: /^((\w+-)|(ext-comp-))\d{4,}$/i,
16305     
16306     constructor: function(config) {
16307         var me = this;
16308         
16309         config = config || {};
16310         if (Ext.isDefined(config.stateful)) {
16311             me.stateful = config.stateful;
16312         }
16313         if (Ext.isDefined(config.saveDelay)) {
16314             me.saveDelay = config.saveDelay;
16315         }
16316         me.stateId = config.stateId;
16317         
16318         if (!me.stateEvents) {
16319             me.stateEvents = [];
16320         }
16321         if (config.stateEvents) {
16322             me.stateEvents.concat(config.stateEvents);
16323         }
16324         this.addEvents(
16325             /**
16326              * @event beforestaterestore
16327              * Fires before the state of the object is restored. Return false from an event handler to stop the restore.
16328              * @param {Ext.state.Stateful} this
16329              * @param {Object} state The hash of state values returned from the StateProvider. If this
16330              * event is not vetoed, then the state object is passed to <b><tt>applyState</tt></b>. By default,
16331              * that simply copies property values into this object. The method maybe overriden to
16332              * provide custom state restoration.
16333              */
16334             'beforestaterestore',
16335             
16336             /**
16337              * @event staterestore
16338              * Fires after the state of the object is restored.
16339              * @param {Ext.state.Stateful} this
16340              * @param {Object} state The hash of state values returned from the StateProvider. This is passed
16341              * to <b><tt>applyState</tt></b>. By default, that simply copies property values into this
16342              * object. The method maybe overriden to provide custom state restoration.
16343              */
16344             'staterestore',
16345             
16346             /**
16347              * @event beforestatesave
16348              * Fires before the state of the object is saved to the configured state provider. Return false to stop the save.
16349              * @param {Ext.state.Stateful} this
16350              * @param {Object} state The hash of state values. This is determined by calling
16351              * <b><tt>getState()</tt></b> on the object. This method must be provided by the
16352              * developer to return whetever representation of state is required, by default, Ext.state.Stateful
16353              * has a null implementation.
16354              */
16355             'beforestatesave',
16356             
16357             /**
16358              * @event statesave
16359              * Fires after the state of the object is saved to the configured state provider.
16360              * @param {Ext.state.Stateful} this
16361              * @param {Object} state The hash of state values. This is determined by calling
16362              * <b><tt>getState()</tt></b> on the object. This method must be provided by the
16363              * developer to return whetever representation of state is required, by default, Ext.state.Stateful
16364              * has a null implementation.
16365              */
16366             'statesave'
16367         );
16368         me.mixins.observable.constructor.call(me);
16369         if (me.stateful !== false) {
16370             me.initStateEvents();
16371             me.initState();
16372         }
16373     },
16374     
16375     /**
16376      * Initializes any state events for this object.
16377      * @private
16378      */
16379     initStateEvents: function() {
16380         this.addStateEvents(this.stateEvents);
16381     },
16382     
16383     /**
16384      * Add events that will trigger the state to be saved.
16385      * @param {String/Array} events The event name or an array of event names.
16386      */
16387     addStateEvents: function(events){
16388         if (!Ext.isArray(events)) {
16389             events = [events];
16390         }
16391         
16392         var me = this,
16393             i = 0,
16394             len = events.length;
16395             
16396         for (; i < len; ++i) {
16397             me.on(events[i], me.onStateChange, me);
16398         }
16399     },
16400     
16401     /**
16402      * This method is called when any of the {@link #stateEvents} are fired.
16403      * @private
16404      */
16405     onStateChange: function(){
16406         var me = this,
16407             delay = me.saveDelay;
16408         
16409         if (delay > 0) {
16410             if (!me.stateTask) {
16411                 me.stateTask = Ext.create('Ext.util.DelayedTask', me.saveState, me);
16412             }
16413             me.stateTask.delay(me.saveDelay);
16414         } else {
16415             me.saveState();
16416         }
16417     },
16418     
16419     /**
16420      * Saves the state of the object to the persistence store.
16421      * @private
16422      */
16423     saveState: function() {
16424         var me = this,
16425             id,
16426             state;
16427         
16428         if (me.stateful !== false) {
16429             id = me.getStateId();
16430             if (id) {
16431                 state = me.getState();
16432                 if (me.fireEvent('beforestatesave', me, state) !== false) {
16433                     Ext.state.Manager.set(id, state);
16434                     me.fireEvent('statesave', me, state);
16435                 }
16436             }
16437         }
16438     },
16439     
16440     /**
16441      * Gets the current state of the object. By default this function returns null,
16442      * it should be overridden in subclasses to implement methods for getting the state.
16443      * @return {Object} The current state
16444      */
16445     getState: function(){
16446         return null;    
16447     },
16448     
16449     /**
16450      * Applies the state to the object. This should be overridden in subclasses to do
16451      * more complex state operations. By default it applies the state properties onto
16452      * the current object.
16453      * @param {Object} state The state
16454      */
16455     applyState: function(state) {
16456         if (state) {
16457             Ext.apply(this, state);
16458         }
16459     },
16460     
16461     /**
16462      * Gets the state id for this object.
16463      * @return {String} The state id, null if not found.
16464      */
16465     getStateId: function() {
16466         var me = this,
16467             id = me.stateId;
16468         
16469         if (!id) {
16470             id = me.autoGenIdRe.test(String(me.id)) ? null : me.id;
16471         }
16472         return id;
16473     },
16474     
16475     /**
16476      * Initializes the state of the object upon construction.
16477      * @private
16478      */
16479     initState: function(){
16480         var me = this,
16481             id = me.getStateId(),
16482             state;
16483             
16484         if (me.stateful !== false) {
16485             if (id) {
16486                 state = Ext.state.Manager.get(id);
16487                 if (state) {
16488                     state = Ext.apply({}, state);
16489                     if (me.fireEvent('beforestaterestore', me, state) !== false) {
16490                         me.applyState(state);
16491                         me.fireEvent('staterestore', me, state);
16492                     }
16493                 }
16494             }
16495         }
16496     },
16497     
16498     /**
16499      * Destroys this stateful object.
16500      */
16501     destroy: function(){
16502         var task = this.stateTask;
16503         if (task) {
16504             task.cancel();
16505         }
16506         this.clearListeners();
16507         
16508     }
16509     
16510 });
16511
16512 /**
16513  * @class Ext.AbstractManager
16514  * @extends Object
16515  * @ignore
16516  * Base Manager class
16517  */
16518
16519 Ext.define('Ext.AbstractManager', {
16520
16521     /* Begin Definitions */
16522
16523     requires: ['Ext.util.HashMap'],
16524
16525     /* End Definitions */
16526
16527     typeName: 'type',
16528
16529     constructor: function(config) {
16530         Ext.apply(this, config || {});
16531
16532         /**
16533          * Contains all of the items currently managed
16534          * @property all
16535          * @type Ext.util.MixedCollection
16536          */
16537         this.all = Ext.create('Ext.util.HashMap');
16538
16539         this.types = {};
16540     },
16541
16542     /**
16543      * Returns an item by id.
16544      * For additional details see {@link Ext.util.HashMap#get}.
16545      * @param {String} id The id of the item
16546      * @return {Mixed} The item, <code>undefined</code> if not found.
16547      */
16548     get : function(id) {
16549         return this.all.get(id);
16550     },
16551
16552     /**
16553      * Registers an item to be managed
16554      * @param {Mixed} item The item to register
16555      */
16556     register: function(item) {
16557         this.all.add(item);
16558     },
16559
16560     /**
16561      * Unregisters an item by removing it from this manager
16562      * @param {Mixed} item The item to unregister
16563      */
16564     unregister: function(item) {
16565         this.all.remove(item);
16566     },
16567
16568     /**
16569      * <p>Registers a new item constructor, keyed by a type key.
16570      * @param {String} type The mnemonic string by which the class may be looked up.
16571      * @param {Constructor} cls The new instance class.
16572      */
16573     registerType : function(type, cls) {
16574         this.types[type] = cls;
16575         cls[this.typeName] = type;
16576     },
16577
16578     /**
16579      * Checks if an item type is registered.
16580      * @param {String} type The mnemonic string by which the class may be looked up
16581      * @return {Boolean} Whether the type is registered.
16582      */
16583     isRegistered : function(type){
16584         return this.types[type] !== undefined;
16585     },
16586
16587     /**
16588      * Creates and returns an instance of whatever this manager manages, based on the supplied type and config object
16589      * @param {Object} config The config object
16590      * @param {String} defaultType If no type is discovered in the config object, we fall back to this type
16591      * @return {Mixed} The instance of whatever this manager is managing
16592      */
16593     create: function(config, defaultType) {
16594         var type        = config[this.typeName] || config.type || defaultType,
16595             Constructor = this.types[type];
16596
16597         if (Constructor == undefined) {
16598             Ext.Error.raise("The '" + type + "' type has not been registered with this manager");
16599         }
16600
16601         return new Constructor(config);
16602     },
16603
16604     /**
16605      * Registers a function that will be called when an item with the specified id is added to the manager. This will happen on instantiation.
16606      * @param {String} id The item id
16607      * @param {Function} fn The callback function. Called with a single parameter, the item.
16608      * @param {Object} scope The scope (<code>this</code> reference) in which the callback is executed. Defaults to the item.
16609      */
16610     onAvailable : function(id, fn, scope){
16611         var all = this.all,
16612             item;
16613         
16614         if (all.containsKey(id)) {
16615             item = all.get(id);
16616             fn.call(scope || item, item);
16617         } else {
16618             all.on('add', function(map, key, item){
16619                 if (key == id) {
16620                     fn.call(scope || item, item);
16621                     all.un('add', fn, scope);
16622                 }
16623             });
16624         }
16625     },
16626     
16627     /**
16628      * Executes the specified function once for each item in the collection.
16629      * Returning false from the function will cease iteration.
16630      * 
16631      * The paramaters passed to the function are:
16632      * <div class="mdetail-params"><ul>
16633      * <li><b>key</b> : String<p class="sub-desc">The key of the item</p></li>
16634      * <li><b>value</b> : Number<p class="sub-desc">The value of the item</p></li>
16635      * <li><b>length</b> : Number<p class="sub-desc">The total number of items in the collection</p></li>
16636      * </ul></div>
16637      * @param {Object} fn The function to execute.
16638      * @param {Object} scope The scope to execute in. Defaults to <tt>this</tt>.
16639      */
16640     each: function(fn, scope){
16641         this.all.each(fn, scope || this);    
16642     },
16643     
16644     /**
16645      * Gets the number of items in the collection.
16646      * @return {Number} The number of items in the collection.
16647      */
16648     getCount: function(){
16649         return this.all.getCount();
16650     }
16651 });
16652
16653 /**
16654  * @class Ext.PluginManager
16655  * @extends Ext.AbstractManager
16656  * <p>Provides a registry of available Plugin <i>classes</i> indexed by a mnemonic code known as the Plugin's ptype.
16657  * The <code>{@link Ext.Component#xtype xtype}</code> provides a way to avoid instantiating child Components
16658  * when creating a full, nested config object for a complete Ext page.</p>
16659  * <p>A child Component may be specified simply as a <i>config object</i>
16660  * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component
16661  * needs rendering, the correct type can be looked up for lazy instantiation.</p>
16662  * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p>
16663  * @singleton
16664  */
16665 Ext.define('Ext.PluginManager', {
16666     extend: 'Ext.AbstractManager',
16667     alternateClassName: 'Ext.PluginMgr',
16668     singleton: true,
16669     typeName: 'ptype',
16670
16671     /**
16672      * Creates a new Plugin from the specified config object using the
16673      * config object's ptype to determine the class to instantiate.
16674      * @param {Object} config A configuration object for the Plugin you wish to create.
16675      * @param {Constructor} defaultType The constructor to provide the default Plugin type if
16676      * the config object does not contain a <code>ptype</code>. (Optional if the config contains a <code>ptype</code>).
16677      * @return {Ext.Component} The newly instantiated Plugin.
16678      */
16679     //create: function(plugin, defaultType) {
16680     //    if (plugin instanceof this) {
16681     //        return plugin;
16682     //    } else {
16683     //        var type, config = {};
16684     //
16685     //        if (Ext.isString(plugin)) {
16686     //            type = plugin;
16687     //        }
16688     //        else {
16689     //            type = plugin[this.typeName] || defaultType;
16690     //            config = plugin;
16691     //        }
16692     //
16693     //        return Ext.createByAlias('plugin.' + type, config);
16694     //    }
16695     //},
16696
16697     create : function(config, defaultType){
16698         if (config.init) {
16699             return config;
16700         } else {
16701             return Ext.createByAlias('plugin.' + (config.ptype || defaultType), config);
16702         }
16703         
16704         // Prior system supported Singleton plugins.
16705         //var PluginCls = this.types[config.ptype || defaultType];
16706         //if (PluginCls.init) {
16707         //    return PluginCls;
16708         //} else {
16709         //    return new PluginCls(config);
16710         //}
16711     },
16712
16713     /**
16714      * Returns all plugins registered with the given type. Here, 'type' refers to the type of plugin, not its ptype.
16715      * @param {String} type The type to search for
16716      * @param {Boolean} defaultsOnly True to only return plugins of this type where the plugin's isDefault property is truthy
16717      * @return {Array} All matching plugins
16718      */
16719     findByType: function(type, defaultsOnly) {
16720         var matches = [],
16721             types   = this.types;
16722
16723         for (var name in types) {
16724             if (!types.hasOwnProperty(name)) {
16725                 continue;
16726             }
16727             var item = types[name];
16728
16729             if (item.type == type && (!defaultsOnly || (defaultsOnly === true && item.isDefault))) {
16730                 matches.push(item);
16731             }
16732         }
16733
16734         return matches;
16735     }
16736 }, function() {    
16737     /**
16738      * Shorthand for {@link Ext.PluginManager#registerType}
16739      * @param {String} ptype The ptype mnemonic string by which the Plugin class
16740      * may be looked up.
16741      * @param {Constructor} cls The new Plugin class.
16742      * @member Ext
16743      * @method preg
16744      */
16745     Ext.preg = function() {
16746         return Ext.PluginManager.registerType.apply(Ext.PluginManager, arguments);
16747     };
16748 });
16749
16750 /**
16751  * @class Ext.ComponentManager
16752  * @extends Ext.AbstractManager
16753  * <p>Provides a registry of all Components (instances of {@link Ext.Component} or any subclass
16754  * thereof) on a page so that they can be easily accessed by {@link Ext.Component component}
16755  * {@link Ext.Component#id id} (see {@link #get}, or the convenience method {@link Ext#getCmp Ext.getCmp}).</p>
16756  * <p>This object also provides a registry of available Component <i>classes</i>
16757  * indexed by a mnemonic code known as the Component's {@link Ext.Component#xtype xtype}.
16758  * The <code>xtype</code> provides a way to avoid instantiating child Components
16759  * when creating a full, nested config object for a complete Ext page.</p>
16760  * <p>A child Component may be specified simply as a <i>config object</i>
16761  * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component
16762  * needs rendering, the correct type can be looked up for lazy instantiation.</p>
16763  * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p>
16764  * @singleton
16765  */
16766 Ext.define('Ext.ComponentManager', {
16767     extend: 'Ext.AbstractManager',
16768     alternateClassName: 'Ext.ComponentMgr',
16769     
16770     singleton: true,
16771     
16772     typeName: 'xtype',
16773     
16774     /**
16775      * Creates a new Component from the specified config object using the
16776      * config object's xtype to determine the class to instantiate.
16777      * @param {Object} config A configuration object for the Component you wish to create.
16778      * @param {Constructor} defaultType The constructor to provide the default Component type if
16779      * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
16780      * @return {Ext.Component} The newly instantiated Component.
16781      */
16782     create: function(component, defaultType){
16783         if (component instanceof Ext.AbstractComponent) {
16784             return component;
16785         }
16786         else if (Ext.isString(component)) {
16787             return Ext.createByAlias('widget.' + component);
16788         }
16789         else {
16790             var type = component.xtype || defaultType,
16791                 config = component;
16792             
16793             return Ext.createByAlias('widget.' + type, config);
16794         }
16795     },
16796
16797     registerType: function(type, cls) {
16798         this.types[type] = cls;
16799         cls[this.typeName] = type;
16800         cls.prototype[this.typeName] = type;
16801     }
16802 });
16803 /**
16804  * @class Ext.XTemplate
16805  * @extends Ext.Template
16806  * <p>A template class that supports advanced functionality like:<div class="mdetail-params"><ul>
16807  * <li>Autofilling arrays using templates and sub-templates</li>
16808  * <li>Conditional processing with basic comparison operators</li>
16809  * <li>Basic math function support</li>
16810  * <li>Execute arbitrary inline code with special built-in template variables</li>
16811  * <li>Custom member functions</li>
16812  * <li>Many special tags and built-in operators that aren't defined as part of
16813  * the API, but are supported in the templates that can be created</li>
16814  * </ul></div></p>
16815  * <p>XTemplate provides the templating mechanism built into:<div class="mdetail-params"><ul>
16816  * <li>{@link Ext.view.View}</li>
16817  * </ul></div></p>
16818  *
16819  * The {@link Ext.Template} describes
16820  * the acceptable parameters to pass to the constructor. The following
16821  * examples demonstrate all of the supported features.</p>
16822  *
16823  * <div class="mdetail-params"><ul>
16824  *
16825  * <li><b><u>Sample Data</u></b>
16826  * <div class="sub-desc">
16827  * <p>This is the data object used for reference in each code example:</p>
16828  * <pre><code>
16829 var data = {
16830 name: 'Tommy Maintz',
16831 title: 'Lead Developer',
16832 company: 'Sencha Inc.',
16833 email: 'tommy@sencha.com',
16834 address: '5 Cups Drive',
16835 city: 'Palo Alto',
16836 state: 'CA',
16837 zip: '44102',
16838 drinks: ['Coffee', 'Soda', 'Water'],
16839 kids: [{
16840         name: 'Joshua',
16841         age:3
16842     },{
16843         name: 'Matthew',
16844         age:2
16845     },{
16846         name: 'Solomon',
16847         age:0
16848 }]
16849 };
16850  </code></pre>
16851  * </div>
16852  * </li>
16853  *
16854  *
16855  * <li><b><u>Auto filling of arrays</u></b>
16856  * <div class="sub-desc">
16857  * <p>The <b><tt>tpl</tt></b> tag and the <b><tt>for</tt></b> operator are used
16858  * to process the provided data object:
16859  * <ul>
16860  * <li>If the value specified in <tt>for</tt> is an array, it will auto-fill,
16861  * repeating the template block inside the <tt>tpl</tt> tag for each item in the
16862  * array.</li>
16863  * <li>If <tt>for="."</tt> is specified, the data object provided is examined.</li>
16864  * <li>While processing an array, the special variable <tt>{#}</tt>
16865  * will provide the current array index + 1 (starts at 1, not 0).</li>
16866  * </ul>
16867  * </p>
16868  * <pre><code>
16869 &lt;tpl <b>for</b>=".">...&lt;/tpl>       // loop through array at root node
16870 &lt;tpl <b>for</b>="foo">...&lt;/tpl>     // loop through array at foo node
16871 &lt;tpl <b>for</b>="foo.bar">...&lt;/tpl> // loop through array at foo.bar node
16872  </code></pre>
16873  * Using the sample data above:
16874  * <pre><code>
16875 var tpl = new Ext.XTemplate(
16876     '&lt;p>Kids: ',
16877     '&lt;tpl <b>for</b>=".">',       // process the data.kids node
16878         '&lt;p>{#}. {name}&lt;/p>',  // use current array index to autonumber
16879     '&lt;/tpl>&lt;/p>'
16880 );
16881 tpl.overwrite(panel.body, data.kids); // pass the kids property of the data object
16882  </code></pre>
16883  * <p>An example illustrating how the <b><tt>for</tt></b> property can be leveraged
16884  * to access specified members of the provided data object to populate the template:</p>
16885  * <pre><code>
16886 var tpl = new Ext.XTemplate(
16887     '&lt;p>Name: {name}&lt;/p>',
16888     '&lt;p>Title: {title}&lt;/p>',
16889     '&lt;p>Company: {company}&lt;/p>',
16890     '&lt;p>Kids: ',
16891     '&lt;tpl <b>for="kids"</b>>',     // interrogate the kids property within the data
16892         '&lt;p>{name}&lt;/p>',
16893     '&lt;/tpl>&lt;/p>'
16894 );
16895 tpl.overwrite(panel.body, data);  // pass the root node of the data object
16896  </code></pre>
16897  * <p>Flat arrays that contain values (and not objects) can be auto-rendered
16898  * using the special <b><tt>{.}</tt></b> variable inside a loop.  This variable
16899  * will represent the value of the array at the current index:</p>
16900  * <pre><code>
16901 var tpl = new Ext.XTemplate(
16902     '&lt;p>{name}\&#39;s favorite beverages:&lt;/p>',
16903     '&lt;tpl for="drinks">',
16904         '&lt;div> - {.}&lt;/div>',
16905     '&lt;/tpl>'
16906 );
16907 tpl.overwrite(panel.body, data);
16908  </code></pre>
16909  * <p>When processing a sub-template, for example while looping through a child array,
16910  * you can access the parent object's members via the <b><tt>parent</tt></b> object:</p>
16911  * <pre><code>
16912 var tpl = new Ext.XTemplate(
16913     '&lt;p>Name: {name}&lt;/p>',
16914     '&lt;p>Kids: ',
16915     '&lt;tpl for="kids">',
16916         '&lt;tpl if="age &amp;gt; 1">',
16917             '&lt;p>{name}&lt;/p>',
16918             '&lt;p>Dad: {<b>parent</b>.name}&lt;/p>',
16919         '&lt;/tpl>',
16920     '&lt;/tpl>&lt;/p>'
16921 );
16922 tpl.overwrite(panel.body, data);
16923  </code></pre>
16924  * </div>
16925  * </li>
16926  *
16927  *
16928  * <li><b><u>Conditional processing with basic comparison operators</u></b>
16929  * <div class="sub-desc">
16930  * <p>The <b><tt>tpl</tt></b> tag and the <b><tt>if</tt></b> operator are used
16931  * to provide conditional checks for deciding whether or not to render specific
16932  * parts of the template. Notes:<div class="sub-desc"><ul>
16933  * <li>Double quotes must be encoded if used within the conditional</li>
16934  * <li>There is no <tt>else</tt> operator &mdash; if needed, two opposite
16935  * <tt>if</tt> statements should be used.</li>
16936  * </ul></div>
16937  * <pre><code>
16938 &lt;tpl if="age &gt; 1 &amp;&amp; age &lt; 10">Child&lt;/tpl>
16939 &lt;tpl if="age >= 10 && age < 18">Teenager&lt;/tpl>
16940 &lt;tpl <b>if</b>="this.isGirl(name)">...&lt;/tpl>
16941 &lt;tpl <b>if</b>="id==\'download\'">...&lt;/tpl>
16942 &lt;tpl <b>if</b>="needsIcon">&lt;img src="{icon}" class="{iconCls}"/>&lt;/tpl>
16943 // no good:
16944 &lt;tpl if="name == "Tommy"">Hello&lt;/tpl>
16945 // encode &#34; if it is part of the condition, e.g.
16946 &lt;tpl if="name == &#38;quot;Tommy&#38;quot;">Hello&lt;/tpl>
16947  * </code></pre>
16948  * Using the sample data above:
16949  * <pre><code>
16950 var tpl = new Ext.XTemplate(
16951     '&lt;p>Name: {name}&lt;/p>',
16952     '&lt;p>Kids: ',
16953     '&lt;tpl for="kids">',
16954         '&lt;tpl if="age &amp;gt; 1">',
16955             '&lt;p>{name}&lt;/p>',
16956         '&lt;/tpl>',
16957     '&lt;/tpl>&lt;/p>'
16958 );
16959 tpl.overwrite(panel.body, data);
16960  </code></pre>
16961  * </div>
16962  * </li>
16963  *
16964  *
16965  * <li><b><u>Basic math support</u></b>
16966  * <div class="sub-desc">
16967  * <p>The following basic math operators may be applied directly on numeric
16968  * data values:</p><pre>
16969  * + - * /
16970  * </pre>
16971  * For example:
16972  * <pre><code>
16973 var tpl = new Ext.XTemplate(
16974     '&lt;p>Name: {name}&lt;/p>',
16975     '&lt;p>Kids: ',
16976     '&lt;tpl for="kids">',
16977         '&lt;tpl if="age &amp;gt; 1">',  // <-- Note that the &gt; is encoded
16978             '&lt;p>{#}: {name}&lt;/p>',  // <-- Auto-number each item
16979             '&lt;p>In 5 Years: {age+5}&lt;/p>',  // <-- Basic math
16980             '&lt;p>Dad: {parent.name}&lt;/p>',
16981         '&lt;/tpl>',
16982     '&lt;/tpl>&lt;/p>'
16983 );
16984 tpl.overwrite(panel.body, data);
16985  </code></pre>
16986  * </div>
16987  * </li>
16988  *
16989  *
16990  * <li><b><u>Execute arbitrary inline code with special built-in template variables</u></b>
16991  * <div class="sub-desc">
16992  * <p>Anything between <code>{[ ... ]}</code> is considered code to be executed
16993  * in the scope of the template. There are some special variables available in that code:
16994  * <ul>
16995  * <li><b><tt>values</tt></b>: The values in the current scope. If you are using
16996  * scope changing sub-templates, you can change what <tt>values</tt> is.</li>
16997  * <li><b><tt>parent</tt></b>: The scope (values) of the ancestor template.</li>
16998  * <li><b><tt>xindex</tt></b>: If you are in a looping template, the index of the
16999  * loop you are in (1-based).</li>
17000  * <li><b><tt>xcount</tt></b>: If you are in a looping template, the total length
17001  * of the array you are looping.</li>
17002  * </ul>
17003  * This example demonstrates basic row striping using an inline code block and the
17004  * <tt>xindex</tt> variable:</p>
17005  * <pre><code>
17006 var tpl = new Ext.XTemplate(
17007     '&lt;p>Name: {name}&lt;/p>',
17008     '&lt;p>Company: {[values.company.toUpperCase() + ", " + values.title]}&lt;/p>',
17009     '&lt;p>Kids: ',
17010     '&lt;tpl for="kids">',
17011         '&lt;div class="{[xindex % 2 === 0 ? "even" : "odd"]}">',
17012         '{name}',
17013         '&lt;/div>',
17014     '&lt;/tpl>&lt;/p>'
17015  );
17016 tpl.overwrite(panel.body, data);
17017  </code></pre>
17018  * </div>
17019  * </li>
17020  *
17021  * <li><b><u>Template member functions</u></b>
17022  * <div class="sub-desc">
17023  * <p>One or more member functions can be specified in a configuration
17024  * object passed into the XTemplate constructor for more complex processing:</p>
17025  * <pre><code>
17026 var tpl = new Ext.XTemplate(
17027     '&lt;p>Name: {name}&lt;/p>',
17028     '&lt;p>Kids: ',
17029     '&lt;tpl for="kids">',
17030         '&lt;tpl if="this.isGirl(name)">',
17031             '&lt;p>Girl: {name} - {age}&lt;/p>',
17032         '&lt;/tpl>',
17033          // use opposite if statement to simulate 'else' processing:
17034         '&lt;tpl if="this.isGirl(name) == false">',
17035             '&lt;p>Boy: {name} - {age}&lt;/p>',
17036         '&lt;/tpl>',
17037         '&lt;tpl if="this.isBaby(age)">',
17038             '&lt;p>{name} is a baby!&lt;/p>',
17039         '&lt;/tpl>',
17040     '&lt;/tpl>&lt;/p>',
17041     {
17042         // XTemplate configuration:
17043         compiled: true,
17044         // member functions:
17045         isGirl: function(name){
17046            return name == 'Sara Grace';
17047         },
17048         isBaby: function(age){
17049            return age < 1;
17050         }
17051     }
17052 );
17053 tpl.overwrite(panel.body, data);
17054  </code></pre>
17055  * </div>
17056  * </li>
17057  *
17058  * </ul></div>
17059  *
17060  * @param {Mixed} config
17061  */
17062
17063 Ext.define('Ext.XTemplate', {
17064
17065     /* Begin Definitions */
17066
17067     extend: 'Ext.Template',
17068
17069     statics: {
17070         /**
17071          * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
17072          * @param {String/HTMLElement} el A DOM element or its id
17073          * @return {Ext.Template} The created template
17074          * @static
17075          */
17076         from: function(el, config) {
17077             el = Ext.getDom(el);
17078             return new this(el.value || el.innerHTML, config || {});
17079         }
17080     },
17081
17082     
17083
17084     argsRe: /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
17085     nameRe: /^<tpl\b[^>]*?for="(.*?)"/,
17086     ifRe: /^<tpl\b[^>]*?if="(.*?)"/,
17087     execRe: /^<tpl\b[^>]*?exec="(.*?)"/,
17088     constructor: function() {
17089         this.callParent(arguments);
17090
17091         var me = this,
17092             html = me.html,
17093             argsRe = me.argsRe,
17094             nameRe = me.nameRe,
17095             ifRe = me.ifRe,
17096             execRe = me.execRe,
17097             id = 0,
17098             tpls = [],
17099             VALUES = 'values',
17100             PARENT = 'parent',
17101             XINDEX = 'xindex',
17102             XCOUNT = 'xcount',
17103             RETURN = 'return ',
17104             WITHVALUES = 'with(values){ ',
17105             m, matchName, matchIf, matchExec, exp, fn, exec, name, i;
17106
17107         html = ['<tpl>', html, '</tpl>'].join('');
17108
17109         while ((m = html.match(argsRe))) {
17110             exp = null;
17111             fn = null;
17112             exec = null;
17113             matchName = m[0].match(nameRe);
17114             matchIf = m[0].match(ifRe);
17115             matchExec = m[0].match(execRe);
17116
17117             exp = matchIf ? matchIf[1] : null;
17118             if (exp) {
17119                 fn = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + 'try{' + RETURN + Ext.String.htmlDecode(exp) + ';}catch(e){return;}}');
17120             }
17121
17122             exp = matchExec ? matchExec[1] : null;
17123             if (exp) {
17124                 exec = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + Ext.String.htmlDecode(exp) + ';}');
17125             }
17126
17127             name = matchName ? matchName[1] : null;
17128             if (name) {
17129                 if (name === '.') {
17130                     name = VALUES;
17131                 } else if (name === '..') {
17132                     name = PARENT;
17133                 }
17134                 name = Ext.functionFactory(VALUES, PARENT, 'try{' + WITHVALUES + RETURN + name + ';}}catch(e){return;}');
17135             }
17136
17137             tpls.push({
17138                 id: id,
17139                 target: name,
17140                 exec: exec,
17141                 test: fn,
17142                 body: m[1] || ''
17143             });
17144
17145             html = html.replace(m[0], '{xtpl' + id + '}');
17146             id = id + 1;
17147         }
17148
17149         for (i = tpls.length - 1; i >= 0; --i) {
17150             me.compileTpl(tpls[i]);
17151         }
17152         me.master = tpls[tpls.length - 1];
17153         me.tpls = tpls;
17154     },
17155
17156     
17157     applySubTemplate: function(id, values, parent, xindex, xcount) {
17158         var me = this, t = me.tpls[id];
17159         return t.compiled.call(me, values, parent, xindex, xcount);
17160     },
17161     
17162     codeRe: /\{\[((?:\\\]|.|\n)*?)\]\}/g,
17163
17164     re: /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\/]\s?[\d\.\+\-\*\/\(\)]+)?\}/g,
17165
17166     
17167     compileTpl: function(tpl) {
17168         var fm = Ext.util.Format,
17169             me = this,
17170             useFormat = me.disableFormats !== true,
17171             body, bodyReturn, evaluatedFn;
17172
17173         function fn(m, name, format, args, math) {
17174             var v;
17175             
17176             
17177             if (name.substr(0, 4) == 'xtpl') {
17178                 return "',this.applySubTemplate(" + name.substr(4) + ", values, parent, xindex, xcount),'";
17179             }
17180             
17181             if (name == '.') {
17182                 
17183                 v = 'Ext.Array.indexOf(["string", "number", "boolean"], typeof values) > -1 || Ext.isDate(values) ? values : ""';
17184             }
17185
17186             
17187             else if (name == '#') {
17188                 v = 'xindex';
17189             }
17190             else if (name.substr(0, 7) == "parent.") {
17191                 v = name;
17192             }
17193             
17194             else if (name.indexOf('.') != -1) {
17195                 v = "values." + name;
17196             }
17197
17198             
17199             else {
17200                 v = "values['" + name + "']";
17201             }
17202             if (math) {
17203                 v = '(' + v + math + ')';
17204             }
17205             if (format && useFormat) {
17206                 args = args ? ',' + args : "";
17207                 if (format.substr(0, 5) != "this.") {
17208                     format = "fm." + format + '(';
17209                 }
17210                 else {
17211                     format = 'this.' + format.substr(5) + '(';
17212                 }
17213             }
17214             else {
17215                 args = '';
17216                 format = "(" + v + " === undefined ? '' : ";
17217             }
17218             return "'," + format + v + args + "),'";
17219         }
17220
17221         function codeFn(m, code) {
17222             
17223             return "',(" + code.replace(me.compileARe, "'") + "),'";
17224         }
17225
17226         bodyReturn = tpl.body.replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn).replace(me.codeRe, codeFn);
17227         body = "evaluatedFn = function(values, parent, xindex, xcount){return ['" + bodyReturn + "'].join('');};";
17228         eval(body);
17229
17230         tpl.compiled = function(values, parent, xindex, xcount) {
17231             var vs,
17232                 length,
17233                 buffer,
17234                 i;
17235
17236             if (tpl.test && !tpl.test.call(me, values, parent, xindex, xcount)) {
17237                 return '';
17238             }
17239
17240             vs = tpl.target ? tpl.target.call(me, values, parent) : values;
17241             if (!vs) {
17242                return '';
17243             }
17244
17245             parent = tpl.target ? values : parent;
17246             if (tpl.target && Ext.isArray(vs)) {
17247                 buffer = [];
17248                 length = vs.length;
17249                 if (tpl.exec) {
17250                     for (i = 0; i < length; i++) {
17251                         buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
17252                         tpl.exec.call(me, vs[i], parent, i + 1, length);
17253                     }
17254                 } else {
17255                     for (i = 0; i < length; i++) {
17256                         buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
17257                     }
17258                 }
17259                 return buffer.join('');
17260             }
17261
17262             if (tpl.exec) {
17263                 tpl.exec.call(me, vs, parent, xindex, xcount);
17264             }
17265             return evaluatedFn.call(me, vs, parent, xindex, xcount);
17266         };
17267
17268         return this;
17269     },
17270
17271     
17272     applyTemplate: function(values) {
17273         return this.master.compiled.call(this, values, {}, 1, 1);
17274     },
17275
17276     
17277     compile: function() {
17278         return this;
17279     }
17280 }, function() {
17281     
17282     this.createAlias('apply', 'applyTemplate');
17283 });
17284
17285
17286 Ext.define('Ext.util.AbstractMixedCollection', {
17287     requires: ['Ext.util.Filter'],
17288     
17289     mixins: {
17290         observable: 'Ext.util.Observable'
17291     },
17292
17293     constructor: function(allowFunctions, keyFn) {
17294         var me = this;
17295
17296         me.items = [];
17297         me.map = {};
17298         me.keys = [];
17299         me.length = 0;
17300
17301         me.addEvents(
17302             
17303             'clear',
17304
17305             
17306             'add',
17307
17308             
17309             'replace',
17310
17311             
17312             'remove'
17313         );
17314
17315         me.allowFunctions = allowFunctions === true;
17316
17317         if (keyFn) {
17318             me.getKey = keyFn;
17319         }
17320
17321         me.mixins.observable.constructor.call(me);
17322     },
17323     
17324     
17325     allowFunctions : false,
17326
17327     
17328     add : function(key, obj){
17329         var me = this,
17330             myObj = obj,
17331             myKey = key,
17332             old;
17333
17334         if (arguments.length == 1) {
17335             myObj = myKey;
17336             myKey = me.getKey(myObj);
17337         }
17338         if (typeof myKey != 'undefined' && myKey !== null) {
17339             old = me.map[myKey];
17340             if (typeof old != 'undefined') {
17341                 return me.replace(myKey, myObj);
17342             }
17343             me.map[myKey] = myObj;
17344         }
17345         me.length++;
17346         me.items.push(myObj);
17347         me.keys.push(myKey);
17348         me.fireEvent('add', me.length - 1, myObj, myKey);
17349         return myObj;
17350     },
17351
17352     
17353     getKey : function(o){
17354          return o.id;
17355     },
17356
17357     
17358     replace : function(key, o){
17359         var me = this,
17360             old,
17361             index;
17362
17363         if (arguments.length == 1) {
17364             o = arguments[0];
17365             key = me.getKey(o);
17366         }
17367         old = me.map[key];
17368         if (typeof key == 'undefined' || key === null || typeof old == 'undefined') {
17369              return me.add(key, o);
17370         }
17371         index = me.indexOfKey(key);
17372         me.items[index] = o;
17373         me.map[key] = o;
17374         me.fireEvent('replace', key, old, o);
17375         return o;
17376     },
17377
17378     
17379     addAll : function(objs){
17380         var me = this,
17381             i = 0,
17382             args,
17383             len,
17384             key;
17385
17386         if (arguments.length > 1 || Ext.isArray(objs)) {
17387             args = arguments.length > 1 ? arguments : objs;
17388             for (len = args.length; i < len; i++) {
17389                 me.add(args[i]);
17390             }
17391         } else {
17392             for (key in objs) {
17393                 if (objs.hasOwnProperty(key)) {
17394                     if (me.allowFunctions || typeof objs[key] != 'function') {
17395                         me.add(key, objs[key]);
17396                     }
17397                 }
17398             }
17399         }
17400     },
17401
17402     
17403     each : function(fn, scope){
17404         var items = [].concat(this.items), 
17405             i = 0,
17406             len = items.length,
17407             item;
17408
17409         for (; i < len; i++) {
17410             item = items[i];
17411             if (fn.call(scope || item, item, i, len) === false) {
17412                 break;
17413             }
17414         }
17415     },
17416
17417     
17418     eachKey : function(fn, scope){
17419         var keys = this.keys,
17420             items = this.items,
17421             i = 0,
17422             len = keys.length;
17423
17424         for (; i < len; i++) {
17425             fn.call(scope || window, keys[i], items[i], i, len);
17426         }
17427     },
17428
17429     
17430     findBy : function(fn, scope) {
17431         var keys = this.keys,
17432             items = this.items,
17433             i = 0,
17434             len = items.length;
17435
17436         for (; i < len; i++) {
17437             if (fn.call(scope || window, items[i], keys[i])) {
17438                 return items[i];
17439             }
17440         }
17441         return null;
17442     },
17443
17444     find : function() {
17445         if (Ext.isDefined(Ext.global.console)) {
17446             Ext.global.console.warn('Ext.util.MixedCollection: find has been deprecated. Use findBy instead.');
17447         }
17448         return this.findBy.apply(this, arguments);
17449     },
17450
17451     
17452     insert : function(index, key, obj){
17453         var me = this,
17454             myKey = key,
17455             myObj = obj;
17456
17457         if (arguments.length == 2) {
17458             myObj = myKey;
17459             myKey = me.getKey(myObj);
17460         }
17461         if (me.containsKey(myKey)) {
17462             me.suspendEvents();
17463             me.removeAtKey(myKey);
17464             me.resumeEvents();
17465         }
17466         if (index >= me.length) {
17467             return me.add(myKey, myObj);
17468         }
17469         me.length++;
17470         me.items.splice(index, 0, myObj);
17471         if (typeof myKey != 'undefined' && myKey !== null) {
17472             me.map[myKey] = myObj;
17473         }
17474         me.keys.splice(index, 0, myKey);
17475         me.fireEvent('add', index, myObj, myKey);
17476         return myObj;
17477     },
17478
17479     
17480     remove : function(o){
17481         return this.removeAt(this.indexOf(o));
17482     },
17483
17484     
17485     removeAll : function(items){
17486         Ext.each(items || [], function(item) {
17487             this.remove(item);
17488         }, this);
17489
17490         return this;
17491     },
17492
17493     
17494     removeAt : function(index){
17495         var me = this,
17496             o,
17497             key;
17498
17499         if (index < me.length && index >= 0) {
17500             me.length--;
17501             o = me.items[index];
17502             me.items.splice(index, 1);
17503             key = me.keys[index];
17504             if (typeof key != 'undefined') {
17505                 delete me.map[key];
17506             }
17507             me.keys.splice(index, 1);
17508             me.fireEvent('remove', o, key);
17509             return o;
17510         }
17511         return false;
17512     },
17513
17514     
17515     removeAtKey : function(key){
17516         return this.removeAt(this.indexOfKey(key));
17517     },
17518
17519     
17520     getCount : function(){
17521         return this.length;
17522     },
17523
17524     
17525     indexOf : function(o){
17526         return Ext.Array.indexOf(this.items, o);
17527     },
17528
17529     
17530     indexOfKey : function(key){
17531         return Ext.Array.indexOf(this.keys, key);
17532     },
17533
17534     
17535     get : function(key) {
17536         var me = this,
17537             mk = me.map[key],
17538             item = mk !== undefined ? mk : (typeof key == 'number') ? me.items[key] : undefined;
17539         return typeof item != 'function' || me.allowFunctions ? item : null; 
17540     },
17541
17542     
17543     getAt : function(index) {
17544         return this.items[index];
17545     },
17546
17547     
17548     getByKey : function(key) {
17549         return this.map[key];
17550     },
17551
17552     
17553     contains : function(o){
17554         return Ext.Array.contains(this.items, o);
17555     },
17556
17557     
17558     containsKey : function(key){
17559         return typeof this.map[key] != 'undefined';
17560     },
17561
17562     
17563     clear : function(){
17564         var me = this;
17565
17566         me.length = 0;
17567         me.items = [];
17568         me.keys = [];
17569         me.map = {};
17570         me.fireEvent('clear');
17571     },
17572
17573     
17574     first : function() {
17575         return this.items[0];
17576     },
17577
17578     
17579     last : function() {
17580         return this.items[this.length - 1];
17581     },
17582
17583     
17584     sum: function(property, root, start, end) {
17585         var values = this.extractValues(property, root),
17586             length = values.length,
17587             sum    = 0,
17588             i;
17589
17590         start = start || 0;
17591         end   = (end || end === 0) ? end : length - 1;
17592
17593         for (i = start; i <= end; i++) {
17594             sum += values[i];
17595         }
17596
17597         return sum;
17598     },
17599
17600     
17601     collect: function(property, root, allowNull) {
17602         var values = this.extractValues(property, root),
17603             length = values.length,
17604             hits   = {},
17605             unique = [],
17606             value, strValue, i;
17607
17608         for (i = 0; i < length; i++) {
17609             value = values[i];
17610             strValue = String(value);
17611
17612             if ((allowNull || !Ext.isEmpty(value)) && !hits[strValue]) {
17613                 hits[strValue] = true;
17614                 unique.push(value);
17615             }
17616         }
17617
17618         return unique;
17619     },
17620
17621     
17622     extractValues: function(property, root) {
17623         var values = this.items;
17624
17625         if (root) {
17626             values = Ext.Array.pluck(values, root);
17627         }
17628
17629         return Ext.Array.pluck(values, property);
17630     },
17631
17632     
17633     getRange : function(start, end){
17634         var me = this,
17635             items = me.items,
17636             range = [],
17637             i;
17638
17639         if (items.length < 1) {
17640             return range;
17641         }
17642
17643         start = start || 0;
17644         end = Math.min(typeof end == 'undefined' ? me.length - 1 : end, me.length - 1);
17645         if (start <= end) {
17646             for (i = start; i <= end; i++) {
17647                 range[range.length] = items[i];
17648             }
17649         } else {
17650             for (i = start; i >= end; i--) {
17651                 range[range.length] = items[i];
17652             }
17653         }
17654         return range;
17655     },
17656
17657     
17658     filter : function(property, value, anyMatch, caseSensitive) {
17659         var filters = [],
17660             filterFn;
17661
17662         
17663         if (Ext.isString(property)) {
17664             filters.push(Ext.create('Ext.util.Filter', {
17665                 property     : property,
17666                 value        : value,
17667                 anyMatch     : anyMatch,
17668                 caseSensitive: caseSensitive
17669             }));
17670         } else if (Ext.isArray(property) || property instanceof Ext.util.Filter) {
17671             filters = filters.concat(property);
17672         }
17673
17674         
17675         
17676         filterFn = function(record) {
17677             var isMatch = true,
17678                 length = filters.length,
17679                 i;
17680
17681             for (i = 0; i < length; i++) {
17682                 var filter = filters[i],
17683                     fn     = filter.filterFn,
17684                     scope  = filter.scope;
17685
17686                 isMatch = isMatch && fn.call(scope, record);
17687             }
17688
17689             return isMatch;
17690         };
17691
17692         return this.filterBy(filterFn);
17693     },
17694
17695     
17696     filterBy : function(fn, scope) {
17697         var me = this,
17698             newMC  = new this.self(),
17699             keys   = me.keys,
17700             items  = me.items,
17701             length = items.length,
17702             i;
17703
17704         newMC.getKey = me.getKey;
17705
17706         for (i = 0; i < length; i++) {
17707             if (fn.call(scope || me, items[i], keys[i])) {
17708                 newMC.add(keys[i], items[i]);
17709             }
17710         }
17711
17712         return newMC;
17713     },
17714
17715     
17716     findIndex : function(property, value, start, anyMatch, caseSensitive){
17717         if(Ext.isEmpty(value, false)){
17718             return -1;
17719         }
17720         value = this.createValueMatcher(value, anyMatch, caseSensitive);
17721         return this.findIndexBy(function(o){
17722             return o && value.test(o[property]);
17723         }, null, start);
17724     },
17725
17726     
17727     findIndexBy : function(fn, scope, start){
17728         var me = this,
17729             keys = me.keys,
17730             items = me.items,
17731             i = start || 0,
17732             len = items.length;
17733
17734         for (; i < len; i++) {
17735             if (fn.call(scope || me, items[i], keys[i])) {
17736                 return i;
17737             }
17738         }
17739         return -1;
17740     },
17741
17742     
17743     createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) {
17744         if (!value.exec) { 
17745             var er = Ext.String.escapeRegex;
17746             value = String(value);
17747
17748             if (anyMatch === true) {
17749                 value = er(value);
17750             } else {
17751                 value = '^' + er(value);
17752                 if (exactMatch === true) {
17753                     value += '$';
17754                 }
17755             }
17756             value = new RegExp(value, caseSensitive ? '' : 'i');
17757         }
17758         return value;
17759     },
17760
17761     
17762     clone : function() {
17763         var me = this,
17764             copy = new this.self(),
17765             keys = me.keys,
17766             items = me.items,
17767             i = 0,
17768             len = items.length;
17769
17770         for(; i < len; i++){
17771             copy.add(keys[i], items[i]);
17772         }
17773         copy.getKey = me.getKey;
17774         return copy;
17775     }
17776 });
17777
17778
17779 Ext.define("Ext.util.Sortable", {
17780     
17781     isSortable: true,
17782     
17783     
17784     defaultSortDirection: "ASC",
17785     
17786     requires: [
17787         'Ext.util.Sorter'
17788     ],
17789
17790         
17791     sortRoot: null,
17792     
17793     
17794     initSortable: function() {
17795         var me = this,
17796             sorters = me.sorters;
17797         
17798         
17799         me.sorters = Ext.create('Ext.util.AbstractMixedCollection', false, function(item) {
17800             return item.id || item.property;
17801         });
17802         
17803         if (sorters) {
17804             me.sorters.addAll(me.decodeSorters(sorters));
17805         }
17806     },
17807
17808     
17809     sort: function(sorters, direction, where, doSort) {
17810         var me = this,
17811             sorter, sorterFn,
17812             newSorters;
17813         
17814         if (Ext.isArray(sorters)) {
17815             doSort = where;
17816             where = direction;
17817             newSorters = sorters;
17818         }
17819         else if (Ext.isObject(sorters)) {
17820             doSort = where;
17821             where = direction;
17822             newSorters = [sorters];
17823         }
17824         else if (Ext.isString(sorters)) {
17825             sorter = me.sorters.get(sorters);
17826
17827             if (!sorter) {
17828                 sorter = {
17829                     property : sorters,
17830                     direction: direction
17831                 };
17832                 newSorters = [sorter];
17833             }
17834             else if (direction === undefined) {
17835                 sorter.toggle();
17836             }
17837             else {
17838                 sorter.setDirection(direction);
17839             }
17840         }
17841         
17842         if (newSorters && newSorters.length) {
17843             newSorters = me.decodeSorters(newSorters);
17844             if (Ext.isString(where)) {
17845                 if (where === 'prepend') {
17846                     sorters = me.sorters.clone().items;
17847                     
17848                     me.sorters.clear();
17849                     me.sorters.addAll(newSorters);
17850                     me.sorters.addAll(sorters);
17851                 }
17852                 else {
17853                     me.sorters.addAll(newSorters);
17854                 }
17855             }
17856             else {
17857                 me.sorters.clear();
17858                 me.sorters.addAll(newSorters);
17859             }
17860             
17861             if (doSort !== false) {
17862                 me.onBeforeSort(newSorters);
17863             }
17864         }
17865         
17866         if (doSort !== false) {
17867             sorters = me.sorters.items;
17868             if (sorters.length) {
17869                 
17870                 sorterFn = function(r1, r2) {
17871                     var result = sorters[0].sort(r1, r2),
17872                         length = sorters.length,
17873                         i;
17874
17875                         
17876                         for (i = 1; i < length; i++) {
17877                             result = result || sorters[i].sort.call(this, r1, r2);
17878                         }
17879
17880                     return result;
17881                 };
17882
17883                 me.doSort(sorterFn);                
17884             }
17885         }
17886         
17887         return sorters;
17888     },
17889     
17890     onBeforeSort: Ext.emptyFn,
17891         
17892     
17893     decodeSorters: function(sorters) {
17894         if (!Ext.isArray(sorters)) {
17895             if (sorters === undefined) {
17896                 sorters = [];
17897             } else {
17898                 sorters = [sorters];
17899             }
17900         }
17901
17902         var length = sorters.length,
17903             Sorter = Ext.util.Sorter,
17904             fields = this.model ? this.model.prototype.fields : null,
17905             field,
17906             config, i;
17907
17908         for (i = 0; i < length; i++) {
17909             config = sorters[i];
17910
17911             if (!(config instanceof Sorter)) {
17912                 if (Ext.isString(config)) {
17913                     config = {
17914                         property: config
17915                     };
17916                 }
17917                 
17918                 Ext.applyIf(config, {
17919                     root     : this.sortRoot,
17920                     direction: "ASC"
17921                 });
17922
17923                 
17924                 if (config.fn) {
17925                     config.sorterFn = config.fn;
17926                 }
17927
17928                 
17929                 if (typeof config == 'function') {
17930                     config = {
17931                         sorterFn: config
17932                     };
17933                 }
17934
17935                 
17936                 if (fields && !config.transform) {
17937                     field = fields.get(config.property);
17938                     config.transform = field ? field.sortType : undefined;
17939                 }
17940                 sorters[i] = Ext.create('Ext.util.Sorter', config);
17941             }
17942         }
17943
17944         return sorters;
17945     },
17946     
17947     getSorters: function() {
17948         return this.sorters.items;
17949     }
17950 });
17951
17952 Ext.define('Ext.util.MixedCollection', {
17953     extend: 'Ext.util.AbstractMixedCollection',
17954     mixins: {
17955         sortable: 'Ext.util.Sortable'
17956     },
17957
17958     constructor: function() {
17959         var me = this;
17960         me.callParent(arguments);
17961         me.addEvents('sort');
17962         me.mixins.sortable.initSortable.call(me);
17963     },
17964
17965     doSort: function(sorterFn) {
17966         this.sortBy(sorterFn);
17967     },
17968
17969     
17970     _sort : function(property, dir, fn){
17971         var me = this,
17972             i, len,
17973             dsc   = String(dir).toUpperCase() == 'DESC' ? -1 : 1,
17974
17975             
17976             c     = [],
17977             keys  = me.keys,
17978             items = me.items;
17979
17980         
17981         fn = fn || function(a, b) {
17982             return a - b;
17983         };
17984
17985         
17986         for(i = 0, len = items.length; i < len; i++){
17987             c[c.length] = {
17988                 key  : keys[i],
17989                 value: items[i],
17990                 index: i
17991             };
17992         }
17993
17994         
17995         Ext.Array.sort(c, function(a, b){
17996             var v = fn(a[property], b[property]) * dsc;
17997             if(v === 0){
17998                 v = (a.index < b.index ? -1 : 1);
17999             }
18000             return v;
18001         });
18002
18003         
18004         for(i = 0, len = c.length; i < len; i++){
18005             items[i] = c[i].value;
18006             keys[i]  = c[i].key;
18007         }
18008
18009         me.fireEvent('sort', me);
18010     },
18011
18012     
18013     sortBy: function(sorterFn) {
18014         var me     = this,
18015             items  = me.items,
18016             keys   = me.keys,
18017             length = items.length,
18018             temp   = [],
18019             i;
18020
18021         
18022         for (i = 0; i < length; i++) {
18023             temp[i] = {
18024                 key  : keys[i],
18025                 value: items[i],
18026                 index: i
18027             };
18028         }
18029
18030         Ext.Array.sort(temp, function(a, b) {
18031             var v = sorterFn(a.value, b.value);
18032             if (v === 0) {
18033                 v = (a.index < b.index ? -1 : 1);
18034             }
18035
18036             return v;
18037         });
18038
18039         
18040         for (i = 0; i < length; i++) {
18041             items[i] = temp[i].value;
18042             keys[i]  = temp[i].key;
18043         }
18044         
18045         me.fireEvent('sort', me, items, keys);
18046     },
18047
18048     
18049     reorder: function(mapping) {
18050         var me = this,
18051             items = me.items,
18052             index = 0,
18053             length = items.length,
18054             order = [],
18055             remaining = [],
18056             oldIndex;
18057
18058         me.suspendEvents();
18059
18060         
18061         for (oldIndex in mapping) {
18062             order[mapping[oldIndex]] = items[oldIndex];
18063         }
18064
18065         for (index = 0; index < length; index++) {
18066             if (mapping[index] == undefined) {
18067                 remaining.push(items[index]);
18068             }
18069         }
18070
18071         for (index = 0; index < length; index++) {
18072             if (order[index] == undefined) {
18073                 order[index] = remaining.shift();
18074             }
18075         }
18076
18077         me.clear();
18078         me.addAll(order);
18079
18080         me.resumeEvents();
18081         me.fireEvent('sort', me);
18082     },
18083
18084     
18085     sortByKey : function(dir, fn){
18086         this._sort('key', dir, fn || function(a, b){
18087             var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();
18088             return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
18089         });
18090     }
18091 });
18092
18093
18094 Ext.define('Ext.data.StoreManager', {
18095     extend: 'Ext.util.MixedCollection',
18096     alternateClassName: ['Ext.StoreMgr', 'Ext.data.StoreMgr', 'Ext.StoreManager'],
18097     singleton: true,
18098     uses: ['Ext.data.ArrayStore'],
18099     
18100     
18101
18102     
18103     register : function() {
18104         for (var i = 0, s; (s = arguments[i]); i++) {
18105             this.add(s);
18106         }
18107     },
18108
18109     
18110     unregister : function() {
18111         for (var i = 0, s; (s = arguments[i]); i++) {
18112             this.remove(this.lookup(s));
18113         }
18114     },
18115
18116     
18117     lookup : function(store) {
18118         
18119         if (Ext.isArray(store)) {
18120             var fields = ['field1'], 
18121                 expand = !Ext.isArray(store[0]),
18122                 data = store,
18123                 i,
18124                 len;
18125                 
18126             if(expand){
18127                 data = [];
18128                 for (i = 0, len = store.length; i < len; ++i) {
18129                     data.push([store[i]]);
18130                 }
18131             } else {
18132                 for(i = 2, len = store[0].length; i <= len; ++i){
18133                     fields.push('field' + i);
18134                 }
18135             }
18136             return Ext.create('Ext.data.ArrayStore', {
18137                 data  : data,
18138                 fields: fields,
18139                 autoDestroy: true,
18140                 autoCreated: true,
18141                 expanded: expand
18142             });
18143         }
18144         
18145         if (Ext.isString(store)) {
18146             
18147             return this.get(store);
18148         } else {
18149             
18150             return Ext.data.AbstractStore.create(store);
18151         }
18152     },
18153
18154     
18155     getKey : function(o) {
18156          return o.storeId;
18157     }
18158 }, function() {    
18159     
18160     Ext.regStore = function(name, config) {
18161         var store;
18162
18163         if (Ext.isObject(name)) {
18164             config = name;
18165         } else {
18166             config.storeId = name;
18167         }
18168
18169         if (config instanceof Ext.data.Store) {
18170             store = config;
18171         } else {
18172             store = Ext.create('Ext.data.Store', config);
18173         }
18174
18175         return Ext.data.StoreManager.register(store);
18176     };
18177
18178     
18179     Ext.getStore = function(name) {
18180         return Ext.data.StoreManager.lookup(name);
18181     };
18182 });
18183
18184
18185
18186 Ext.define('Ext.LoadMask', {
18187
18188     
18189
18190     mixins: {
18191         observable: 'Ext.util.Observable'
18192     },
18193
18194     requires: ['Ext.data.StoreManager'],
18195
18196     
18197
18198     
18199
18200     
18201     msg : 'Loading...',
18202     
18203     msgCls : Ext.baseCSSPrefix + 'mask-loading',
18204     
18205     
18206     useMsg: true,
18207
18208     
18209     disabled: false,
18210
18211     constructor : function(el, config) {
18212         var me = this;
18213
18214         if (el.isComponent) {
18215             me.bindComponent(el);
18216         } else {
18217             me.el = Ext.get(el);
18218         }
18219         Ext.apply(me, config);
18220
18221         me.addEvents('beforeshow', 'show', 'hide');
18222         if (me.store) {
18223             me.bindStore(me.store, true);
18224         }
18225         me.mixins.observable.constructor.call(me, config);
18226     },
18227
18228     bindComponent: function(comp) {
18229         var me = this,
18230             listeners = {
18231                 resize: me.onComponentResize,
18232                 scope: me
18233             };
18234
18235         if (comp.el) {
18236             me.onComponentRender(comp);
18237         } else {
18238             listeners.render = {
18239                 fn: me.onComponentRender,
18240                 scope: me,
18241                 single: true
18242             };
18243         }
18244         me.mon(comp, listeners);
18245     },
18246
18247     
18248     onComponentRender: function(comp) {
18249         this.el = comp.getContentTarget();
18250     },
18251
18252     
18253     onComponentResize: function(comp, w, h) {
18254         this.el.isMasked();
18255     },
18256
18257     
18258     bindStore : function(store, initial) {
18259         var me = this;
18260
18261         if (!initial && me.store) {
18262             me.mun(me.store, {
18263                 scope: me,
18264                 beforeload: me.onBeforeLoad,
18265                 load: me.onLoad,
18266                 exception: me.onLoad
18267             });
18268             if(!store) {
18269                 me.store = null;
18270             }
18271         }
18272         if (store) {
18273             store = Ext.data.StoreManager.lookup(store);
18274             me.mon(store, {
18275                 scope: me,
18276                 beforeload: me.onBeforeLoad,
18277                 load: me.onLoad,
18278                 exception: me.onLoad
18279             });
18280
18281         }
18282         me.store = store;
18283         if (store && store.isLoading()) {
18284             me.onBeforeLoad();
18285         }
18286     },
18287
18288     
18289     disable : function() {
18290         var me = this;
18291
18292        me.disabled = true;
18293        if (me.loading) {
18294            me.onLoad();
18295        }
18296     },
18297
18298     
18299     enable : function() {
18300         this.disabled = false;
18301     },
18302
18303     
18304     isDisabled : function() {
18305         return this.disabled;
18306     },
18307
18308     
18309     onLoad : function() {
18310         var me = this;
18311
18312         me.loading = false;
18313         me.el.unmask();
18314         me.fireEvent('hide', me, me.el, me.store);
18315     },
18316
18317     
18318     onBeforeLoad : function() {
18319         var me = this;
18320
18321         if (!me.disabled && !me.loading && me.fireEvent('beforeshow', me, me.el, me.store) !== false) {
18322             if (me.useMsg) {
18323                 me.el.mask(me.msg, me.msgCls, false);
18324             } else {
18325                 me.el.mask();
18326             }
18327             
18328             me.fireEvent('show', me, me.el, me.store);
18329             me.loading = true;
18330         }
18331     },
18332
18333     
18334     show: function() {
18335         this.onBeforeLoad();
18336     },
18337
18338     
18339     hide: function() {
18340         this.onLoad();
18341     },
18342
18343     
18344     destroy : function() {
18345         this.hide();
18346         this.clearListeners();
18347     }
18348 });
18349
18350
18351 Ext.define('Ext.ComponentLoader', {
18352
18353     
18354     
18355     extend: 'Ext.ElementLoader',
18356
18357     statics: {
18358         Renderer: {
18359             Data: function(loader, response, active){
18360                 var success = true;
18361                 try {
18362                     loader.getTarget().update(Ext.decode(response.responseText));
18363                 } catch (e) {
18364                     success = false;
18365                 }
18366                 return success;
18367             },
18368
18369             Component: function(loader, response, active){
18370                 var success = true,
18371                     target = loader.getTarget(),
18372                     items = [];
18373
18374                 if (!target.isContainer) {
18375                     Ext.Error.raise({
18376                         target: target,
18377                         msg: 'Components can only be loaded into a container'
18378                     });
18379                 }
18380
18381                 try {
18382                     items = Ext.decode(response.responseText);
18383                 } catch (e) {
18384                     success = false;
18385                 }
18386
18387                 if (success) {
18388                     if (active.removeAll) {
18389                         target.removeAll();
18390                     }
18391                     target.add(items);
18392                 }
18393                 return success;
18394             }
18395         }
18396     },
18397
18398     
18399
18400     
18401     target: null,
18402
18403     
18404     loadMask: false,
18405     
18406     
18407
18408     
18409     renderer: 'html',
18410
18411     
18412     setTarget: function(target){
18413         var me = this;
18414         
18415         if (Ext.isString(target)) {
18416             target = Ext.getCmp(target);
18417         }
18418
18419         if (me.target && me.target != target) {
18420             me.abort();
18421         }
18422         me.target = target;
18423     },
18424     
18425     
18426     removeMask: function(){
18427         this.target.setLoading(false);
18428     },
18429     
18430     
18431     addMask: function(mask){
18432         this.target.setLoading(mask);
18433     },
18434
18435     
18436     
18437     setOptions: function(active, options){
18438         active.removeAll = Ext.isDefined(options.removeAll) ? options.removeAll : this.removeAll;
18439     },
18440
18441     
18442     getRenderer: function(renderer){
18443         if (Ext.isFunction(renderer)) {
18444             return renderer;
18445         }
18446
18447         var renderers = this.statics().Renderer;
18448         switch (renderer) {
18449             case 'component':
18450                 return renderers.Component;
18451             case 'data':
18452                 return renderers.Data;
18453             default:
18454                 return Ext.ElementLoader.Renderer.Html;
18455         }
18456     }
18457 });
18458
18459
18460
18461 Ext.define('Ext.layout.component.Auto', {
18462
18463     
18464
18465     alias: 'layout.autocomponent',
18466
18467     extend: 'Ext.layout.component.Component',
18468
18469     
18470
18471     type: 'autocomponent',
18472
18473     onLayout : function(width, height) {
18474         this.setTargetSize(width, height);
18475     }
18476 });
18477
18478
18479 Ext.define('Ext.AbstractComponent', {
18480
18481     
18482
18483     mixins: {
18484         observable: 'Ext.util.Observable',
18485         animate: 'Ext.util.Animate',
18486         state: 'Ext.state.Stateful'
18487     },
18488
18489     requires: [
18490         'Ext.PluginManager',
18491         'Ext.ComponentManager',
18492         'Ext.core.Element',
18493         'Ext.core.DomHelper',
18494         'Ext.XTemplate',
18495         'Ext.ComponentQuery',
18496         'Ext.LoadMask',
18497         'Ext.ComponentLoader',
18498         'Ext.EventManager',
18499         'Ext.layout.Layout',
18500         'Ext.layout.component.Auto'
18501     ],
18502
18503     
18504     
18505     uses: [
18506         'Ext.ZIndexManager'
18507     ],
18508
18509     statics: {
18510         AUTO_ID: 1000
18511     },
18512
18513     
18514
18515     isComponent: true,
18516
18517     getAutoId: function() {
18518         return ++Ext.AbstractComponent.AUTO_ID;
18519     },
18520
18521     
18522
18523     
18524
18525     
18526
18527     
18528
18529     
18530     renderTpl: null,
18531
18532     
18533
18534     
18535
18536     
18537
18538     
18539
18540     
18541
18542     
18543
18544     
18545
18546     
18547     tplWriteMode: 'overwrite',
18548
18549     
18550     baseCls: Ext.baseCSSPrefix + 'component',
18551
18552     
18553
18554     
18555
18556     
18557
18558     
18559     disabledCls: Ext.baseCSSPrefix + 'item-disabled',
18560
18561     
18562     ui: 'default',
18563     
18564     
18565     uiCls: [],
18566     
18567     
18568
18569     
18570
18571     
18572
18573     
18574
18575     
18576
18577     
18578
18579     
18580     hidden: false,
18581
18582     
18583     disabled: false,
18584
18585     
18586
18587     
18588     draggable: false,
18589
18590     
18591     floating: false,
18592
18593     
18594     hideMode: 'display',
18595
18596     
18597
18598     
18599
18600     
18601     styleHtmlContent: false,
18602
18603     
18604     styleHtmlCls: Ext.baseCSSPrefix + 'html',
18605
18606     
18607     
18608     
18609     
18610
18611     
18612
18613      
18614      allowDomMove: true,
18615
18616      
18617      autoShow: false,
18618
18619     
18620      autoRender: false,
18621
18622      needsLayout: false,
18623
18624     
18625
18626     
18627     rendered: false,
18628
18629     weight: 0,
18630
18631     trimRe: /^\s+|\s+$/g,
18632     spacesRe: /\s+/,
18633     
18634     
18635          
18636     maskOnDisable: true,
18637
18638     constructor : function(config) {
18639         var me = this,
18640             i, len;
18641
18642         config = config || {};
18643         me.initialConfig = config;
18644         Ext.apply(me, config);
18645
18646         me.addEvents(
18647             
18648              'beforeactivate',
18649             
18650              'activate',
18651             
18652              'beforedeactivate',
18653             
18654              'deactivate',
18655             
18656              'added',
18657             
18658              'disable',
18659             
18660              'enable',
18661             
18662              'beforeshow',
18663             
18664              'show',
18665             
18666              'beforehide',
18667             
18668              'hide',
18669             
18670              'removed',
18671             
18672              'beforerender',
18673             
18674              'render',
18675             
18676              'afterrender',
18677             
18678              'beforedestroy',
18679             
18680              'destroy',
18681             
18682              'resize',
18683             
18684              'move'
18685         );
18686
18687         me.getId();
18688
18689         me.mons = [];
18690         me.additionalCls = [];
18691         me.renderData = me.renderData || {};
18692         me.renderSelectors = me.renderSelectors || {};
18693
18694         if (me.plugins) {
18695             me.plugins = [].concat(me.plugins);
18696             for (i = 0, len = me.plugins.length; i < len; i++) {
18697                 me.plugins[i] = me.constructPlugin(me.plugins[i]);
18698             }
18699         }
18700         
18701         me.initComponent();
18702
18703         
18704         Ext.ComponentManager.register(me);
18705
18706         
18707         me.mixins.observable.constructor.call(me);
18708         me.mixins.state.constructor.call(me, config);
18709
18710         
18711         if (me.plugins) {
18712             me.plugins = [].concat(me.plugins);
18713             for (i = 0, len = me.plugins.length; i < len; i++) {
18714                 me.plugins[i] = me.initPlugin(me.plugins[i]);
18715             }
18716         }
18717
18718         me.loader = me.getLoader();
18719
18720         if (me.renderTo) {
18721             me.render(me.renderTo);
18722             
18723             
18724             
18725         }
18726
18727         if (me.autoShow) {
18728             me.show();
18729         }
18730         
18731         if (Ext.isDefined(me.disabledClass)) {
18732             if (Ext.isDefined(Ext.global.console)) {
18733                 Ext.global.console.warn('Ext.Component: disabledClass has been deprecated. Please use disabledCls.');
18734             }
18735             me.disabledCls = me.disabledClass;
18736             delete me.disabledClass;
18737         }
18738     },
18739
18740     initComponent: Ext.emptyFn,
18741
18742     show: Ext.emptyFn,
18743
18744     animate: function(animObj) {
18745         var me = this,
18746             to;
18747
18748         animObj = animObj || {};
18749         to = animObj.to || {};
18750
18751         if (Ext.fx.Manager.hasFxBlock(me.id)) {
18752             return me;
18753         }
18754         
18755         if (!animObj.dynamic && (to.height || to.width)) {
18756             var curWidth = me.getWidth(),
18757                 w = curWidth,
18758                 curHeight = me.getHeight(),
18759                 h = curHeight,
18760                 needsResize = false;
18761
18762             if (to.height && to.height > curHeight) {
18763                 h = to.height;
18764                 needsResize = true;
18765             }
18766             if (to.width && to.width > curWidth) {
18767                 w = to.width;
18768                 needsResize = true;
18769             }
18770
18771             
18772             
18773             
18774             if (needsResize) {
18775                 var clearWidth = !Ext.isNumber(me.width),
18776                     clearHeight = !Ext.isNumber(me.height);
18777
18778                 me.componentLayout.childrenChanged = true;
18779                 me.setSize(w, h, me.ownerCt);
18780                 me.el.setSize(curWidth, curHeight);
18781                 if (clearWidth) {
18782                     delete me.width;
18783                 }
18784                 if (clearHeight) {
18785                     delete me.height;
18786                 }
18787             }
18788         }
18789         return me.mixins.animate.animate.apply(me, arguments);
18790     },
18791
18792     
18793     findLayoutController: function() {
18794         return this.findParentBy(function(c) {
18795             
18796             
18797             return !c.ownerCt || (c.layout.layoutBusy && !c.ownerCt.layout.layoutBusy);
18798         });
18799     },
18800
18801     onShow : function() {
18802         
18803         var needsLayout = this.needsLayout;
18804         if (Ext.isObject(needsLayout)) {
18805             this.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
18806         }
18807     },
18808
18809     constructPlugin: function(plugin) {
18810         if (plugin.ptype && typeof plugin.init != 'function') {
18811             plugin.cmp = this;
18812             plugin = Ext.PluginManager.create(plugin);
18813         }
18814         else if (typeof plugin == 'string') {
18815             plugin = Ext.PluginManager.create({
18816                 ptype: plugin,
18817                 cmp: this
18818             });
18819         }
18820         return plugin;
18821     },
18822
18823     
18824     initPlugin : function(plugin) {
18825         plugin.init(this);
18826
18827         return plugin;
18828     },
18829
18830     
18831     doAutoRender: function() {
18832         var me = this;
18833         if (me.floating) {
18834             me.render(document.body);
18835         } else {
18836             me.render(Ext.isBoolean(me.autoRender) ? Ext.getBody() : me.autoRender);
18837         }
18838     },
18839
18840     
18841     render : function(container, position) {
18842         var me = this;
18843
18844         if (!me.rendered && me.fireEvent('beforerender', me) !== false) {
18845             
18846             
18847             if (me.el) {
18848                 me.el = Ext.get(me.el);
18849             }
18850
18851             
18852             if (me.floating) {
18853                 me.onFloatRender();
18854             }
18855
18856             container = me.initContainer(container);
18857
18858             me.onRender(container, position);
18859
18860             
18861             
18862             me.el.setVisibilityMode(Ext.core.Element[me.hideMode.toUpperCase()]);
18863
18864             if (me.overCls) {
18865                 me.el.hover(me.addOverCls, me.removeOverCls, me);
18866             }
18867
18868             me.fireEvent('render', me);
18869
18870             me.initContent();
18871
18872             me.afterRender(container);
18873             me.fireEvent('afterrender', me);
18874
18875             me.initEvents();
18876
18877             if (me.hidden) {
18878                 
18879                 
18880                 
18881                 me.el.hide();
18882             }
18883
18884             if (me.disabled) {
18885                 
18886                 me.disable(true);
18887             }
18888         }
18889         return me;
18890     },
18891
18892     
18893     onRender : function(container, position) {
18894         var me = this,
18895             el = me.el,
18896             cls = me.initCls(),
18897             styles = me.initStyles(),
18898             renderTpl, renderData, i;
18899
18900         position = me.getInsertPosition(position);
18901
18902         if (!el) {
18903             if (position) {
18904                 el = Ext.core.DomHelper.insertBefore(position, me.getElConfig(), true);
18905             }
18906             else {
18907                 el = Ext.core.DomHelper.append(container, me.getElConfig(), true);
18908             }
18909         }
18910         else if (me.allowDomMove !== false) {
18911             if (position) {
18912                 container.dom.insertBefore(el.dom, position);
18913             } else {
18914                 container.dom.appendChild(el.dom);
18915             }
18916         }
18917
18918         if (Ext.scopeResetCSS && !me.ownerCt) {
18919             
18920             if (el.dom == Ext.getBody().dom) {
18921                 el.parent().addCls(Ext.baseCSSPrefix + 'reset');
18922             }
18923             else {
18924                 
18925                 me.resetEl = el.wrap({
18926                     cls: Ext.baseCSSPrefix + 'reset'
18927                 });
18928             }
18929         }
18930
18931         el.addCls(cls);
18932         el.setStyle(styles);
18933
18934         
18935         
18936         
18937         
18938         
18939         
18940         
18941         
18942         
18943         
18944
18945         me.el = el;
18946         
18947         me.rendered = true;
18948         me.addUIToElement(true);
18949         
18950         for (i = 0; i < me.uiCls.length; i++) {
18951             me.addUIClsToElement(me.uiCls[i], true);
18952         }
18953         me.rendered = false;
18954         me.initFrame();
18955
18956         renderTpl = me.initRenderTpl();
18957         if (renderTpl) {
18958             renderData = me.initRenderData();
18959             renderTpl.append(me.getTargetEl(), renderData);
18960         }
18961
18962         me.applyRenderSelectors();
18963         
18964         me.rendered = true;
18965         
18966         me.setUI(me.ui);
18967     },
18968
18969     
18970     afterRender : function() {
18971         var me = this,
18972             pos,
18973             xy;
18974
18975         me.getComponentLayout();
18976
18977         
18978         if (!me.ownerCt || (me.height || me.width)) {
18979             me.setSize(me.width, me.height);
18980         }
18981
18982         
18983         
18984         if (me.floating && (me.x === undefined || me.y === undefined)) {
18985             if (me.floatParent) {
18986                 xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c');
18987                 pos = me.floatParent.getTargetEl().translatePoints(xy[0], xy[1]);
18988             } else {
18989                 xy = me.el.getAlignToXY(me.container, 'c-c');
18990                 pos = me.container.translatePoints(xy[0], xy[1]);
18991             }
18992             me.x = me.x === undefined ? pos.left: me.x;
18993             me.y = me.y === undefined ? pos.top: me.y;
18994         }
18995
18996         if (Ext.isDefined(me.x) || Ext.isDefined(me.y)) {
18997             me.setPosition(me.x, me.y);
18998         }
18999
19000         if (me.styleHtmlContent) {
19001             me.getTargetEl().addCls(me.styleHtmlCls);
19002         }
19003     },
19004
19005     frameCls: Ext.baseCSSPrefix + 'frame',
19006
19007     frameTpl: [
19008         '<tpl if="top">',
19009             '<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>',
19010                 '<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>',
19011                     '<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>',
19012                 '<tpl if="right"></div></tpl>',
19013             '<tpl if="left"></div></tpl>',
19014         '</tpl>',
19015         '<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>',
19016             '<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>',
19017                 '<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>',
19018             '<tpl if="right"></div></tpl>',
19019         '<tpl if="left"></div></tpl>',
19020         '<tpl if="bottom">',
19021             '<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>',
19022                 '<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>',
19023                     '<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>',
19024                 '<tpl if="right"></div></tpl>',
19025             '<tpl if="left"></div></tpl>',
19026         '</tpl>'
19027     ],
19028
19029     frameTableTpl: [
19030         '<table><tbody>',
19031             '<tpl if="top">',
19032                 '<tr>',
19033                     '<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>',
19034                     '<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>',
19035                     '<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>',
19036                 '</tr>',
19037             '</tpl>',
19038             '<tr>',
19039                 '<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>',
19040                 '<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>',
19041                 '<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>',
19042             '</tr>',
19043             '<tpl if="bottom">',
19044                 '<tr>',
19045                     '<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>',
19046                     '<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>',
19047                     '<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>',
19048                 '</tr>',
19049             '</tpl>',
19050         '</tbody></table>'
19051     ],
19052     
19053     
19054     initFrame : function() {
19055         if (Ext.supports.CSS3BorderRadius) {
19056             return false;
19057         }
19058         
19059         var me = this,
19060             frameInfo = me.getFrameInfo(),
19061             frameWidth = frameInfo.width,
19062             frameTpl = me.getFrameTpl(frameInfo.table);
19063                         
19064         if (me.frame) {
19065             
19066             frameTpl.insertFirst(me.el, Ext.apply({}, {
19067                 ui:         me.ui,
19068                 uiCls:      me.uiCls,
19069                 frameCls:   me.frameCls,
19070                 baseCls:    me.baseCls,
19071                 frameWidth: frameWidth,
19072                 top:        !!frameInfo.top,
19073                 left:       !!frameInfo.left,
19074                 right:      !!frameInfo.right,
19075                 bottom:     !!frameInfo.bottom
19076             }, me.getFramePositions(frameInfo)));
19077
19078             
19079             me.frameBody = me.el.down('.' + me.frameCls + '-mc');
19080             
19081             
19082             Ext.apply(me.renderSelectors, {
19083                 frameTL: '.' + me.baseCls + '-tl',
19084                 frameTC: '.' + me.baseCls + '-tc',
19085                 frameTR: '.' + me.baseCls + '-tr',
19086                 frameML: '.' + me.baseCls + '-ml',
19087                 frameMC: '.' + me.baseCls + '-mc',
19088                 frameMR: '.' + me.baseCls + '-mr',
19089                 frameBL: '.' + me.baseCls + '-bl',
19090                 frameBC: '.' + me.baseCls + '-bc',
19091                 frameBR: '.' + me.baseCls + '-br'
19092             });
19093         }
19094     },
19095     
19096     updateFrame: function() {
19097         if (Ext.supports.CSS3BorderRadius) {
19098             return false;
19099         }
19100         
19101         var me = this,
19102             wasTable = this.frameSize && this.frameSize.table,
19103             oldFrameTL = this.frameTL,
19104             oldFrameBL = this.frameBL,
19105             oldFrameML = this.frameML,
19106             oldFrameMC = this.frameMC,
19107             newMCClassName;
19108         
19109         this.initFrame();
19110         
19111         if (oldFrameMC) {
19112             if (me.frame) {                
19113                 
19114                 delete me.frameTL;
19115                 delete me.frameTC;
19116                 delete me.frameTR;
19117                 delete me.frameML;
19118                 delete me.frameMC;
19119                 delete me.frameMR;
19120                 delete me.frameBL;
19121                 delete me.frameBC;
19122                 delete me.frameBR;    
19123                 this.applyRenderSelectors();
19124                 
19125                 
19126                 newMCClassName = this.frameMC.dom.className;
19127                 
19128                 
19129                 oldFrameMC.insertAfter(this.frameMC);
19130                 this.frameMC.remove();
19131                 
19132                 
19133                 this.frameBody = this.frameMC = oldFrameMC;
19134                 
19135                 
19136                 oldFrameMC.dom.className = newMCClassName;
19137                 
19138                 
19139                 if (wasTable) {
19140                     me.el.query('> table')[1].remove();
19141                 }                                
19142                 else {
19143                     if (oldFrameTL) {
19144                         oldFrameTL.remove();
19145                     }
19146                     if (oldFrameBL) {
19147                         oldFrameBL.remove();
19148                     }
19149                     oldFrameML.remove();
19150                 }
19151             }
19152             else {
19153                 
19154                 
19155             }
19156         }
19157         else if (me.frame) {
19158             this.applyRenderSelectors();
19159         }
19160     },
19161     
19162     getFrameInfo: function() {
19163         if (Ext.supports.CSS3BorderRadius) {
19164             return false;
19165         }
19166         
19167         var me = this,
19168             left = me.el.getStyle('background-position-x'),
19169             top = me.el.getStyle('background-position-y'),
19170             info, frameInfo = false, max;
19171
19172         
19173         
19174         if (!left && !top) {
19175             info = me.el.getStyle('background-position').split(' ');
19176             left = info[0];
19177             top = info[1];
19178         }
19179         
19180         
19181         
19182         
19183         if (parseInt(left, 10) >= 1000000 && parseInt(top, 10) >= 1000000) {
19184             max = Math.max;
19185             
19186             frameInfo = {
19187                 
19188                 table: left.substr(0, 3) == '110',
19189                 
19190                 
19191                 vertical: top.substr(0, 3) == '110',
19192                 
19193                 
19194                 top:    max(left.substr(3, 2), left.substr(5, 2)),
19195                 right:  max(left.substr(5, 2), top.substr(3, 2)),
19196                 bottom: max(top.substr(3, 2), top.substr(5, 2)),
19197                 left:   max(top.substr(5, 2), left.substr(3, 2))
19198             };
19199             
19200             frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left);
19201
19202             
19203             me.el.setStyle('background-image', 'none');
19204         }        
19205         
19206         
19207         
19208         if (me.frame === true && !frameInfo) {
19209             Ext.Error.raise("You have set frame: true explicity on this component while it doesn't have any " +
19210                             "framing defined in the CSS template. In this case IE can't figure out what sizes " +
19211                             "to use and thus framing on this component will be disabled.");
19212         }
19213         
19214         me.frame = me.frame || !!frameInfo;
19215         me.frameSize = frameInfo || false;
19216         
19217         return frameInfo;
19218     },
19219     
19220     getFramePositions: function(frameInfo) {
19221         var me = this,
19222             frameWidth = frameInfo.width,
19223             dock = me.dock,
19224             positions, tc, bc, ml, mr;
19225             
19226         if (frameInfo.vertical) {
19227             tc = '0 -' + (frameWidth * 0) + 'px';
19228             bc = '0 -' + (frameWidth * 1) + 'px';
19229             
19230             if (dock && dock == "right") {
19231                 tc = 'right -' + (frameWidth * 0) + 'px';
19232                 bc = 'right -' + (frameWidth * 1) + 'px';
19233             }
19234             
19235             positions = {
19236                 tl: '0 -' + (frameWidth * 0) + 'px',
19237                 tr: '0 -' + (frameWidth * 1) + 'px',
19238                 bl: '0 -' + (frameWidth * 2) + 'px',
19239                 br: '0 -' + (frameWidth * 3) + 'px',
19240
19241                 ml: '-' + (frameWidth * 1) + 'px 0',
19242                 mr: 'right 0',
19243
19244                 tc: tc,
19245                 bc: bc
19246             };
19247         } else {
19248             ml = '-' + (frameWidth * 0) + 'px 0';
19249             mr = 'right 0';
19250             
19251             if (dock && dock == "bottom") {
19252                 ml = 'left bottom';
19253                 mr = 'right bottom';
19254             }
19255             
19256             positions = {
19257                 tl: '0 -' + (frameWidth * 2) + 'px',
19258                 tr: 'right -' + (frameWidth * 3) + 'px',
19259                 bl: '0 -' + (frameWidth * 4) + 'px',
19260                 br: 'right -' + (frameWidth * 5) + 'px',
19261
19262                 ml: ml,
19263                 mr: mr,
19264
19265                 tc: '0 -' + (frameWidth * 0) + 'px',
19266                 bc: '0 -' + (frameWidth * 1) + 'px'
19267             };
19268         }
19269         
19270         return positions;
19271     },
19272     
19273     
19274     getFrameTpl : function(table) {
19275         return table ? this.getTpl('frameTableTpl') : this.getTpl('frameTpl');
19276     },
19277
19278     
19279     initCls: function() {
19280         var me = this,
19281             cls = [];
19282
19283         cls.push(me.baseCls);
19284
19285         if (Ext.isDefined(me.cmpCls)) {
19286             if (Ext.isDefined(Ext.global.console)) {
19287                 Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.');
19288             }
19289             me.componentCls = me.cmpCls;
19290             delete me.cmpCls;
19291         }
19292
19293         if (me.componentCls) {
19294             cls.push(me.componentCls);
19295         } else {
19296             me.componentCls = me.baseCls;
19297         }
19298         if (me.cls) {
19299             cls.push(me.cls);
19300             delete me.cls;
19301         }
19302
19303         return cls.concat(me.additionalCls);
19304     },
19305     
19306     
19307     setUI: function(ui) {
19308         var me = this,
19309             oldUICls = Ext.Array.clone(me.uiCls),
19310             newUICls = [],
19311             cls,
19312             i;
19313         
19314         
19315         for (i = 0; i < oldUICls.length; i++) {
19316             cls = oldUICls[i];
19317             
19318             me.removeClsWithUI(cls);
19319             newUICls.push(cls);
19320         }
19321         
19322         
19323         me.removeUIFromElement();
19324         
19325         
19326         me.ui = ui;
19327         
19328         
19329         me.addUIToElement();
19330         
19331         
19332         for (i = 0; i < newUICls.length; i++) {
19333             cls = newUICls[i];
19334             
19335             me.addClsWithUI(cls);
19336         }
19337     },
19338     
19339     
19340     addClsWithUI: function(cls) {
19341         var me = this,
19342             i;
19343         
19344         if (!Ext.isArray(cls)) {
19345             cls = [cls];
19346         }
19347         
19348         for (i = 0; i < cls.length; i++) {
19349             if (cls[i] && !me.hasUICls(cls[i])) {
19350                 me.uiCls = Ext.Array.clone(me.uiCls);
19351                 me.uiCls.push(cls[i]);
19352                 me.addUIClsToElement(cls[i]);
19353             }
19354         }
19355     },
19356     
19357     
19358     removeClsWithUI: function(cls) {
19359         var me = this,
19360             i;
19361         
19362         if (!Ext.isArray(cls)) {
19363             cls = [cls];
19364         }
19365         
19366         for (i = 0; i < cls.length; i++) {
19367             if (cls[i] && me.hasUICls(cls[i])) {
19368                 me.uiCls = Ext.Array.remove(me.uiCls, cls[i]);
19369                 me.removeUIClsFromElement(cls[i]);
19370             }
19371         }
19372     },
19373     
19374     
19375     hasUICls: function(cls) {
19376         var me = this,
19377             uiCls = me.uiCls || [];
19378         
19379         return Ext.Array.contains(uiCls, cls);
19380     },
19381     
19382     
19383     addUIClsToElement: function(cls, force) {
19384         var me = this;
19385         
19386         me.addCls(Ext.baseCSSPrefix + cls);
19387         me.addCls(me.baseCls + '-' + cls);
19388         me.addCls(me.baseCls + '-' + me.ui + '-' + cls);
19389         
19390         if (!force && me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
19391             
19392             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
19393                 i, el;
19394             
19395             
19396             for (i = 0; i < els.length; i++) {
19397                 el = me['frame' + els[i].toUpperCase()];
19398                 
19399                 if (el && el.dom) {
19400                     el.addCls(me.baseCls + '-' + me.ui + '-' + els[i]);
19401                     el.addCls(me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]);
19402                 }
19403             }
19404         }
19405     },
19406     
19407     
19408     removeUIClsFromElement: function(cls, force) {
19409         var me = this;
19410         
19411         me.removeCls(Ext.baseCSSPrefix + cls);
19412         me.removeCls(me.baseCls + '-' + cls);
19413         me.removeCls(me.baseCls + '-' + me.ui + '-' + cls);
19414         
19415         if (!force &&me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
19416             
19417             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
19418                 i, el;
19419             
19420             
19421             for (i = 0; i < els.length; i++) {
19422                 el = me['frame' + els[i].toUpperCase()];
19423                 if (el && el.dom) {
19424                     el.removeCls(me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]);
19425                 }
19426             }
19427         }
19428     },
19429     
19430     
19431     addUIToElement: function(force) {
19432         var me = this;
19433         
19434         me.addCls(me.baseCls + '-' + me.ui);
19435         
19436         if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
19437             
19438             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
19439                 i, el;
19440             
19441             
19442             for (i = 0; i < els.length; i++) {
19443                 el = me['frame' + els[i].toUpperCase()];
19444                 
19445                 if (el) {
19446                     el.addCls(me.baseCls + '-' + me.ui + '-' + els[i]);
19447                 }
19448             }
19449         }
19450     },
19451     
19452     
19453     removeUIFromElement: function() {
19454         var me = this;
19455         
19456         me.removeCls(me.baseCls + '-' + me.ui);
19457         
19458         if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
19459             
19460             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
19461                 i, el;
19462             
19463             
19464             for (i = 0; i < els.length; i++) {
19465                 el = me['frame' + els[i].toUpperCase()];
19466                 if (el) {
19467                     el.removeCls(me.baseCls + '-' + me.ui + '-' + els[i]);
19468                 }
19469             }
19470         }
19471     },
19472     
19473     getElConfig : function() {
19474         var result = this.autoEl || {tag: 'div'};
19475         result.id = this.id;
19476         return result;
19477     },
19478
19479     
19480     getInsertPosition: function(position) {
19481         
19482         if (position !== undefined) {
19483             if (Ext.isNumber(position)) {
19484                 position = this.container.dom.childNodes[position];
19485             }
19486             else {
19487                 position = Ext.getDom(position);
19488             }
19489         }
19490
19491         return position;
19492     },
19493
19494     
19495     initContainer: function(container) {
19496         var me = this;
19497
19498         
19499         
19500         
19501         if (!container && me.el) {
19502             container = me.el.dom.parentNode;
19503             me.allowDomMove = false;
19504         }
19505
19506         me.container = Ext.get(container);
19507
19508         if (me.ctCls) {
19509             me.container.addCls(me.ctCls);
19510         }
19511
19512         return me.container;
19513     },
19514
19515     
19516     initRenderData: function() {
19517         var me = this;
19518
19519         return Ext.applyIf(me.renderData, {
19520             ui: me.ui,
19521             uiCls: me.uiCls,
19522             baseCls: me.baseCls,
19523             componentCls: me.componentCls,
19524             frame: me.frame
19525         });
19526     },
19527
19528     
19529     getTpl: function(name) {
19530         var prototype = this.self.prototype,
19531             ownerPrototype;
19532
19533         if (this.hasOwnProperty(name)) {
19534             if (!(this[name] instanceof Ext.XTemplate)) {
19535                 this[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', this[name]);
19536             }
19537
19538             return this[name];
19539         }
19540
19541         if (!(prototype[name] instanceof Ext.XTemplate)) {
19542             ownerPrototype = prototype;
19543
19544             do {
19545                 if (ownerPrototype.hasOwnProperty(name)) {
19546                     ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', ownerPrototype[name]);
19547                     break;
19548                 }
19549
19550                 ownerPrototype = ownerPrototype.superclass;
19551             } while (ownerPrototype);
19552         }
19553
19554         return prototype[name];
19555     },
19556
19557     
19558     initRenderTpl: function() {
19559         return this.getTpl('renderTpl');
19560     },
19561
19562     
19563     initStyles: function() {
19564         var style = {},
19565             me = this,
19566             Element = Ext.core.Element;
19567
19568         if (Ext.isString(me.style)) {
19569             style = Element.parseStyles(me.style);
19570         } else {
19571             style = Ext.apply({}, me.style);
19572         }
19573
19574         
19575         
19576         if (me.padding !== undefined) {
19577             style.padding = Element.unitizeBox((me.padding === true) ? 5 : me.padding);
19578         }
19579
19580         if (me.margin !== undefined) {
19581             style.margin = Element.unitizeBox((me.margin === true) ? 5 : me.margin);
19582         }
19583
19584         delete me.style;
19585         return style;
19586     },
19587
19588     
19589     initContent: function() {
19590         var me = this,
19591             target = me.getTargetEl(),
19592             contentEl,
19593             pre;
19594
19595         if (me.html) {
19596             target.update(Ext.core.DomHelper.markup(me.html));
19597             delete me.html;
19598         }
19599
19600         if (me.contentEl) {
19601             contentEl = Ext.get(me.contentEl);
19602             pre = Ext.baseCSSPrefix;
19603             contentEl.removeCls([pre + 'hidden', pre + 'hide-display', pre + 'hide-offsets', pre + 'hide-nosize']);
19604             target.appendChild(contentEl.dom);
19605         }
19606
19607         if (me.tpl) {
19608             
19609             if (!me.tpl.isTemplate) {
19610                 me.tpl = Ext.create('Ext.XTemplate', me.tpl);
19611             }
19612
19613             if (me.data) {
19614                 me.tpl[me.tplWriteMode](target, me.data);
19615                 delete me.data;
19616             }
19617         }
19618     },
19619
19620     
19621     initEvents : function() {
19622         var me = this,
19623             afterRenderEvents = me.afterRenderEvents,
19624             property, listeners;
19625         if (afterRenderEvents) {
19626             for (property in afterRenderEvents) {
19627                 if (afterRenderEvents.hasOwnProperty(property)) {
19628                     listeners = afterRenderEvents[property];
19629                     if (me[property] && me[property].on) {
19630                         me.mon(me[property], listeners);
19631                     }
19632                 }
19633             }
19634         }
19635     },
19636
19637     
19638     applyRenderSelectors: function() {
19639         var selectors = this.renderSelectors || {},
19640             el = this.el.dom,
19641             selector;
19642
19643         for (selector in selectors) {
19644             if (selectors.hasOwnProperty(selector) && selectors[selector]) {
19645                 this[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], el));
19646             }
19647         }
19648     },
19649
19650     
19651     is: function(selector) {
19652         return Ext.ComponentQuery.is(this, selector);
19653     },
19654
19655     
19656     up: function(selector) {
19657         var result = this.ownerCt;
19658         if (selector) {
19659             for (; result; result = result.ownerCt) {
19660                 if (Ext.ComponentQuery.is(result, selector)) {
19661                     return result;
19662                 }
19663             }
19664         }
19665         return result;
19666     },
19667
19668     
19669     nextSibling: function(selector) {
19670         var o = this.ownerCt, it, last, idx, c;
19671         if (o) {
19672             it = o.items;
19673             idx = it.indexOf(this) + 1;
19674             if (idx) {
19675                 if (selector) {
19676                     for (last = it.getCount(); idx < last; idx++) {
19677                         if ((c = it.getAt(idx)).is(selector)) {
19678                             return c;
19679                         }
19680                     }
19681                 } else {
19682                     if (idx < it.getCount()) {
19683                         return it.getAt(idx);
19684                     }
19685                 }
19686             }
19687         }
19688         return null;
19689     },
19690
19691     
19692     previousSibling: function(selector) {
19693         var o = this.ownerCt, it, idx, c;
19694         if (o) {
19695             it = o.items;
19696             idx = it.indexOf(this);
19697             if (idx != -1) {
19698                 if (selector) {
19699                     for (--idx; idx >= 0; idx--) {
19700                         if ((c = it.getAt(idx)).is(selector)) {
19701                             return c;
19702                         }
19703                     }
19704                 } else {
19705                     if (idx) {
19706                         return it.getAt(--idx);
19707                     }
19708                 }
19709             }
19710         }
19711         return null;
19712     },
19713
19714     
19715     previousNode: function(selector, includeSelf) {
19716         var node = this,
19717             result,
19718             it, len, i;
19719
19720         
19721         if (includeSelf && node.is(selector)) {
19722             return node;
19723         }
19724
19725         result = this.prev(selector);
19726         if (result) {
19727             return result;
19728         }
19729
19730         if (node.ownerCt) {
19731             for (it = node.ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
19732                 if (it[i].query) {
19733                     result = it[i].query(selector);
19734                     result = result[result.length - 1];
19735                     if (result) {
19736                         return result;
19737                     }
19738                 }
19739             }
19740             return node.ownerCt.previousNode(selector, true);
19741         }
19742     },
19743
19744     
19745     nextNode: function(selector, includeSelf) {
19746         var node = this,
19747             result,
19748             it, len, i;
19749
19750         
19751         if (includeSelf && node.is(selector)) {
19752             return node;
19753         }
19754
19755         result = this.next(selector);
19756         if (result) {
19757             return result;
19758         }
19759
19760         if (node.ownerCt) {
19761             for (it = node.ownerCt.items, i = it.indexOf(node) + 1, it = it.items, len = it.length; i < len; i++) {
19762                 if (it[i].down) {
19763                     result = it[i].down(selector);
19764                     if (result) {
19765                         return result;
19766                     }
19767                 }
19768             }
19769             return node.ownerCt.nextNode(selector);
19770         }
19771     },
19772
19773     
19774     getId : function() {
19775         return this.id || (this.id = 'ext-comp-' + (this.getAutoId()));
19776     },
19777
19778     getItemId : function() {
19779         return this.itemId || this.id;
19780     },
19781
19782     
19783     getEl : function() {
19784         return this.el;
19785     },
19786
19787     
19788     getTargetEl: function() {
19789         return this.frameBody || this.el;
19790     },
19791
19792     
19793     isXType: function(xtype, shallow) {
19794         
19795         if (Ext.isFunction(xtype)) {
19796             xtype = xtype.xtype;
19797             
19798         } else if (Ext.isObject(xtype)) {
19799             xtype = xtype.statics().xtype;
19800             
19801         }
19802
19803         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1: this.self.xtype == xtype;
19804     },
19805
19806     
19807     getXTypes: function() {
19808         var self = this.self,
19809             xtypes      = [],
19810             parentPrototype  = this,
19811             xtype;
19812
19813         if (!self.xtypes) {
19814             while (parentPrototype && Ext.getClass(parentPrototype)) {
19815                 xtype = Ext.getClass(parentPrototype).xtype;
19816
19817                 if (xtype !== undefined) {
19818                     xtypes.unshift(xtype);
19819                 }
19820
19821                 parentPrototype = parentPrototype.superclass;
19822             }
19823
19824             self.xtypeChain = xtypes;
19825             self.xtypes = xtypes.join('/');
19826         }
19827
19828         return self.xtypes;
19829     },
19830
19831     
19832     update : function(htmlOrData, loadScripts, cb) {
19833         var me = this;
19834
19835         if (me.tpl && !Ext.isString(htmlOrData)) {
19836             me.data = htmlOrData;
19837             if (me.rendered) {
19838                 me.tpl[me.tplWriteMode](me.getTargetEl(), htmlOrData || {});
19839             }
19840         } else {
19841             me.html = Ext.isObject(htmlOrData) ? Ext.core.DomHelper.markup(htmlOrData) : htmlOrData;
19842             if (me.rendered) {
19843                 me.getTargetEl().update(me.html, loadScripts, cb);
19844             }
19845         }
19846
19847         if (me.rendered) {
19848             me.doComponentLayout();
19849         }
19850     },
19851
19852     
19853     setVisible : function(visible) {
19854         return this[visible ? 'show': 'hide']();
19855     },
19856
19857     
19858     isVisible: function(deep) {
19859         var me = this,
19860             child = me,
19861             visible = !me.hidden,
19862             ancestor = me.ownerCt;
19863
19864         
19865         me.hiddenAncestor = false;
19866         if (me.destroyed) {
19867             return false;
19868         }
19869
19870         if (deep && visible && me.rendered && ancestor) {
19871             while (ancestor) {
19872                 
19873                 
19874                 
19875                 
19876                 if (ancestor.hidden || (ancestor.collapsed &&
19877                         !(ancestor.getDockedItems && Ext.Array.contains(ancestor.getDockedItems(), child)))) {
19878                     
19879                     me.hiddenAncestor = ancestor;
19880                     visible = false;
19881                     break;
19882                 }
19883                 child = ancestor;
19884                 ancestor = ancestor.ownerCt;
19885             }
19886         }
19887         return visible;
19888     },
19889
19890     
19891     enable: function(silent) {
19892         var me = this;
19893
19894         if (me.rendered) {
19895             me.el.removeCls(me.disabledCls);
19896             me.el.dom.disabled = false;
19897             me.onEnable();
19898         }
19899
19900         me.disabled = false;
19901
19902         if (silent !== true) {
19903             me.fireEvent('enable', me);
19904         }
19905
19906         return me;
19907     },
19908
19909     
19910     disable: function(silent) {
19911         var me = this;
19912
19913         if (me.rendered) {
19914             me.el.addCls(me.disabledCls);
19915             me.el.dom.disabled = true;
19916             me.onDisable();
19917         }
19918
19919         me.disabled = true;
19920
19921         if (silent !== true) {
19922             me.fireEvent('disable', me);
19923         }
19924
19925         return me;
19926     },
19927     
19928     
19929     onEnable: function() {
19930         if (this.maskOnDisable) {
19931             this.el.unmask();
19932         }        
19933     },
19934
19935     
19936     onDisable : function() {
19937         if (this.maskOnDisable) {
19938             this.el.mask();
19939         }
19940     },
19941     
19942     
19943     isDisabled : function() {
19944         return this.disabled;
19945     },
19946
19947     
19948     setDisabled : function(disabled) {
19949         return this[disabled ? 'disable': 'enable']();
19950     },
19951
19952     
19953     isHidden : function() {
19954         return this.hidden;
19955     },
19956
19957     
19958     addCls : function(className) {
19959         var me = this;
19960         if (!className) {
19961             return me;
19962         }
19963         if (!Ext.isArray(className)){
19964             className = className.replace(me.trimRe, '').split(me.spacesRe);
19965         }
19966         if (me.rendered) {
19967             me.el.addCls(className);
19968         }
19969         else {
19970             me.additionalCls = Ext.Array.unique(me.additionalCls.concat(className));
19971         }
19972         return me;
19973     },
19974
19975     
19976     addClass : function() {
19977         return this.addCls.apply(this, arguments);
19978     },
19979
19980     
19981     removeCls : function(className) {
19982         var me = this;
19983
19984         if (!className) {
19985             return me;
19986         }
19987         if (!Ext.isArray(className)){
19988             className = className.replace(me.trimRe, '').split(me.spacesRe);
19989         }
19990         if (me.rendered) {
19991             me.el.removeCls(className);
19992         }
19993         else if (me.additionalCls.length) {
19994             Ext.each(className, function(cls) {
19995                 Ext.Array.remove(me.additionalCls, cls);
19996             });
19997         }
19998         return me;
19999     },
20000
20001     removeClass : function() {
20002         if (Ext.isDefined(Ext.global.console)) {
20003             Ext.global.console.warn('Ext.Component: removeClass has been deprecated. Please use removeCls.');
20004         }
20005         return this.removeCls.apply(this, arguments);
20006     },
20007
20008     addOverCls: function() {
20009         var me = this;
20010         if (!me.disabled) {
20011             me.el.addCls(me.overCls);
20012         }
20013     },
20014
20015     removeOverCls: function() {
20016         this.el.removeCls(this.overCls);
20017     },
20018
20019     addListener : function(element, listeners, scope, options) {
20020         var me = this,
20021             fn,
20022             option;
20023
20024         if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) {
20025             if (options.element) {
20026                 fn = listeners;
20027
20028                 listeners = {};
20029                 listeners[element] = fn;
20030                 element = options.element;
20031                 if (scope) {
20032                     listeners.scope = scope;
20033                 }
20034
20035                 for (option in options) {
20036                     if (options.hasOwnProperty(option)) {
20037                         if (me.eventOptionsRe.test(option)) {
20038                             listeners[option] = options[option];
20039                         }
20040                     }
20041                 }
20042             }
20043
20044             
20045             
20046             if (me[element] && me[element].on) {
20047                 me.mon(me[element], listeners);
20048             } else {
20049                 me.afterRenderEvents = me.afterRenderEvents || {};
20050                 me.afterRenderEvents[element] = listeners;
20051             }
20052         }
20053
20054         return me.mixins.observable.addListener.apply(me, arguments);
20055     },
20056     
20057     
20058     removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
20059         var me = this,
20060             element = managedListener.options ? managedListener.options.element : null;
20061         
20062         if (element) {
20063             element = me[element];
20064             if (element && element.un) {
20065                 if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
20066                     element.un(managedListener.ename, managedListener.fn, managedListener.scope);
20067                     if (!isClear) {
20068                         Ext.Array.remove(me.managedListeners, managedListener);
20069                     }
20070                 }
20071             }
20072         } else {
20073             return me.mixins.observable.removeManagedListenerItem.apply(me, arguments);
20074         }
20075     },
20076
20077     
20078     getBubbleTarget : function() {
20079         return this.ownerCt;
20080     },
20081
20082     
20083     isFloating : function() {
20084         return this.floating;
20085     },
20086
20087     
20088     isDraggable : function() {
20089         return !!this.draggable;
20090     },
20091
20092     
20093     isDroppable : function() {
20094         return !!this.droppable;
20095     },
20096
20097     
20098     onAdded : function(container, pos) {
20099         this.ownerCt = container;
20100         this.fireEvent('added', this, container, pos);
20101     },
20102
20103     
20104     onRemoved : function() {
20105         var me = this;
20106
20107         me.fireEvent('removed', me, me.ownerCt);
20108         delete me.ownerCt;
20109     },
20110
20111     
20112     beforeDestroy : Ext.emptyFn,
20113     
20114     
20115     onResize : Ext.emptyFn,
20116
20117     
20118     setSize : function(width, height) {
20119         var me = this,
20120             layoutCollection;
20121
20122         
20123         if (Ext.isObject(width)) {
20124             height = width.height;
20125             width  = width.width;
20126         }
20127
20128         
20129         if (Ext.isNumber(width)) {
20130             width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
20131         }
20132         if (Ext.isNumber(height)) {
20133             height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
20134         }
20135
20136         if (!me.rendered || !me.isVisible()) {
20137             
20138             if (me.hiddenAncestor) {
20139                 layoutCollection = me.hiddenAncestor.layoutOnShow;
20140                 layoutCollection.remove(me);
20141                 layoutCollection.add(me);
20142             }
20143             me.needsLayout = {
20144                 width: width,
20145                 height: height,
20146                 isSetSize: true
20147             };
20148             if (!me.rendered) {
20149                 me.width  = (width !== undefined) ? width : me.width;
20150                 me.height = (height !== undefined) ? height : me.height;
20151             }
20152             return me;
20153         }
20154         me.doComponentLayout(width, height, true);
20155
20156         return me;
20157     },
20158
20159     setCalculatedSize : function(width, height, ownerCt) {
20160         var me = this,
20161             layoutCollection;
20162
20163         
20164         if (Ext.isObject(width)) {
20165             ownerCt = width.ownerCt;
20166             height = width.height;
20167             width  = width.width;
20168         }
20169
20170         
20171         if (Ext.isNumber(width)) {
20172             width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
20173         }
20174         if (Ext.isNumber(height)) {
20175             height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
20176         }
20177
20178         if (!me.rendered || !me.isVisible()) {
20179             
20180             if (me.hiddenAncestor) {
20181                 layoutCollection = me.hiddenAncestor.layoutOnShow;
20182                 layoutCollection.remove(me);
20183                 layoutCollection.add(me);
20184             }
20185             me.needsLayout = {
20186                 width: width,
20187                 height: height,
20188                 isSetSize: false,
20189                 ownerCt: ownerCt
20190             };
20191             return me;
20192         }
20193         me.doComponentLayout(width, height, false, ownerCt);
20194
20195         return me;
20196     },
20197
20198     
20199     doComponentLayout : function(width, height, isSetSize, ownerCt) {
20200         var me = this,
20201             componentLayout = me.getComponentLayout();
20202
20203         
20204         
20205         
20206         if (me.rendered && componentLayout) {
20207             width = (width !== undefined) ? width : me.width;
20208             height = (height !== undefined) ? height : me.height;
20209             if (isSetSize) {
20210                 me.width = width;
20211                 me.height = height;
20212             }
20213
20214             componentLayout.layout(width, height, isSetSize, ownerCt);
20215         }
20216         return me;
20217     },
20218
20219     
20220     setComponentLayout : function(layout) {
20221         var currentLayout = this.componentLayout;
20222         if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
20223             currentLayout.setOwner(null);
20224         }
20225         this.componentLayout = layout;
20226         layout.setOwner(this);
20227     },
20228
20229     getComponentLayout : function() {
20230         var me = this;
20231
20232         if (!me.componentLayout || !me.componentLayout.isLayout) {
20233             me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));
20234         }
20235         return me.componentLayout;
20236     },
20237
20238     
20239     afterComponentLayout: function(width, height, isSetSize, layoutOwner) {
20240         this.fireEvent('resize', this, width, height);
20241     },
20242
20243     
20244     beforeComponentLayout: function(width, height, isSetSize, layoutOwner) {
20245         return true;
20246     },
20247
20248     
20249     setPosition : function(x, y) {
20250         var me = this;
20251
20252         if (Ext.isObject(x)) {
20253             y = x.y;
20254             x = x.x;
20255         }
20256
20257         if (!me.rendered) {
20258             return me;
20259         }
20260
20261         if (x !== undefined || y !== undefined) {
20262             me.el.setBox(x, y);
20263             me.onPosition(x, y);
20264             me.fireEvent('move', me, x, y);
20265         }
20266         return me;
20267     },
20268
20269     
20270     onPosition: Ext.emptyFn,
20271
20272     
20273     setWidth : function(width) {
20274         return this.setSize(width);
20275     },
20276
20277     
20278     setHeight : function(height) {
20279         return this.setSize(undefined, height);
20280     },
20281
20282     
20283     getSize : function() {
20284         return this.el.getSize();
20285     },
20286
20287     
20288     getWidth : function() {
20289         return this.el.getWidth();
20290     },
20291
20292     
20293     getHeight : function() {
20294         return this.el.getHeight();
20295     },
20296
20297     
20298     getLoader: function(){
20299         var me = this,
20300             autoLoad = me.autoLoad ? (Ext.isObject(me.autoLoad) ? me.autoLoad : {url: me.autoLoad}) : null,
20301             loader = me.loader || autoLoad;
20302
20303         if (loader) {
20304             if (!loader.isLoader) {
20305                 me.loader = Ext.create('Ext.ComponentLoader', Ext.apply({
20306                     target: me,
20307                     autoLoad: autoLoad
20308                 }, loader));
20309             } else {
20310                 loader.setTarget(me);
20311             }
20312             return me.loader;
20313
20314         }
20315         return null;
20316     },
20317
20318     
20319     setLoading : function(load, targetEl) {
20320         var me = this,
20321             config;
20322
20323         if (me.rendered) {
20324             if (load !== false && !me.collapsed) {
20325                 if (Ext.isObject(load)) {
20326                     config = load;
20327                 }
20328                 else if (Ext.isString(load)) {
20329                     config = {msg: load};
20330                 }
20331                 else {
20332                     config = {};
20333                 }
20334                 me.loadMask = me.loadMask || Ext.create('Ext.LoadMask', targetEl ? me.getTargetEl() : me.el, config);
20335                 me.loadMask.show();
20336             } else if (me.loadMask) {
20337                 Ext.destroy(me.loadMask);
20338                 me.loadMask = null;
20339             }
20340         }
20341
20342         return me.loadMask;
20343     },
20344
20345     
20346     setDocked : function(dock, layoutParent) {
20347         var me = this;
20348
20349         me.dock = dock;
20350         if (layoutParent && me.ownerCt && me.rendered) {
20351             me.ownerCt.doComponentLayout();
20352         }
20353         return me;
20354     },
20355
20356     onDestroy : function() {
20357         var me = this;
20358
20359         if (me.monitorResize && Ext.EventManager.resizeEvent) {
20360             Ext.EventManager.resizeEvent.removeListener(me.setSize, me);
20361         }
20362         Ext.destroy(me.componentLayout, me.loadMask);
20363     },
20364
20365     
20366     destroy : function() {
20367         var me = this;
20368
20369         if (!me.isDestroyed) {
20370             if (me.fireEvent('beforedestroy', me) !== false) {
20371                 me.destroying = true;
20372                 me.beforeDestroy();
20373
20374                 if (me.floating) {
20375                     delete me.floatParent;
20376                     
20377                     
20378                     if (me.zIndexManager) {
20379                         me.zIndexManager.unregister(me);
20380                     }
20381                 } else if (me.ownerCt && me.ownerCt.remove) {
20382                     me.ownerCt.remove(me, false);
20383                 }
20384
20385                 if (me.rendered) {
20386                     me.el.remove();
20387                 }
20388
20389                 me.onDestroy();
20390
20391                 
20392                 Ext.destroy(me.plugins);
20393
20394                 Ext.ComponentManager.unregister(me);
20395                 me.fireEvent('destroy', me);
20396
20397                 me.mixins.state.destroy.call(me);
20398
20399                 me.clearListeners();
20400                 me.destroying = false;
20401                 me.isDestroyed = true;
20402             }
20403         }
20404     },
20405
20406     
20407     getPlugin: function(pluginId) {
20408         var i = 0,
20409             plugins = this.plugins,
20410             ln = plugins.length;
20411         for (; i < ln; i++) {
20412             if (plugins[i].pluginId === pluginId) {
20413                 return plugins[i];
20414             }
20415         }
20416     },
20417     
20418     
20419     isDescendantOf: function(container) {
20420         return !!this.findParentBy(function(p){
20421             return p === container;
20422         });
20423     }
20424 }, function() {
20425     this.createAlias({
20426         on: 'addListener',
20427         prev: 'previousSibling',
20428         next: 'nextSibling'
20429     });
20430 });
20431
20432
20433 Ext.define('Ext.AbstractPlugin', {
20434     disabled: false,
20435     
20436     constructor: function(config) {
20437         if (!config.cmp && Ext.global.console) {
20438             Ext.global.console.warn("Attempted to attach a plugin ");
20439         }
20440         Ext.apply(this, config);
20441     },
20442     
20443     getCmp: function() {
20444         return this.cmp;
20445     },
20446
20447     
20448     init: Ext.emptyFn,
20449
20450     
20451     destroy: Ext.emptyFn,
20452
20453     
20454     enable: function() {
20455         this.disabled = false;
20456     },
20457
20458     
20459     disable: function() {
20460         this.disabled = true;
20461     }
20462 });
20463
20464
20465 Ext.define('Ext.data.Connection', {
20466     mixins: {
20467         observable: 'Ext.util.Observable'
20468     },
20469
20470     statics: {
20471         requestId: 0
20472     },
20473
20474     url: null,
20475     async: true,
20476     method: null,
20477     username: '',
20478     password: '',
20479
20480     
20481     disableCaching: true,
20482
20483     
20484     disableCachingParam: '_dc',
20485
20486     
20487     timeout : 30000,
20488
20489     
20490
20491     useDefaultHeader : true,
20492     defaultPostHeader : 'application/x-www-form-urlencoded; charset=UTF-8',
20493     useDefaultXhrHeader : true,
20494     defaultXhrHeader : 'XMLHttpRequest',
20495
20496     constructor : function(config) {
20497         config = config || {};
20498         Ext.apply(this, config);
20499
20500         this.addEvents(
20501             
20502             'beforerequest',
20503             
20504             'requestcomplete',
20505             
20506             'requestexception'
20507         );
20508         this.requests = {};
20509         this.mixins.observable.constructor.call(this);
20510     },
20511
20512     
20513     request : function(options) {
20514         options = options || {};
20515         var me = this,
20516             scope = options.scope || window,
20517             username = options.username || me.username,
20518             password = options.password || me.password || '',
20519             async,
20520             requestOptions,
20521             request,
20522             headers,
20523             xhr;
20524
20525         if (me.fireEvent('beforerequest', me, options) !== false) {
20526
20527             requestOptions = me.setOptions(options, scope);
20528
20529             if (this.isFormUpload(options) === true) {
20530                 this.upload(options.form, requestOptions.url, requestOptions.data, options);
20531                 return null;
20532             }
20533
20534             
20535             if (options.autoAbort === true || me.autoAbort) {
20536                 me.abort();
20537             }
20538
20539             
20540             xhr = this.getXhrInstance();
20541
20542             async = options.async !== false ? (options.async || me.async) : false;
20543
20544             
20545             if (username) {
20546                 xhr.open(requestOptions.method, requestOptions.url, async, username, password);
20547             } else {
20548                 xhr.open(requestOptions.method, requestOptions.url, async);
20549             }
20550
20551             headers = me.setupHeaders(xhr, options, requestOptions.data, requestOptions.params);
20552
20553             
20554             request = {
20555                 id: ++Ext.data.Connection.requestId,
20556                 xhr: xhr,
20557                 headers: headers,
20558                 options: options,
20559                 async: async,
20560                 timeout: setTimeout(function() {
20561                     request.timedout = true;
20562                     me.abort(request);
20563                 }, options.timeout || me.timeout)
20564             };
20565             me.requests[request.id] = request;
20566
20567             
20568             if (async) {
20569                 xhr.onreadystatechange = Ext.Function.bind(me.onStateChange, me, [request]);
20570             }
20571
20572             
20573             xhr.send(requestOptions.data);
20574             if (!async) {
20575                 return this.onComplete(request);
20576             }
20577             return request;
20578         } else {
20579             Ext.callback(options.callback, options.scope, [options, undefined, undefined]);
20580             return null;
20581         }
20582     },
20583
20584     
20585     upload: function(form, url, params, options){
20586         form = Ext.getDom(form);
20587         options = options || {};
20588
20589         var id = Ext.id(),
20590                 frame = document.createElement('iframe'),
20591                 hiddens = [],
20592                 encoding = 'multipart/form-data',
20593                 buf = {
20594                     target: form.target,
20595                     method: form.method,
20596                     encoding: form.encoding,
20597                     enctype: form.enctype,
20598                     action: form.action
20599                 }, hiddenItem;
20600
20601         
20602         Ext.fly(frame).set({
20603             id: id,
20604             name: id,
20605             cls: Ext.baseCSSPrefix + 'hide-display',
20606             src: Ext.SSL_SECURE_URL
20607         });
20608
20609         document.body.appendChild(frame);
20610
20611         
20612         if (document.frames) {
20613            document.frames[id].name = id;
20614         }
20615
20616         Ext.fly(form).set({
20617             target: id,
20618             method: 'POST',
20619             enctype: encoding,
20620             encoding: encoding,
20621             action: url || buf.action
20622         });
20623
20624         
20625         if (params) {
20626             Ext.iterate(Ext.Object.fromQueryString(params), function(name, value){
20627                 hiddenItem = document.createElement('input');
20628                 Ext.fly(hiddenItem).set({
20629                     type: 'hidden',
20630                     value: value,
20631                     name: name
20632                 });
20633                 form.appendChild(hiddenItem);
20634                 hiddens.push(hiddenItem);
20635             });
20636         }
20637
20638         Ext.fly(frame).on('load', Ext.Function.bind(this.onUploadComplete, this, [frame, options]), null, {single: true});
20639         form.submit();
20640
20641         Ext.fly(form).set(buf);
20642         Ext.each(hiddens, function(h) {
20643             Ext.removeNode(h);
20644         });
20645     },
20646
20647     onUploadComplete: function(frame, options){
20648         var me = this,
20649             
20650             response = {
20651                 responseText: '',
20652                 responseXML: null
20653             }, doc, firstChild;
20654
20655         try {
20656             doc = frame.contentWindow.document || frame.contentDocument || window.frames[id].document;
20657             if (doc) {
20658                 if (doc.body) {
20659                     if (/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)) { 
20660                         response.responseText = firstChild.value;
20661                     } else {
20662                         response.responseText = doc.body.innerHTML;
20663                     }
20664                 }
20665                 
20666                 response.responseXML = doc.XMLDocument || doc;
20667             }
20668         } catch (e) {
20669         }
20670
20671         me.fireEvent('requestcomplete', me, response, options);
20672
20673         Ext.callback(options.success, options.scope, [response, options]);
20674         Ext.callback(options.callback, options.scope, [options, true, response]);
20675
20676         setTimeout(function(){
20677             Ext.removeNode(frame);
20678         }, 100);
20679     },
20680
20681     
20682     isFormUpload: function(options){
20683         var form = this.getForm(options);
20684         if (form) {
20685             return (options.isUpload || (/multipart\/form-data/i).test(form.getAttribute('enctype')));
20686         }
20687         return false;
20688     },
20689
20690     
20691     getForm: function(options){
20692         return Ext.getDom(options.form) || null;
20693     },
20694
20695     
20696     setOptions: function(options, scope){
20697         var me =  this,
20698             params = options.params || {},
20699             extraParams = me.extraParams,
20700             urlParams = options.urlParams,
20701             url = options.url || me.url,
20702             jsonData = options.jsonData,
20703             method,
20704             disableCache,
20705             data;
20706
20707
20708         
20709         if (Ext.isFunction(params)) {
20710             params = params.call(scope, options);
20711         }
20712
20713         
20714         if (Ext.isFunction(url)) {
20715             url = url.call(scope, options);
20716         }
20717
20718         url = this.setupUrl(options, url);
20719
20720         if (!url) {
20721             Ext.Error.raise({
20722                 options: options,
20723                 msg: 'No URL specified'
20724             });
20725         }
20726
20727         
20728         data = options.rawData || options.xmlData || jsonData || null;
20729         if (jsonData && !Ext.isPrimitive(jsonData)) {
20730             data = Ext.encode(data);
20731         }
20732
20733         
20734         if (Ext.isObject(params)) {
20735             params = Ext.Object.toQueryString(params);
20736         }
20737
20738         if (Ext.isObject(extraParams)) {
20739             extraParams = Ext.Object.toQueryString(extraParams);
20740         }
20741
20742         params = params + ((extraParams) ? ((params) ? '&' : '') + extraParams : '');
20743
20744         urlParams = Ext.isObject(urlParams) ? Ext.Object.toQueryString(urlParams) : urlParams;
20745
20746         params = this.setupParams(options, params);
20747
20748         
20749         method = (options.method || me.method || ((params || data) ? 'POST' : 'GET')).toUpperCase();
20750         this.setupMethod(options, method);
20751
20752
20753         disableCache = options.disableCaching !== false ? (options.disableCaching || me.disableCaching) : false;
20754         
20755         if (method === 'GET' && disableCache) {
20756             url = Ext.urlAppend(url, (options.disableCachingParam || me.disableCachingParam) + '=' + (new Date().getTime()));
20757         }
20758
20759         
20760         if ((method == 'GET' || data) && params) {
20761             url = Ext.urlAppend(url, params);
20762             params = null;
20763         }
20764
20765         
20766         if (urlParams) {
20767             url = Ext.urlAppend(url, urlParams);
20768         }
20769
20770         return {
20771             url: url,
20772             method: method,
20773             data: data || params || null
20774         };
20775     },
20776
20777     
20778     setupUrl: function(options, url){
20779         var form = this.getForm(options);
20780         if (form) {
20781             url = url || form.action;
20782         }
20783         return url;
20784     },
20785
20786
20787     
20788     setupParams: function(options, params) {
20789         var form = this.getForm(options),
20790             serializedForm;
20791         if (form && !this.isFormUpload(options)) {
20792             serializedForm = Ext.core.Element.serializeForm(form);
20793             params = params ? (params + '&' + serializedForm) : serializedForm;
20794         }
20795         return params;
20796     },
20797
20798     
20799     setupMethod: function(options, method){
20800         if (this.isFormUpload(options)) {
20801             return 'POST';
20802         }
20803         return method;
20804     },
20805
20806     
20807     setupHeaders: function(xhr, options, data, params){
20808         var me = this,
20809             headers = Ext.apply({}, options.headers || {}, me.defaultHeaders || {}),
20810             contentType = me.defaultPostHeader,
20811             jsonData = options.jsonData,
20812             xmlData = options.xmlData,
20813             key,
20814             header;
20815
20816         if (!headers['Content-Type'] && (data || params)) {
20817             if (data) {
20818                 if (options.rawData) {
20819                     contentType = 'text/plain';
20820                 } else {
20821                     if (xmlData && Ext.isDefined(xmlData)) {
20822                         contentType = 'text/xml';
20823                     } else if (jsonData && Ext.isDefined(jsonData)) {
20824                         contentType = 'application/json';
20825                     }
20826                 }
20827             }
20828             headers['Content-Type'] = contentType;
20829         }
20830
20831         if (me.useDefaultXhrHeader && !headers['X-Requested-With']) {
20832             headers['X-Requested-With'] = me.defaultXhrHeader;
20833         }
20834         
20835         try{
20836             for (key in headers) {
20837                 if (headers.hasOwnProperty(key)) {
20838                     header = headers[key];
20839                     xhr.setRequestHeader(key, header);
20840                 }
20841
20842             }
20843         } catch(e) {
20844             me.fireEvent('exception', key, header);
20845         }
20846         return headers;
20847     },
20848
20849     
20850     getXhrInstance: (function(){
20851         var options = [function(){
20852             return new XMLHttpRequest();
20853         }, function(){
20854             return new ActiveXObject('MSXML2.XMLHTTP.3.0');
20855         }, function(){
20856             return new ActiveXObject('MSXML2.XMLHTTP');
20857         }, function(){
20858             return new ActiveXObject('Microsoft.XMLHTTP');
20859         }], i = 0,
20860             len = options.length,
20861             xhr;
20862
20863         for(; i < len; ++i) {
20864             try{
20865                 xhr = options[i];
20866                 xhr();
20867                 break;
20868             }catch(e){}
20869         }
20870         return xhr;
20871     })(),
20872
20873     
20874     isLoading : function(request) {
20875         if (!(request && request.xhr)) {
20876             return false;
20877         }
20878         
20879         var state = request.xhr.readyState;
20880         return !(state === 0 || state == 4);
20881     },
20882
20883     
20884     abort : function(request) {
20885         var me = this,
20886             requests = me.requests,
20887             id;
20888
20889         if (request && me.isLoading(request)) {
20890             
20891             request.xhr.onreadystatechange = null;
20892             request.xhr.abort();
20893             me.clearTimeout(request);
20894             if (!request.timedout) {
20895                 request.aborted = true;
20896             }
20897             me.onComplete(request);
20898             me.cleanup(request);
20899         } else if (!request) {
20900             for(id in requests) {
20901                 if (requests.hasOwnProperty(id)) {
20902                     me.abort(requests[id]);
20903                 }
20904             }
20905         }
20906     },
20907
20908     
20909     onStateChange : function(request) {
20910         if (request.xhr.readyState == 4) {
20911             this.clearTimeout(request);
20912             this.onComplete(request);
20913             this.cleanup(request);
20914         }
20915     },
20916
20917     
20918     clearTimeout: function(request){
20919         clearTimeout(request.timeout);
20920         delete request.timeout;
20921     },
20922
20923     
20924     cleanup: function(request){
20925         request.xhr = null;
20926         delete request.xhr;
20927     },
20928
20929     
20930     onComplete : function(request) {
20931         var me = this,
20932             options = request.options,
20933             result = me.parseStatus(request.xhr.status),
20934             success = result.success,
20935             response;
20936
20937         if (success) {
20938             response = me.createResponse(request);
20939             me.fireEvent('requestcomplete', me, response, options);
20940             Ext.callback(options.success, options.scope, [response, options]);
20941         } else {
20942             if (result.isException || request.aborted || request.timedout) {
20943                 response = me.createException(request);
20944             } else {
20945                 response = me.createResponse(request);
20946             }
20947             me.fireEvent('requestexception', me, response, options);
20948             Ext.callback(options.failure, options.scope, [response, options]);
20949         }
20950         Ext.callback(options.callback, options.scope, [options, success, response]);
20951         delete me.requests[request.id];
20952         return response;
20953     },
20954
20955     
20956     parseStatus: function(status) {
20957         
20958         status = status == 1223 ? 204 : status;
20959
20960         var success = (status >= 200 && status < 300) || status == 304,
20961             isException = false;
20962
20963         if (!success) {
20964             switch (status) {
20965                 case 12002:
20966                 case 12029:
20967                 case 12030:
20968                 case 12031:
20969                 case 12152:
20970                 case 13030:
20971                     isException = true;
20972                     break;
20973             }
20974         }
20975         return {
20976             success: success,
20977             isException: isException
20978         };
20979     },
20980
20981     
20982     createResponse : function(request) {
20983         var xhr = request.xhr,
20984             headers = {},
20985             lines = xhr.getAllResponseHeaders().replace(/\r\n/g, '\n').split('\n'),
20986             count = lines.length,
20987             line, index, key, value, response;
20988
20989         while (count--) {
20990             line = lines[count];
20991             index = line.indexOf(':');
20992             if(index >= 0) {
20993                 key = line.substr(0, index).toLowerCase();
20994                 if (line.charAt(index + 1) == ' ') {
20995                     ++index;
20996                 }
20997                 headers[key] = line.substr(index + 1);
20998             }
20999         }
21000
21001         request.xhr = null;
21002         delete request.xhr;
21003
21004         response = {
21005             request: request,
21006             requestId : request.id,
21007             status : xhr.status,
21008             statusText : xhr.statusText,
21009             getResponseHeader : function(header){ return headers[header.toLowerCase()]; },
21010             getAllResponseHeaders : function(){ return headers; },
21011             responseText : xhr.responseText,
21012             responseXML : xhr.responseXML
21013         };
21014
21015         
21016         
21017         xhr = null;
21018         return response;
21019     },
21020
21021     
21022     createException : function(request) {
21023         return {
21024             request : request,
21025             requestId : request.id,
21026             status : request.aborted ? -1 : 0,
21027             statusText : request.aborted ? 'transaction aborted' : 'communication failure',
21028             aborted: request.aborted,
21029             timedout: request.timedout
21030         };
21031     }
21032 });
21033
21034
21035 Ext.define('Ext.Ajax', {
21036     extend: 'Ext.data.Connection',
21037     singleton: true,
21038
21039     
21040     
21041     
21042     
21043     
21044     
21045
21046     
21047
21048     
21049     
21050     
21051     
21052     
21053     
21054
21055     
21056     autoAbort : false
21057 });
21058
21059 Ext.define('Ext.data.Association', {
21060     
21061
21062     
21063
21064     
21065     primaryKey: 'id',
21066
21067     
21068     
21069     
21070
21071     defaultReaderType: 'json',
21072
21073     statics: {
21074         create: function(association){
21075             if (!association.isAssociation) {
21076                 if (Ext.isString(association)) {
21077                     association = {
21078                         type: association
21079                     };
21080                 }
21081
21082                 switch (association.type) {
21083                     case 'belongsTo':
21084                         return Ext.create('Ext.data.BelongsToAssociation', association);
21085                     case 'hasMany':
21086                         return Ext.create('Ext.data.HasManyAssociation', association);
21087                     
21088
21089
21090                     default:
21091                         Ext.Error.raise('Unknown Association type: "' + association.type + '"');
21092                 }
21093             }
21094             return association;
21095         }
21096     },
21097
21098     constructor: function(config) {
21099         Ext.apply(this, config);
21100
21101         var types           = Ext.ModelManager.types,
21102             ownerName       = config.ownerModel,
21103             associatedName  = config.associatedModel,
21104             ownerModel      = types[ownerName],
21105             associatedModel = types[associatedName],
21106             ownerProto;
21107
21108         if (ownerModel === undefined) {
21109             Ext.Error.raise("The configured ownerModel was not valid (you tried " + ownerName + ")");
21110         }
21111         if (associatedModel === undefined) {
21112             Ext.Error.raise("The configured associatedModel was not valid (you tried " + associatedName + ")");
21113         }
21114
21115         this.ownerModel = ownerModel;
21116         this.associatedModel = associatedModel;
21117
21118         
21119
21120         
21121
21122         Ext.applyIf(this, {
21123             ownerName : ownerName,
21124             associatedName: associatedName
21125         });
21126     },
21127
21128     
21129     getReader: function(){
21130         var me = this,
21131             reader = me.reader,
21132             model = me.associatedModel;
21133
21134         if (reader) {
21135             if (Ext.isString(reader)) {
21136                 reader = {
21137                     type: reader
21138                 };
21139             }
21140             if (reader.isReader) {
21141                 reader.setModel(model);
21142             } else {
21143                 Ext.applyIf(reader, {
21144                     model: model,
21145                     type : me.defaultReaderType
21146                 });
21147             }
21148             me.reader = Ext.createByAlias('reader.' + reader.type, reader);
21149         }
21150         return me.reader || null;
21151     }
21152 });
21153
21154
21155 Ext.define('Ext.ModelManager', {
21156     extend: 'Ext.AbstractManager',
21157     alternateClassName: 'Ext.ModelMgr',
21158     requires: ['Ext.data.Association'],
21159     
21160     singleton: true,
21161     
21162     typeName: 'mtype',
21163     
21164     
21165     associationStack: [],
21166     
21167     
21168     registerType: function(name, config) {
21169         var proto = config.prototype,
21170             model;
21171         if (proto && proto.isModel) {
21172             
21173             model = config;
21174         } else {
21175             
21176             if (!config.extend) {
21177                 config.extend = 'Ext.data.Model';
21178             }
21179             model = Ext.define(name, config);
21180         }
21181         this.types[name] = model;
21182         return model;
21183     },
21184     
21185     
21186     onModelDefined: function(model) {
21187         var stack  = this.associationStack,
21188             length = stack.length,
21189             create = [],
21190             association, i, created;
21191         
21192         for (i = 0; i < length; i++) {
21193             association = stack[i];
21194             
21195             if (association.associatedModel == model.modelName) {
21196                 create.push(association);
21197             }
21198         }
21199         
21200         for (i = 0, length = create.length; i < length; i++) {
21201             created = create[i];
21202             this.types[created.ownerModel].prototype.associations.add(Ext.data.Association.create(created));
21203             Ext.Array.remove(stack, created);
21204         }
21205     },
21206     
21207     
21208     registerDeferredAssociation: function(association){
21209         this.associationStack.push(association);
21210     },
21211     
21212     
21213     getModel: function(id) {
21214         var model = id;
21215         if (typeof model == 'string') {
21216             model = this.types[model];
21217         }
21218         return model;
21219     },
21220     
21221     
21222     create: function(config, name, id) {
21223         var con = typeof name == 'function' ? name : this.types[name || config.name];
21224         
21225         return new con(config, id);
21226     }
21227 }, function() {
21228     
21229     
21230     Ext.regModel = function() {
21231         if (Ext.isDefined(Ext.global.console)) {
21232             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: []});.');
21233         }
21234         return this.ModelManager.registerType.apply(this.ModelManager, arguments);
21235     };
21236 });
21237
21238   
21239 Ext.define('Ext.app.Controller', {
21240     
21241
21242     mixins: {
21243         observable: 'Ext.util.Observable'
21244     },
21245
21246     onClassExtended: function(cls, data) {
21247         var className = Ext.getClassName(cls),
21248             match = className.match(/^(.*)\.controller\./);
21249
21250         if (match !== null) {
21251             var namespace = Ext.Loader.getPrefix(className) || match[1],
21252                 onBeforeClassCreated = data.onBeforeClassCreated,
21253                 requires = [],
21254                 modules = ['model', 'view', 'store'],
21255                 prefix;
21256
21257             data.onBeforeClassCreated = function(cls, data) {
21258                 var i, ln, module,
21259                     items, j, subLn, item;
21260
21261                 for (i = 0,ln = modules.length; i < ln; i++) {
21262                     module = modules[i];
21263
21264                     items = Ext.Array.from(data[module + 's']);
21265
21266                     for (j = 0,subLn = items.length; j < subLn; j++) {
21267                         item = items[j];
21268
21269                         prefix = Ext.Loader.getPrefix(item);
21270
21271                         if (prefix === '' || prefix === item) {
21272                             requires.push(namespace + '.' + module + '.' + item);
21273                         }
21274                         else {
21275                             requires.push(item);
21276                         }
21277                     }
21278                 }
21279
21280                 Ext.require(requires, Ext.Function.pass(onBeforeClassCreated, arguments, this));
21281             };
21282         }
21283     },
21284
21285     constructor: function(config) {
21286         this.mixins.observable.constructor.call(this, config);
21287
21288         Ext.apply(this, config || {});
21289
21290         this.createGetters('model', this.models);
21291         this.createGetters('store', this.stores);
21292         this.createGetters('view', this.views);
21293
21294         if (this.refs) {
21295             this.ref(this.refs);
21296         }
21297     },
21298
21299     
21300     init: function(application) {},
21301     
21302     onLaunch: function(application) {},
21303
21304     createGetters: function(type, refs) {
21305         type = Ext.String.capitalize(type);
21306         Ext.Array.each(refs, function(ref) {
21307             var fn = 'get',
21308                 parts = ref.split('.');
21309
21310             
21311             Ext.Array.each(parts, function(part) {
21312                 fn += Ext.String.capitalize(part);
21313             });
21314             fn += type;
21315
21316             if (!this[fn]) {
21317                 this[fn] = Ext.Function.pass(this['get' + type], [ref], this);
21318             }
21319             
21320             this[fn](ref);
21321         },
21322         this);
21323     },
21324
21325     ref: function(refs) {
21326         var me = this;
21327         refs = Ext.Array.from(refs);
21328         Ext.Array.each(refs, function(info) {
21329             var ref = info.ref,
21330                 fn = 'get' + Ext.String.capitalize(ref);
21331             if (!me[fn]) {
21332                 me[fn] = Ext.Function.pass(me.getRef, [ref, info], me);
21333             }
21334         });
21335     },
21336
21337     getRef: function(ref, info, config) {
21338         this.refCache = this.refCache || {};
21339         info = info || {};
21340         config = config || {};
21341
21342         Ext.apply(info, config);
21343
21344         if (info.forceCreate) {
21345             return Ext.ComponentManager.create(info, 'component');
21346         }
21347
21348         var me = this,
21349             selector = info.selector,
21350             cached = me.refCache[ref];
21351
21352         if (!cached) {
21353             me.refCache[ref] = cached = Ext.ComponentQuery.query(info.selector)[0];
21354             if (!cached && info.autoCreate) {
21355                 me.refCache[ref] = cached = Ext.ComponentManager.create(info, 'component');
21356             }
21357             if (cached) {
21358                 cached.on('beforedestroy', function() {
21359                     me.refCache[ref] = null;
21360                 });
21361             }
21362         }
21363
21364         return cached;
21365     },
21366
21367     control: function(selectors, listeners) {
21368         this.application.control(selectors, listeners, this);
21369     },
21370
21371     getController: function(name) {
21372         return this.application.getController(name);
21373     },
21374
21375     getStore: function(name) {
21376         return this.application.getStore(name);
21377     },
21378
21379     getModel: function(model) {
21380         return this.application.getModel(model);
21381     },
21382
21383     getView: function(view) {
21384         return this.application.getView(view);
21385     }
21386 });
21387
21388
21389 Ext.define('Ext.data.SortTypes', {
21390     
21391     singleton: true,
21392     
21393     
21394     none : function(s) {
21395         return s;
21396     },
21397
21398     
21399     stripTagsRE : /<\/?[^>]+>/gi,
21400
21401     
21402     asText : function(s) {
21403         return String(s).replace(this.stripTagsRE, "");
21404     },
21405
21406     
21407     asUCText : function(s) {
21408         return String(s).toUpperCase().replace(this.stripTagsRE, "");
21409     },
21410
21411     
21412     asUCString : function(s) {
21413         return String(s).toUpperCase();
21414     },
21415
21416     
21417     asDate : function(s) {
21418         if(!s){
21419             return 0;
21420         }
21421         if(Ext.isDate(s)){
21422             return s.getTime();
21423         }
21424         return Date.parse(String(s));
21425     },
21426
21427     
21428     asFloat : function(s) {
21429         var val = parseFloat(String(s).replace(/,/g, ""));
21430         return isNaN(val) ? 0 : val;
21431     },
21432
21433     
21434     asInt : function(s) {
21435         var val = parseInt(String(s).replace(/,/g, ""), 10);
21436         return isNaN(val) ? 0 : val;
21437     }
21438 });
21439
21440 Ext.define('Ext.data.Errors', {
21441     extend: 'Ext.util.MixedCollection',
21442     
21443     
21444     isValid: function() {
21445         return this.length === 0;
21446     },
21447     
21448     
21449     getByField: function(fieldName) {
21450         var errors = [],
21451             error, field, i;
21452             
21453         for (i = 0; i < this.length; i++) {
21454             error = this.items[i];
21455             
21456             if (error.field == fieldName) {
21457                 errors.push(error);
21458             }
21459         }
21460         
21461         return errors;
21462     }
21463 });
21464
21465
21466 Ext.define('Ext.data.Operation', {
21467     
21468     synchronous: true,
21469     
21470     
21471     action: undefined,
21472     
21473     
21474     filters: undefined,
21475     
21476     
21477     sorters: undefined,
21478     
21479     
21480     group: undefined,
21481     
21482     
21483     start: undefined,
21484     
21485     
21486     limit: undefined,
21487     
21488     
21489     batch: undefined,
21490         
21491     
21492     started: false,
21493     
21494     
21495     running: false,
21496     
21497     
21498     complete: false,
21499     
21500     
21501     success: undefined,
21502     
21503     
21504     exception: false,
21505     
21506     
21507     error: undefined,
21508     
21509     constructor: function(config) {
21510         Ext.apply(this, config || {});
21511     },
21512     
21513     
21514     setStarted: function() {
21515         this.started = true;
21516         this.running = true;
21517     },
21518     
21519     
21520     setCompleted: function() {
21521         this.complete = true;
21522         this.running  = false;
21523     },
21524     
21525     
21526     setSuccessful: function() {
21527         this.success = true;
21528     },
21529     
21530     
21531     setException: function(error) {
21532         this.exception = true;
21533         this.success = false;
21534         this.running = false;
21535         this.error = error;
21536     },
21537     
21538     
21539     hasException: function() {
21540         return this.exception === true;
21541     },
21542     
21543     
21544     getError: function() {
21545         return this.error;
21546     },
21547     
21548     
21549     getRecords: function() {
21550         var resultSet = this.getResultSet();
21551         
21552         return (resultSet === undefined ? this.records : resultSet.records);
21553     },
21554     
21555     
21556     getResultSet: function() {
21557         return this.resultSet;
21558     },
21559     
21560     
21561     isStarted: function() {
21562         return this.started === true;
21563     },
21564     
21565     
21566     isRunning: function() {
21567         return this.running === true;
21568     },
21569     
21570     
21571     isComplete: function() {
21572         return this.complete === true;
21573     },
21574     
21575     
21576     wasSuccessful: function() {
21577         return this.isComplete() && this.success === true;
21578     },
21579     
21580     
21581     setBatch: function(batch) {
21582         this.batch = batch;
21583     },
21584     
21585     
21586     allowWrite: function() {
21587         return this.action != 'read';
21588     }
21589 });
21590
21591 Ext.define('Ext.data.validations', {
21592     singleton: true,
21593     
21594     
21595     presenceMessage: 'must be present',
21596     
21597     
21598     lengthMessage: 'is the wrong length',
21599     
21600     
21601     formatMessage: 'is the wrong format',
21602     
21603     
21604     inclusionMessage: 'is not included in the list of acceptable values',
21605     
21606     
21607     exclusionMessage: 'is not an acceptable value',
21608     
21609     
21610     presence: function(config, value) {
21611         if (value === undefined) {
21612             value = config;
21613         }
21614         
21615         return !!value;
21616     },
21617     
21618     
21619     length: function(config, value) {
21620         if (value === undefined) {
21621             return false;
21622         }
21623         
21624         var length = value.length,
21625             min    = config.min,
21626             max    = config.max;
21627         
21628         if ((min && length < min) || (max && length > max)) {
21629             return false;
21630         } else {
21631             return true;
21632         }
21633     },
21634     
21635     
21636     format: function(config, value) {
21637         return !!(config.matcher && config.matcher.test(value));
21638     },
21639     
21640     
21641     inclusion: function(config, value) {
21642         return config.list && Ext.Array.indexOf(config.list,value) != -1;
21643     },
21644     
21645     
21646     exclusion: function(config, value) {
21647         return config.list && Ext.Array.indexOf(config.list,value) == -1;
21648     }
21649 });
21650
21651 Ext.define('Ext.data.ResultSet', {
21652     
21653     loaded: true,
21654     
21655     
21656     count: 0,
21657     
21658     
21659     total: 0,
21660     
21661     
21662     success: false,
21663     
21664     
21665
21666     constructor: function(config) {
21667         Ext.apply(this, config);
21668         
21669         
21670         this.totalRecords = this.total;
21671         
21672         if (config.count === undefined) {
21673             this.count = this.records.length;
21674         }
21675     }
21676 });
21677
21678 Ext.define('Ext.data.writer.Writer', {
21679     alias: 'writer.base',
21680     alternateClassName: ['Ext.data.DataWriter', 'Ext.data.Writer'],
21681     
21682     
21683     writeAllFields: true,
21684     
21685     
21686     nameProperty: 'name',
21687
21688     constructor: function(config) {
21689         Ext.apply(this, config);
21690     },
21691
21692     
21693     write: function(request) {
21694         var operation = request.operation,
21695             records   = operation.records || [],
21696             len       = records.length,
21697             i         = 0,
21698             data      = [];
21699
21700         for (; i < len; i++) {
21701             data.push(this.getRecordData(records[i]));
21702         }
21703         return this.writeRecords(request, data);
21704     },
21705
21706     
21707     getRecordData: function(record) {
21708         var isPhantom = record.phantom === true,
21709             writeAll = this.writeAllFields || isPhantom,
21710             nameProperty = this.nameProperty,
21711             fields = record.fields,
21712             data = {},
21713             changes,
21714             name,
21715             field,
21716             key;
21717         
21718         if (writeAll) {
21719             fields.each(function(field){
21720                 if (field.persist) {
21721                     name = field[nameProperty] || field.name;
21722                     data[name] = record.get(field.name);
21723                 }
21724             });
21725         } else {
21726             
21727             changes = record.getChanges();
21728             for (key in changes) {
21729                 if (changes.hasOwnProperty(key)) {
21730                     field = fields.get(key);
21731                     name = field[nameProperty] || field.name;
21732                     data[name] = changes[key];
21733                 }
21734             }
21735             if (!isPhantom) {
21736                 
21737                 data[record.idProperty] = record.getId();
21738             }
21739         }
21740         return data;
21741     }
21742 });
21743
21744
21745 Ext.define('Ext.util.Floating', {
21746
21747     uses: ['Ext.Layer', 'Ext.window.Window'],
21748
21749     
21750     focusOnToFront: true,
21751
21752     
21753     shadow: 'sides',
21754
21755     constructor: function(config) {
21756         this.floating = true;
21757         this.el = Ext.create('Ext.Layer', Ext.apply({}, config, {
21758             hideMode: this.hideMode,
21759             hidden: this.hidden,
21760             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
21761             shadowOffset: this.shadowOffset,
21762             constrain: false,
21763             shim: this.shim === false ? false : undefined
21764         }), this.el);
21765     },
21766
21767     onFloatRender: function() {
21768         var me = this;
21769         me.zIndexParent = me.getZIndexParent();
21770         me.setFloatParent(me.ownerCt);
21771         delete me.ownerCt;
21772
21773         if (me.zIndexParent) {
21774             me.zIndexParent.registerFloatingItem(me);
21775         } else {
21776             Ext.WindowManager.register(me);
21777         }
21778     },
21779
21780     setFloatParent: function(floatParent) {
21781         var me = this;
21782
21783         
21784         if (me.floatParent) {
21785             me.mun(me.floatParent, {
21786                 hide: me.onFloatParentHide,
21787                 show: me.onFloatParentShow,
21788                 scope: me
21789             });
21790         }
21791
21792         me.floatParent = floatParent;
21793
21794         
21795         if (floatParent) {
21796             me.mon(me.floatParent, {
21797                 hide: me.onFloatParentHide,
21798                 show: me.onFloatParentShow,
21799                 scope: me
21800             });
21801         }
21802
21803         
21804         
21805         if ((me.constrain || me.constrainHeader) && !me.constrainTo) {
21806             me.constrainTo = floatParent ? floatParent.getTargetEl() : me.container;
21807         }
21808     },
21809
21810     onFloatParentHide: function() {
21811         this.showOnParentShow = this.isVisible();
21812         this.hide();
21813     },
21814
21815     onFloatParentShow: function() {
21816         if (this.showOnParentShow) {
21817             delete this.showOnParentShow;
21818             this.show();
21819         }
21820     },
21821
21822     
21823     getZIndexParent: function() {
21824         var p = this.ownerCt,
21825             c;
21826
21827         if (p) {
21828             while (p) {
21829                 c = p;
21830                 p = p.ownerCt;
21831             }
21832             if (c.floating) {
21833                 return c;
21834             }
21835         }
21836     },
21837
21838     
21839     
21840     
21841     
21842     
21843     setZIndex: function(index) {
21844         var me = this;
21845         this.el.setZIndex(index);
21846
21847         
21848         index += 10;
21849
21850         
21851         
21852         if (me.floatingItems) {
21853             index = Math.floor(me.floatingItems.setBase(index) / 100) * 100 + 10000;
21854         }
21855         return index;
21856     },
21857
21858     
21859     doConstrain: function(constrainTo) {
21860         var me = this,
21861             vector = me.getConstrainVector(constrainTo),
21862             xy;
21863
21864         if (vector) {
21865             xy = me.getPosition();
21866             xy[0] += vector[0];
21867             xy[1] += vector[1];
21868             me.setPosition(xy);
21869         }
21870     },
21871     
21872     
21873     
21874     getConstrainVector: function(constrainTo){
21875         var me = this,
21876             el;
21877             
21878         if (me.constrain || me.constrainHeader) {
21879             el = me.constrainHeader ? me.header.el : me.el;
21880             constrainTo = constrainTo || (me.floatParent && me.floatParent.getTargetEl()) || me.container;
21881             return el.getConstrainVector(constrainTo);
21882         }
21883     },
21884
21885     
21886     alignTo: function(element, position, offsets) {
21887         if (element.isComponent) {
21888             element = element.getEl();
21889         }
21890         var xy = this.el.getAlignToXY(element, position, offsets);
21891         this.setPagePosition(xy);
21892         return this;
21893     },
21894
21895     
21896     toFront: function(preventFocus) {
21897         var me = this;
21898
21899         
21900         
21901         if (me.zIndexParent) {
21902             me.zIndexParent.toFront(true);
21903         }
21904         if (me.zIndexManager.bringToFront(me)) {
21905             if (!Ext.isDefined(preventFocus)) {
21906                 preventFocus = !me.focusOnToFront;
21907             }
21908             if (!preventFocus) {
21909                 
21910                 
21911                 
21912                 me.focus(false, true);
21913             }
21914         }
21915         return me;
21916     },
21917
21918     
21919     setActive: function(active, newActive) {
21920         if (active) {
21921             if ((this instanceof Ext.window.Window) && !this.maximized) {
21922                 this.el.enableShadow(true);
21923             }
21924             this.fireEvent('activate', this);
21925         } else {
21926             
21927             
21928             if ((this instanceof Ext.window.Window) && (newActive instanceof Ext.window.Window)) {
21929                 this.el.disableShadow();
21930             }
21931             this.fireEvent('deactivate', this);
21932         }
21933     },
21934
21935     
21936     toBack: function() {
21937         this.zIndexManager.sendToBack(this);
21938         return this;
21939     },
21940
21941     
21942     center: function() {
21943         var xy = this.el.getAlignToXY(this.container, 'c-c');
21944         this.setPagePosition(xy);
21945         return this;
21946     },
21947
21948     
21949     syncShadow : function(){
21950         if (this.floating) {
21951             this.el.sync(true);
21952         }
21953     },
21954
21955     
21956     fitContainer: function() {
21957         var parent = this.floatParent,
21958             container = parent ? parent.getTargetEl() : this.container,
21959             size = container.getViewSize(false);
21960
21961         this.setSize(size);
21962     }
21963 });
21964
21965
21966 Ext.define('Ext.layout.container.AbstractContainer', {
21967
21968     
21969
21970     extend: 'Ext.layout.Layout',
21971
21972     
21973
21974     type: 'container',
21975
21976     fixedLayout: true,
21977
21978     
21979     managedHeight: true,
21980     
21981     managedWidth: true,
21982
21983     
21984     bindToOwnerCtComponent: false,
21985
21986     
21987     bindToOwnerCtContainer: false,
21988
21989     
21990
21991     isManaged: function(dimension) {
21992         dimension = Ext.String.capitalize(dimension);
21993         var me = this,
21994             child = me,
21995             managed = me['managed' + dimension],
21996             ancestor = me.owner.ownerCt;
21997
21998         if (ancestor && ancestor.layout) {
21999             while (ancestor && ancestor.layout) {
22000                 if (managed === false || ancestor.layout['managed' + dimension] === false) {
22001                     managed = false;
22002                     break;
22003                 }
22004                 ancestor = ancestor.ownerCt;
22005             }
22006         }
22007         return managed;
22008     },
22009
22010     layout: function() {
22011         var me = this,
22012             owner = me.owner;
22013         if (Ext.isNumber(owner.height) || owner.isViewport) {
22014             me.managedHeight = false;
22015         }
22016         if (Ext.isNumber(owner.width) || owner.isViewport) {
22017             me.managedWidth = false;
22018         }
22019         me.callParent(arguments);
22020     },
22021
22022     
22023     setItemSize: function(item, width, height) {
22024         if (Ext.isObject(width)) {
22025             height = width.height;
22026             width = width.width;
22027         }
22028         item.setCalculatedSize(width, height, this.owner);
22029     },
22030
22031     
22032     getLayoutItems: function() {
22033         return this.owner && this.owner.items && this.owner.items.items || [];
22034     },
22035
22036     afterLayout: function() {
22037         this.owner.afterLayout(this);
22038     },
22039     
22040      getTarget: function() {
22041          return this.owner.getTargetEl();
22042      },
22043     
22044      getRenderTarget: function() {
22045          return this.owner.getTargetEl();
22046      }
22047 });
22048
22049
22050 Ext.define('Ext.ZIndexManager', {
22051
22052     alternateClassName: 'Ext.WindowGroup',
22053
22054     statics: {
22055         zBase : 9000
22056     },
22057
22058     constructor: function(container) {
22059         var me = this;
22060
22061         me.list = {};
22062         me.zIndexStack = [];
22063         me.front = null;
22064
22065         if (container) {
22066
22067             
22068             if (container.isContainer) {
22069                 container.on('resize', me._onContainerResize, me);
22070                 me.zseed = Ext.Number.from(container.getEl().getStyle('zIndex'), me.getNextZSeed());
22071                 
22072                 me.targetEl = container.getTargetEl();
22073                 me.container = container;
22074             }
22075             
22076             else {
22077                 Ext.EventManager.onWindowResize(me._onContainerResize, me);
22078                 me.zseed = me.getNextZSeed();
22079                 me.targetEl = Ext.get(container);
22080             }
22081         }
22082         
22083         
22084         else {
22085             Ext.EventManager.onWindowResize(me._onContainerResize, me);
22086             me.zseed = me.getNextZSeed();
22087             Ext.onDocumentReady(function() {
22088                 me.targetEl = Ext.getBody();
22089             });
22090         }
22091     },
22092
22093     getNextZSeed: function() {
22094         return (Ext.ZIndexManager.zBase += 10000);
22095     },
22096
22097     setBase: function(baseZIndex) {
22098         this.zseed = baseZIndex;
22099         return this.assignZIndices();
22100     },
22101
22102     
22103     assignZIndices: function() {
22104         var a = this.zIndexStack,
22105             len = a.length,
22106             i = 0,
22107             zIndex = this.zseed,
22108             comp;
22109
22110         for (; i < len; i++) {
22111             comp = a[i];
22112             if (comp && !comp.hidden) {
22113
22114                 
22115                 
22116                 
22117                 
22118                 
22119                 
22120                 
22121                 zIndex = comp.setZIndex(zIndex);
22122             }
22123         }
22124         this._activateLast();
22125         return zIndex;
22126     },
22127
22128     
22129     _setActiveChild: function(comp) {
22130         if (comp != this.front) {
22131
22132             if (this.front) {
22133                 this.front.setActive(false, comp);
22134             }
22135             this.front = comp;
22136             if (comp) {
22137                 comp.setActive(true);
22138                 if (comp.modal) {
22139                     this._showModalMask(comp.el.getStyle('zIndex') - 4);
22140                 }
22141             }
22142         }
22143     },
22144
22145     
22146     _activateLast: function(justHidden) {
22147         var comp,
22148             lastActivated = false,
22149             i;
22150
22151         
22152         
22153         
22154         for (i = this.zIndexStack.length-1; i >= 0; --i) {
22155             comp = this.zIndexStack[i];
22156             if (!comp.hidden) {
22157                 if (!lastActivated) {
22158                     this._setActiveChild(comp);
22159                     lastActivated = true;
22160                 }
22161
22162                 
22163                 if (comp.modal) {
22164                     this._showModalMask(comp.el.getStyle('zIndex') - 4);
22165                     return;
22166                 }
22167             }
22168         }
22169
22170         
22171         
22172         this._hideModalMask();
22173         if (!lastActivated) {
22174             this._setActiveChild(null);
22175         }
22176     },
22177
22178     _showModalMask: function(zIndex) {
22179         if (!this.mask) {
22180             this.mask = this.targetEl.createChild({
22181                 cls: Ext.baseCSSPrefix + 'mask'
22182             });
22183             this.mask.setVisibilityMode(Ext.core.Element.DISPLAY);
22184             this.mask.on('click', this._onMaskClick, this);
22185         }
22186         Ext.getBody().addCls(Ext.baseCSSPrefix + 'body-masked');
22187         this.mask.setSize(this.targetEl.getViewSize(true));
22188         this.mask.setStyle('zIndex', zIndex);
22189         this.mask.show();
22190     },
22191
22192     _hideModalMask: function() {
22193         if (this.mask) {
22194             Ext.getBody().removeCls(Ext.baseCSSPrefix + 'body-masked');
22195             this.mask.hide();
22196         }
22197     },
22198
22199     _onMaskClick: function() {
22200         if (this.front) {
22201             this.front.focus();
22202         }
22203     },
22204
22205     _onContainerResize: function() {
22206         if (this.mask && this.mask.isVisible()) {
22207             this.mask.setSize(this.targetEl.getViewSize(true));
22208         }
22209     },
22210
22211     
22212     register : function(comp) {
22213         if (comp.zIndexManager) {
22214             comp.zIndexManager.unregister(comp);
22215         }
22216         comp.zIndexManager = this;
22217
22218         this.list[comp.id] = comp;
22219         this.zIndexStack.push(comp);
22220         comp.on('hide', this._activateLast, this);
22221     },
22222
22223     
22224     unregister : function(comp) {
22225         delete comp.zIndexManager;
22226         if (this.list && this.list[comp.id]) {
22227             delete this.list[comp.id];
22228             comp.un('hide', this._activateLast);
22229             Ext.Array.remove(this.zIndexStack, comp);
22230
22231             
22232             this._activateLast(comp);
22233         }
22234     },
22235
22236     
22237     get : function(id) {
22238         return typeof id == "object" ? id : this.list[id];
22239     },
22240
22241    
22242     bringToFront : function(comp) {
22243         comp = this.get(comp);
22244         if (comp != this.front) {
22245             Ext.Array.remove(this.zIndexStack, comp);
22246             this.zIndexStack.push(comp);
22247             this.assignZIndices();
22248             return true;
22249         }
22250         if (comp.modal) {
22251             Ext.getBody().addCls(Ext.baseCSSPrefix + 'body-masked');
22252             this.mask.setSize(Ext.core.Element.getViewWidth(true), Ext.core.Element.getViewHeight(true));
22253             this.mask.show();
22254         }
22255         return false;
22256     },
22257
22258     
22259     sendToBack : function(comp) {
22260         comp = this.get(comp);
22261         Ext.Array.remove(this.zIndexStack, comp);
22262         this.zIndexStack.unshift(comp);
22263         this.assignZIndices();
22264         return comp;
22265     },
22266
22267     
22268     hideAll : function() {
22269         for (var id in this.list) {
22270             if (this.list[id].isComponent && this.list[id].isVisible()) {
22271                 this.list[id].hide();
22272             }
22273         }
22274     },
22275
22276     
22277     hide: function() {
22278         var i = 0,
22279             ln = this.zIndexStack.length,
22280             comp;
22281
22282         this.tempHidden = [];
22283         for (; i < ln; i++) {
22284             comp = this.zIndexStack[i];
22285             if (comp.isVisible()) {
22286                 this.tempHidden.push(comp);
22287                 comp.hide();
22288             }
22289         }
22290     },
22291
22292     
22293     show: function() {
22294         var i = 0,
22295             ln = this.tempHidden.length,
22296             comp,
22297             x,
22298             y;
22299
22300         for (; i < ln; i++) {
22301             comp = this.tempHidden[i];
22302             x = comp.x;
22303             y = comp.y;
22304             comp.show();
22305             comp.setPosition(x, y);
22306         }
22307         delete this.tempHidden;
22308     },
22309
22310     
22311     getActive : function() {
22312         return this.front;
22313     },
22314
22315     
22316     getBy : function(fn, scope) {
22317         var r = [],
22318             i = 0,
22319             len = this.zIndexStack.length,
22320             comp;
22321
22322         for (; i < len; i++) {
22323             comp = this.zIndexStack[i];
22324             if (fn.call(scope||comp, comp) !== false) {
22325                 r.push(comp);
22326             }
22327         }
22328         return r;
22329     },
22330
22331     
22332     each : function(fn, scope) {
22333         var comp;
22334         for (var id in this.list) {
22335             comp = this.list[id];
22336             if (comp.isComponent && fn.call(scope || comp, comp) === false) {
22337                 return;
22338             }
22339         }
22340     },
22341
22342     
22343     eachBottomUp: function (fn, scope) {
22344         var comp,
22345             stack = this.zIndexStack,
22346             i, n;
22347
22348         for (i = 0, n = stack.length ; i < n; i++) {
22349             comp = stack[i];
22350             if (comp.isComponent && fn.call(scope || comp, comp) === false) {
22351                 return;
22352             }
22353         }
22354     },
22355
22356     
22357     eachTopDown: function (fn, scope) {
22358         var comp,
22359             stack = this.zIndexStack,
22360             i;
22361
22362         for (i = stack.length ; i-- > 0; ) {
22363             comp = stack[i];
22364             if (comp.isComponent && fn.call(scope || comp, comp) === false) {
22365                 return;
22366             }
22367         }
22368     },
22369
22370     destroy: function() {
22371         delete this.zIndexStack;
22372         delete this.list;
22373         delete this.container;
22374         delete this.targetEl;
22375     }
22376 }, function() {
22377     
22378     Ext.WindowManager = Ext.WindowMgr = new this();
22379 });
22380
22381
22382 Ext.define('Ext.layout.container.boxOverflow.None', {
22383     
22384     alternateClassName: 'Ext.layout.boxOverflow.None',
22385     
22386     constructor: function(layout, config) {
22387         this.layout = layout;
22388         Ext.apply(this, config || {});
22389     },
22390
22391     handleOverflow: Ext.emptyFn,
22392
22393     clearOverflow: Ext.emptyFn,
22394     
22395     onRemove: Ext.emptyFn,
22396
22397     
22398     getItem: function(item) {
22399         return this.layout.owner.getComponent(item);
22400     },
22401     
22402     onRemove: Ext.emptyFn
22403 });
22404
22405 Ext.define('Ext.util.KeyMap', {
22406     alternateClassName: 'Ext.KeyMap',
22407     
22408     constructor: function(el, binding, eventName){
22409         var me = this;
22410         
22411         Ext.apply(me, {
22412             el: Ext.get(el),
22413             eventName: eventName || me.eventName,
22414             bindings: []
22415         });
22416         if (binding) {
22417             me.addBinding(binding);
22418         }
22419         me.enable();
22420     },
22421     
22422     eventName: 'keydown',
22423
22424     
22425     addBinding : function(binding){
22426         if (Ext.isArray(binding)) {
22427             Ext.each(binding, this.addBinding, this);
22428             return;
22429         }
22430         
22431         var keyCode = binding.key,
22432             processed = false,
22433             key,
22434             keys,
22435             keyString,
22436             i,
22437             len;
22438
22439         if (Ext.isString(keyCode)) {
22440             keys = [];
22441             keyString = keyCode.toLowerCase();
22442             
22443             for (i = 0, len = keyString.length; i < len; ++i){
22444                 keys.push(keyString.charCodeAt(i));
22445             }
22446             keyCode = keys;
22447             processed = true;
22448         }
22449         
22450         if (!Ext.isArray(keyCode)) {
22451             keyCode = [keyCode];
22452         }
22453         
22454         if (!processed) {
22455             for (i = 0, len = keyCode.length; i < len; ++i) {
22456                 key = keyCode[i];
22457                 if (Ext.isString(key)) {
22458                     keyCode[i] = key.toLowerCase().charCodeAt(0);
22459                 }
22460             }
22461         }
22462         
22463         this.bindings.push(Ext.apply({
22464             keyCode: keyCode
22465         }, binding));
22466     },
22467     
22468     
22469     handleKeyDown: function(event) {
22470         if (this.enabled) { 
22471             var bindings = this.bindings,
22472                 i = 0,
22473                 len = bindings.length;
22474                 
22475             event = this.processEvent(event);
22476             for(; i < len; ++i){
22477                 this.processBinding(bindings[i], event);
22478             }
22479         }
22480     },
22481     
22482     
22483     processEvent: function(event){
22484         return event;
22485     },
22486     
22487     
22488     processBinding: function(binding, event){
22489         if (this.checkModifiers(binding, event)) {
22490             var key = event.getKey(),
22491                 handler = binding.fn || binding.handler,
22492                 scope = binding.scope || this,
22493                 keyCode = binding.keyCode,
22494                 defaultEventAction = binding.defaultEventAction,
22495                 i,
22496                 len,
22497                 keydownEvent = new Ext.EventObjectImpl(event);
22498                 
22499             
22500             for (i = 0, len = keyCode.length; i < len; ++i) {
22501                 if (key === keyCode[i]) {
22502                     if (handler.call(scope, key, event) !== true && defaultEventAction) {
22503                         keydownEvent[defaultEventAction]();
22504                     }
22505                     break;
22506                 }
22507             }
22508         }
22509     },
22510     
22511     
22512     checkModifiers: function(binding, e){
22513         var keys = ['shift', 'ctrl', 'alt'],
22514             i = 0,
22515             len = keys.length,
22516             val, key;
22517             
22518         for (; i < len; ++i){
22519             key = keys[i];
22520             val = binding[key];
22521             if (!(val === undefined || (val === e[key + 'Key']))) {
22522                 return false;
22523             }
22524         }
22525         return true;
22526     },
22527
22528     
22529     on: function(key, fn, scope) {
22530         var keyCode, shift, ctrl, alt;
22531         if (Ext.isObject(key) && !Ext.isArray(key)) {
22532             keyCode = key.key;
22533             shift = key.shift;
22534             ctrl = key.ctrl;
22535             alt = key.alt;
22536         } else {
22537             keyCode = key;
22538         }
22539         this.addBinding({
22540             key: keyCode,
22541             shift: shift,
22542             ctrl: ctrl,
22543             alt: alt,
22544             fn: fn,
22545             scope: scope
22546         });
22547     },
22548
22549     
22550     isEnabled : function(){
22551         return this.enabled;
22552     },
22553
22554     
22555     enable: function(){
22556         if(!this.enabled){
22557             this.el.on(this.eventName, this.handleKeyDown, this);
22558             this.enabled = true;
22559         }
22560     },
22561
22562     
22563     disable: function(){
22564         if(this.enabled){
22565             this.el.removeListener(this.eventName, this.handleKeyDown, this);
22566             this.enabled = false;
22567         }
22568     },
22569
22570     
22571     setDisabled : function(disabled){
22572         if (disabled) {
22573             this.disable();
22574         } else {
22575             this.enable();
22576         }
22577     },
22578     
22579     
22580     destroy: function(removeEl){
22581         var me = this;
22582         
22583         me.bindings = [];
22584         me.disable();
22585         if (removeEl === true) {
22586             me.el.remove();
22587         }
22588         delete me.el;
22589     }
22590 });
22591
22592
22593 Ext.define('Ext.util.ClickRepeater', {
22594     extend: 'Ext.util.Observable',
22595
22596     constructor : function(el, config){
22597         this.el = Ext.get(el);
22598         this.el.unselectable();
22599
22600         Ext.apply(this, config);
22601
22602         this.addEvents(
22603         
22604         "mousedown",
22605         
22606         "click",
22607         
22608         "mouseup"
22609         );
22610
22611         if(!this.disabled){
22612             this.disabled = true;
22613             this.enable();
22614         }
22615
22616         
22617         if(this.handler){
22618             this.on("click", this.handler,  this.scope || this);
22619         }
22620
22621         this.callParent();
22622     },
22623
22624     
22625
22626     
22627
22628     
22629
22630     
22631     interval : 20,
22632
22633     
22634     delay: 250,
22635
22636     
22637     preventDefault : true,
22638     
22639     stopDefault : false,
22640
22641     timer : 0,
22642
22643     
22644     enable: function(){
22645         if(this.disabled){
22646             this.el.on('mousedown', this.handleMouseDown, this);
22647             if (Ext.isIE){
22648                 this.el.on('dblclick', this.handleDblClick, this);
22649             }
22650             if(this.preventDefault || this.stopDefault){
22651                 this.el.on('click', this.eventOptions, this);
22652             }
22653         }
22654         this.disabled = false;
22655     },
22656
22657     
22658     disable: function( force){
22659         if(force || !this.disabled){
22660             clearTimeout(this.timer);
22661             if(this.pressedCls){
22662                 this.el.removeCls(this.pressedCls);
22663             }
22664             Ext.getDoc().un('mouseup', this.handleMouseUp, this);
22665             this.el.removeAllListeners();
22666         }
22667         this.disabled = true;
22668     },
22669
22670     
22671     setDisabled: function(disabled){
22672         this[disabled ? 'disable' : 'enable']();
22673     },
22674
22675     eventOptions: function(e){
22676         if(this.preventDefault){
22677             e.preventDefault();
22678         }
22679         if(this.stopDefault){
22680             e.stopEvent();
22681         }
22682     },
22683
22684     
22685     destroy : function() {
22686         this.disable(true);
22687         Ext.destroy(this.el);
22688         this.clearListeners();
22689     },
22690
22691     handleDblClick : function(e){
22692         clearTimeout(this.timer);
22693         this.el.blur();
22694
22695         this.fireEvent("mousedown", this, e);
22696         this.fireEvent("click", this, e);
22697     },
22698
22699     
22700     handleMouseDown : function(e){
22701         clearTimeout(this.timer);
22702         this.el.blur();
22703         if(this.pressedCls){
22704             this.el.addCls(this.pressedCls);
22705         }
22706         this.mousedownTime = new Date();
22707
22708         Ext.getDoc().on("mouseup", this.handleMouseUp, this);
22709         this.el.on("mouseout", this.handleMouseOut, this);
22710
22711         this.fireEvent("mousedown", this, e);
22712         this.fireEvent("click", this, e);
22713
22714         
22715         if (this.accelerate) {
22716             this.delay = 400;
22717         }
22718
22719         
22720         
22721         e = new Ext.EventObjectImpl(e);
22722
22723         this.timer =  Ext.defer(this.click, this.delay || this.interval, this, [e]);
22724     },
22725
22726     
22727     click : function(e){
22728         this.fireEvent("click", this, e);
22729         this.timer =  Ext.defer(this.click, this.accelerate ?
22730             this.easeOutExpo(Ext.Date.getElapsed(this.mousedownTime),
22731                 400,
22732                 -390,
22733                 12000) :
22734             this.interval, this, [e]);
22735     },
22736
22737     easeOutExpo : function (t, b, c, d) {
22738         return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
22739     },
22740
22741     
22742     handleMouseOut : function(){
22743         clearTimeout(this.timer);
22744         if(this.pressedCls){
22745             this.el.removeCls(this.pressedCls);
22746         }
22747         this.el.on("mouseover", this.handleMouseReturn, this);
22748     },
22749
22750     
22751     handleMouseReturn : function(){
22752         this.el.un("mouseover", this.handleMouseReturn, this);
22753         if(this.pressedCls){
22754             this.el.addCls(this.pressedCls);
22755         }
22756         this.click();
22757     },
22758
22759     
22760     handleMouseUp : function(e){
22761         clearTimeout(this.timer);
22762         this.el.un("mouseover", this.handleMouseReturn, this);
22763         this.el.un("mouseout", this.handleMouseOut, this);
22764         Ext.getDoc().un("mouseup", this.handleMouseUp, this);
22765         if(this.pressedCls){
22766             this.el.removeCls(this.pressedCls);
22767         }
22768         this.fireEvent("mouseup", this, e);
22769     }
22770 });
22771
22772
22773 Ext.define('Ext.layout.component.Button', {
22774
22775     
22776
22777     alias: ['layout.button'],
22778
22779     extend: 'Ext.layout.component.Component',
22780
22781     
22782
22783     type: 'button',
22784
22785     cellClsRE: /-btn-(tl|br)\b/,
22786     htmlRE: /<.*>/,
22787
22788     beforeLayout: function() {
22789         return this.callParent(arguments) || this.lastText !== this.owner.text;
22790     },
22791
22792     
22793     onLayout: function(width, height) {
22794         var me = this,
22795             isNum = Ext.isNumber,
22796             owner = me.owner,
22797             ownerEl = owner.el,
22798             btnEl = owner.btnEl,
22799             btnInnerEl = owner.btnInnerEl,
22800             minWidth = owner.minWidth,
22801             maxWidth = owner.maxWidth,
22802             ownerWidth, btnFrameWidth, metrics;
22803
22804         me.getTargetInfo();
22805         me.callParent(arguments);
22806
22807         btnInnerEl.unclip();
22808         me.setTargetSize(width, height);
22809
22810         if (!isNum(width)) {
22811             
22812             
22813             
22814             if (owner.text && Ext.isIE7 && Ext.isStrict && btnEl && btnEl.getWidth() > 20) {
22815                 btnFrameWidth = me.btnFrameWidth;
22816                 metrics = Ext.util.TextMetrics.measure(btnInnerEl, owner.text);
22817                 ownerEl.setWidth(metrics.width + btnFrameWidth + me.adjWidth);
22818                 btnEl.setWidth(metrics.width + btnFrameWidth);
22819                 btnInnerEl.setWidth(metrics.width + btnFrameWidth);
22820             } else {
22821                 
22822                 ownerEl.setWidth(null);
22823                 btnEl.setWidth(null);
22824                 btnInnerEl.setWidth(null);
22825             }
22826
22827             
22828             if (minWidth || maxWidth) {
22829                 ownerWidth = ownerEl.getWidth();
22830                 if (minWidth && (ownerWidth < minWidth)) {
22831                     me.setTargetSize(minWidth, height);
22832                 }
22833                 else if (maxWidth && (ownerWidth > maxWidth)) {
22834                     btnInnerEl.clip();
22835                     me.setTargetSize(maxWidth, height);
22836                 }
22837             }
22838         }
22839
22840         this.lastText = owner.text;
22841     },
22842
22843     setTargetSize: function(width, height) {
22844         var me = this,
22845             owner = me.owner,
22846             isNum = Ext.isNumber,
22847             btnInnerEl = owner.btnInnerEl,
22848             btnWidth = (isNum(width) ? width - me.adjWidth : width),
22849             btnHeight = (isNum(height) ? height - me.adjHeight : height),
22850             btnFrameHeight = me.btnFrameHeight,
22851             text = owner.getText(),
22852             textHeight;
22853
22854         me.callParent(arguments);
22855         me.setElementSize(owner.btnEl, btnWidth, btnHeight);
22856         me.setElementSize(btnInnerEl, btnWidth, btnHeight);
22857         if (isNum(btnHeight)) {
22858             btnInnerEl.setStyle('line-height', btnHeight - btnFrameHeight + 'px');
22859         }
22860
22861         
22862         
22863         
22864         
22865         
22866         if (text && this.htmlRE.test(text)) {
22867             btnInnerEl.setStyle('line-height', 'normal');
22868             textHeight = Ext.util.TextMetrics.measure(btnInnerEl, text).height;
22869             btnInnerEl.setStyle('padding-top', me.btnFrameTop + Math.max(btnInnerEl.getHeight() - btnFrameHeight - textHeight, 0) / 2 + 'px');
22870             me.setElementSize(btnInnerEl, btnWidth, btnHeight);
22871         }
22872     },
22873
22874     getTargetInfo: function() {
22875         var me = this,
22876             owner = me.owner,
22877             ownerEl = owner.el,
22878             frameSize = me.frameSize,
22879             frameBody = owner.frameBody,
22880             btnWrap = owner.btnWrap,
22881             innerEl = owner.btnInnerEl;
22882
22883         if (!('adjWidth' in me)) {
22884             Ext.apply(me, {
22885                 
22886                 adjWidth: frameSize.left + frameSize.right + ownerEl.getBorderWidth('lr') + ownerEl.getPadding('lr') +
22887                           btnWrap.getPadding('lr') + (frameBody ? frameBody.getFrameWidth('lr') : 0),
22888                 adjHeight: frameSize.top + frameSize.bottom + ownerEl.getBorderWidth('tb') + ownerEl.getPadding('tb') +
22889                            btnWrap.getPadding('tb') + (frameBody ? frameBody.getFrameWidth('tb') : 0),
22890                 btnFrameWidth: innerEl.getFrameWidth('lr'),
22891                 btnFrameHeight: innerEl.getFrameWidth('tb'),
22892                 btnFrameTop: innerEl.getFrameWidth('t')
22893             });
22894         }
22895
22896         return me.callParent();
22897     }
22898 });
22899
22900 Ext.define('Ext.util.TextMetrics', {
22901     statics: {
22902         shared: null,
22903         
22904         measure: function(el, text, fixedWidth){
22905             var me = this,
22906                 shared = me.shared;
22907             
22908             if(!shared){
22909                 shared = me.shared = new me(el, fixedWidth);
22910             }
22911             shared.bind(el);
22912             shared.setFixedWidth(fixedWidth || 'auto');
22913             return shared.getSize(text);
22914         },
22915         
22916         
22917          destroy: function(){
22918              var me = this;
22919              Ext.destroy(me.shared);
22920              me.shared = null;
22921          }
22922     },
22923     
22924     
22925     constructor: function(bindTo, fixedWidth){
22926         var measure = this.measure = Ext.getBody().createChild({
22927             cls: 'x-textmetrics'
22928         });
22929         this.el = Ext.get(bindTo);
22930         
22931         measure.position('absolute');
22932         measure.setLeftTop(-1000, -1000);
22933         measure.hide();
22934
22935         if (fixedWidth) {
22936            measure.setWidth(fixedWidth);
22937         }
22938     },
22939     
22940     
22941     getSize: function(text){
22942         var measure = this.measure,
22943             size;
22944         
22945         measure.update(text);
22946         size = measure.getSize();
22947         measure.update('');
22948         return size;
22949     },
22950     
22951     
22952     bind: function(el){
22953         var me = this;
22954         
22955         me.el = Ext.get(el);
22956         me.measure.setStyle(
22957             me.el.getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing')
22958         );
22959     },
22960     
22961     
22962      setFixedWidth : function(width){
22963          this.measure.setWidth(width);
22964      },
22965      
22966      
22967      getWidth : function(text){
22968          this.measure.dom.style.width = 'auto';
22969          return this.getSize(text).width;
22970      },
22971      
22972      
22973      getHeight : function(text){
22974          return this.getSize(text).height;
22975      },
22976      
22977      
22978      destroy: function(){
22979          var me = this;
22980          me.measure.remove();
22981          delete me.el;
22982          delete me.measure;
22983      }
22984 }, function(){
22985     Ext.core.Element.addMethods({
22986         
22987         getTextWidth : function(text, min, max){
22988             return Ext.Number.constrain(Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width, min || 0, max || 1000000);
22989         }
22990     });
22991 });
22992
22993
22994 Ext.define('Ext.layout.container.boxOverflow.Scroller', {
22995
22996     
22997
22998     extend: 'Ext.layout.container.boxOverflow.None',
22999     requires: ['Ext.util.ClickRepeater', 'Ext.core.Element'],
23000     alternateClassName: 'Ext.layout.boxOverflow.Scroller',
23001     mixins: {
23002         observable: 'Ext.util.Observable'
23003     },
23004     
23005     
23006
23007     
23008     animateScroll: false,
23009
23010     
23011     scrollIncrement: 20,
23012
23013     
23014     wheelIncrement: 10,
23015
23016     
23017     scrollRepeatInterval: 60,
23018
23019     
23020     scrollDuration: 400,
23021
23022     
23023
23024     
23025
23026     
23027     scrollerCls: Ext.baseCSSPrefix + 'box-scroller',
23028
23029     
23030
23031     
23032     
23033     constructor: function(layout, config) {
23034         this.layout = layout;
23035         Ext.apply(this, config || {});
23036         
23037         this.addEvents(
23038             
23039             'scroll'
23040         );
23041     },
23042     
23043     initCSSClasses: function() {
23044         var me = this,
23045         layout = me.layout;
23046
23047         if (!me.CSSinitialized) {
23048             me.beforeCtCls = me.beforeCtCls || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelBefore;
23049             me.afterCtCls  = me.afterCtCls  || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelAfter;
23050             me.beforeScrollerCls = me.beforeScrollerCls || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelBefore;
23051             me.afterScrollerCls  = me.afterScrollerCls  || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelAfter;
23052             me.CSSinitializes = true;
23053         }
23054     },
23055
23056     handleOverflow: function(calculations, targetSize) {
23057         var me = this,
23058             layout = me.layout,
23059             methodName = 'get' + layout.parallelPrefixCap,
23060             newSize = {};
23061
23062         me.initCSSClasses();
23063         me.callParent(arguments);
23064         this.createInnerElements();
23065         this.showScrollers();
23066         newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
23067         newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - (me.beforeCt[methodName]() + me.afterCt[methodName]());
23068         return { targetSize: newSize };
23069     },
23070
23071     
23072     createInnerElements: function() {
23073         var me = this,
23074             target = me.layout.getRenderTarget();
23075
23076         
23077         
23078         if (!me.beforeCt) {
23079             target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
23080             me.beforeCt = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.beforeCtCls}, 'before');
23081             me.afterCt  = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.afterCtCls},  'after');
23082             me.createWheelListener();
23083         }
23084     },
23085
23086     
23087     createWheelListener: function() {
23088         this.layout.innerCt.on({
23089             scope     : this,
23090             mousewheel: function(e) {
23091                 e.stopEvent();
23092
23093                 this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
23094             }
23095         });
23096     },
23097
23098     
23099     clearOverflow: function() {
23100         this.hideScrollers();
23101     },
23102
23103     
23104     showScrollers: function() {
23105         this.createScrollers();
23106         this.beforeScroller.show();
23107         this.afterScroller.show();
23108         this.updateScrollButtons();
23109         
23110         this.layout.owner.addClsWithUI('scroller');
23111     },
23112
23113     
23114     hideScrollers: function() {
23115         if (this.beforeScroller != undefined) {
23116             this.beforeScroller.hide();
23117             this.afterScroller.hide();
23118             
23119             this.layout.owner.removeClsWithUI('scroller');
23120         }
23121     },
23122
23123     
23124     createScrollers: function() {
23125         if (!this.beforeScroller && !this.afterScroller) {
23126             var before = this.beforeCt.createChild({
23127                 cls: Ext.String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
23128             });
23129
23130             var after = this.afterCt.createChild({
23131                 cls: Ext.String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
23132             });
23133
23134             before.addClsOnOver(this.beforeScrollerCls + '-hover');
23135             after.addClsOnOver(this.afterScrollerCls + '-hover');
23136
23137             before.setVisibilityMode(Ext.core.Element.DISPLAY);
23138             after.setVisibilityMode(Ext.core.Element.DISPLAY);
23139
23140             this.beforeRepeater = Ext.create('Ext.util.ClickRepeater', before, {
23141                 interval: this.scrollRepeatInterval,
23142                 handler : this.scrollLeft,
23143                 scope   : this
23144             });
23145
23146             this.afterRepeater = Ext.create('Ext.util.ClickRepeater', after, {
23147                 interval: this.scrollRepeatInterval,
23148                 handler : this.scrollRight,
23149                 scope   : this
23150             });
23151
23152             
23153             this.beforeScroller = before;
23154
23155             
23156             this.afterScroller = after;
23157         }
23158     },
23159
23160     
23161     destroy: function() {
23162         Ext.destroy(this.beforeRepeater, this.afterRepeater, this.beforeScroller, this.afterScroller, this.beforeCt, this.afterCt);
23163     },
23164
23165     
23166     scrollBy: function(delta, animate) {
23167         this.scrollTo(this.getScrollPosition() + delta, animate);
23168     },
23169
23170     
23171     getScrollAnim: function() {
23172         return {
23173             duration: this.scrollDuration, 
23174             callback: this.updateScrollButtons, 
23175             scope   : this
23176         };
23177     },
23178
23179     
23180     updateScrollButtons: function() {
23181         if (this.beforeScroller == undefined || this.afterScroller == undefined) {
23182             return;
23183         }
23184
23185         var beforeMeth = this.atExtremeBefore()  ? 'addCls' : 'removeCls',
23186             afterMeth  = this.atExtremeAfter() ? 'addCls' : 'removeCls',
23187             beforeCls  = this.beforeScrollerCls + '-disabled',
23188             afterCls   = this.afterScrollerCls  + '-disabled';
23189         
23190         this.beforeScroller[beforeMeth](beforeCls);
23191         this.afterScroller[afterMeth](afterCls);
23192         this.scrolling = false;
23193     },
23194
23195     
23196     atExtremeBefore: function() {
23197         return this.getScrollPosition() === 0;
23198     },
23199
23200     
23201     scrollLeft: function() {
23202         this.scrollBy(-this.scrollIncrement, false);
23203     },
23204
23205     
23206     scrollRight: function() {
23207         this.scrollBy(this.scrollIncrement, false);
23208     },
23209
23210     
23211     getScrollPosition: function(){
23212         var layout = this.layout;
23213         return parseInt(layout.innerCt.dom['scroll' + layout.parallelBeforeCap], 10) || 0;
23214     },
23215
23216     
23217     getMaxScrollPosition: function() {
23218         var layout = this.layout;
23219         return layout.innerCt.dom['scroll' + layout.parallelPrefixCap] - this.layout.innerCt['get' + layout.parallelPrefixCap]();
23220     },
23221
23222     
23223     atExtremeAfter: function() {
23224         return this.getScrollPosition() >= this.getMaxScrollPosition();
23225     },
23226
23227     
23228     scrollTo: function(position, animate) {
23229         var me = this,
23230             layout = me.layout,
23231             oldPosition = me.getScrollPosition(),
23232             newPosition = Ext.Number.constrain(position, 0, me.getMaxScrollPosition());
23233
23234         if (newPosition != oldPosition && !me.scrolling) {
23235             if (animate == undefined) {
23236                 animate = me.animateScroll;
23237             }
23238
23239             layout.innerCt.scrollTo(layout.parallelBefore, newPosition, animate ? me.getScrollAnim() : false);
23240             if (animate) {
23241                 me.scrolling = true;
23242             } else {
23243                 me.scrolling = false;
23244                 me.updateScrollButtons();
23245             }
23246             
23247             me.fireEvent('scroll', me, newPosition, animate ? me.getScrollAnim() : false);
23248         }
23249     },
23250
23251     
23252     scrollToItem: function(item, animate) {
23253         var me = this,
23254             layout = me.layout,
23255             visibility,
23256             box,
23257             newPos;
23258
23259         item = me.getItem(item);
23260         if (item != undefined) {
23261             visibility = this.getItemVisibility(item);
23262             if (!visibility.fullyVisible) {
23263                 box  = item.getBox(true, true);
23264                 newPos = box[layout.parallelPosition];
23265                 if (visibility.hiddenEnd) {
23266                     newPos -= (this.layout.innerCt['get' + layout.parallelPrefixCap]() - box[layout.parallelPrefix]);
23267                 }
23268                 this.scrollTo(newPos, animate);
23269             }
23270         }
23271     },
23272
23273     
23274     getItemVisibility: function(item) {
23275         var me          = this,
23276             box         = me.getItem(item).getBox(true, true),
23277             layout      = me.layout,
23278             itemStart   = box[layout.parallelPosition],
23279             itemEnd     = itemStart + box[layout.parallelPrefix],
23280             scrollStart = me.getScrollPosition(),
23281             scrollEnd   = scrollStart + layout.innerCt['get' + layout.parallelPrefixCap]();
23282
23283         return {
23284             hiddenStart : itemStart < scrollStart,
23285             hiddenEnd   : itemEnd > scrollEnd,
23286             fullyVisible: itemStart > scrollStart && itemEnd < scrollEnd
23287         };
23288     }
23289 });
23290
23291 Ext.define('Ext.util.Offset', {
23292
23293     
23294
23295     statics: {
23296         fromObject: function(obj) {
23297             return new this(obj.x, obj.y);
23298         }
23299     },
23300
23301     
23302
23303     constructor: function(x, y) {
23304         this.x = (x != null && !isNaN(x)) ? x : 0;
23305         this.y = (y != null && !isNaN(y)) ? y : 0;
23306
23307         return this;
23308     },
23309
23310     copy: function() {
23311         return new Ext.util.Offset(this.x, this.y);
23312     },
23313
23314     copyFrom: function(p) {
23315         this.x = p.x;
23316         this.y = p.y;
23317     },
23318
23319     toString: function() {
23320         return "Offset[" + this.x + "," + this.y + "]";
23321     },
23322
23323     equals: function(offset) {
23324         if(!(offset instanceof this.statics())) {
23325             Ext.Error.raise('Offset must be an instance of Ext.util.Offset');
23326         }
23327
23328         return (this.x == offset.x && this.y == offset.y);
23329     },
23330
23331     round: function(to) {
23332         if (!isNaN(to)) {
23333             var factor = Math.pow(10, to);
23334             this.x = Math.round(this.x * factor) / factor;
23335             this.y = Math.round(this.y * factor) / factor;
23336         } else {
23337             this.x = Math.round(this.x);
23338             this.y = Math.round(this.y);
23339         }
23340     },
23341
23342     isZero: function() {
23343         return this.x == 0 && this.y == 0;
23344     }
23345 });
23346
23347
23348 Ext.define('Ext.util.KeyNav', {
23349     
23350     alternateClassName: 'Ext.KeyNav',
23351     
23352     requires: ['Ext.util.KeyMap'],
23353     
23354     statics: {
23355         keyOptions: {
23356             left: 37,
23357             right: 39,
23358             up: 38,
23359             down: 40,
23360             space: 32,
23361             pageUp: 33,
23362             pageDown: 34,
23363             del: 46,
23364             backspace: 8,
23365             home: 36,
23366             end: 35,
23367             enter: 13,
23368             esc: 27,
23369             tab: 9
23370         }
23371     },
23372     
23373     constructor: function(el, config){
23374         this.setConfig(el, config || {});
23375     },
23376     
23377     
23378     setConfig: function(el, config) {
23379         if (this.map) {
23380             this.map.destroy();
23381         }
23382         
23383         var map = Ext.create('Ext.util.KeyMap', el, null, this.getKeyEvent('forceKeyDown' in config ? config.forceKeyDown : this.forceKeyDown)),
23384             keys = Ext.util.KeyNav.keyOptions,
23385             scope = config.scope || this,
23386             key;
23387         
23388         this.map = map;
23389         for (key in keys) {
23390             if (keys.hasOwnProperty(key)) {
23391                 if (config[key]) {
23392                     map.addBinding({
23393                         scope: scope,
23394                         key: keys[key],
23395                         handler: Ext.Function.bind(this.handleEvent, scope, [config[key]], true),
23396                         defaultEventAction: config.defaultEventAction || this.defaultEventAction
23397                     });
23398                 }
23399             }
23400         }
23401         
23402         map.disable();
23403         if (!config.disabled) {
23404             map.enable();
23405         }
23406     },
23407     
23408     
23409     handleEvent: function(map, event, handler){
23410         return handler.call(this, event);
23411     },
23412     
23413     
23414     disabled: false,
23415     
23416     
23417     defaultEventAction: "stopEvent",
23418     
23419     
23420     forceKeyDown: false,
23421     
23422     
23423     destroy: function(removeEl){
23424         this.map.destroy(removeEl);
23425         delete this.map;
23426     },
23427
23428     
23429     enable: function() {
23430         this.map.enable();
23431         this.disabled = false;
23432     },
23433
23434     
23435     disable: function() {
23436         this.map.disable();
23437         this.disabled = true;
23438     },
23439     
23440     
23441     setDisabled : function(disabled){
23442         this.map.setDisabled(disabled);
23443         this.disabled = disabled;
23444     },
23445     
23446     
23447     getKeyEvent: function(forceKeyDown){
23448         return (forceKeyDown || Ext.EventManager.useKeyDown) ? 'keydown' : 'keypress';
23449     }
23450 });
23451
23452
23453
23454 Ext.define('Ext.fx.Queue', {
23455
23456     requires: ['Ext.util.HashMap'],
23457
23458     constructor: function() {
23459         this.targets = Ext.create('Ext.util.HashMap');
23460         this.fxQueue = {};
23461     },
23462
23463     
23464     getFxDefaults: function(targetId) {
23465         var target = this.targets.get(targetId);
23466         if (target) {
23467             return target.fxDefaults;
23468         }
23469         return {};
23470     },
23471
23472     
23473     setFxDefaults: function(targetId, obj) {
23474         var target = this.targets.get(targetId);
23475         if (target) {
23476             target.fxDefaults = Ext.apply(target.fxDefaults || {}, obj);
23477         }
23478     },
23479
23480     
23481     stopAnimation: function(targetId) {
23482         var me = this,
23483             queue = me.getFxQueue(targetId),
23484             ln = queue.length;
23485         while (ln) {
23486             queue[ln - 1].end();
23487             ln--;
23488         }
23489     },
23490
23491     
23492     getActiveAnimation: function(targetId) {
23493         var queue = this.getFxQueue(targetId);
23494         return (queue && !!queue.length) ? queue[0] : false;
23495     },
23496
23497     
23498     hasFxBlock: function(targetId) {
23499         var queue = this.getFxQueue(targetId);
23500         return queue && queue[0] && queue[0].block;
23501     },
23502
23503     
23504     getFxQueue: function(targetId) {
23505         if (!targetId) {
23506             return false;
23507         }
23508         var me = this,
23509             queue = me.fxQueue[targetId],
23510             target = me.targets.get(targetId);
23511
23512         if (!target) {
23513             return false;
23514         }
23515
23516         if (!queue) {
23517             me.fxQueue[targetId] = [];
23518             
23519             if (target.type != 'element') {
23520                 target.target.on('destroy', function() {
23521                     me.fxQueue[targetId] = [];
23522                 });
23523             }
23524         }
23525         return me.fxQueue[targetId];
23526     },
23527
23528     
23529     queueFx: function(anim) {
23530         var me = this,
23531             target = anim.target,
23532             queue, ln;
23533
23534         if (!target) {
23535             return;
23536         }
23537
23538         queue = me.getFxQueue(target.getId());
23539         ln = queue.length;
23540
23541         if (ln) {
23542             if (anim.concurrent) {
23543                 anim.paused = false;
23544             }
23545             else {
23546                 queue[ln - 1].on('afteranimate', function() {
23547                     anim.paused = false;
23548                 });
23549             }
23550         }
23551         else {
23552             anim.paused = false;
23553         }
23554         anim.on('afteranimate', function() {
23555             Ext.Array.remove(queue, anim);
23556             if (anim.remove) {
23557                 if (target.type == 'element') {
23558                     var el = Ext.get(target.id);
23559                     if (el) {
23560                         el.remove();
23561                     }
23562                 }
23563             }
23564         }, this);
23565         queue.push(anim);
23566     }
23567 });
23568
23569
23570 Ext.define('Ext.fx.target.Target', {
23571
23572     isAnimTarget: true,
23573
23574     constructor: function(target) {
23575         this.target = target;
23576         this.id = this.getId();
23577     },
23578     
23579     getId: function() {
23580         return this.target.id;
23581     }
23582 });
23583
23584
23585
23586 Ext.define('Ext.fx.target.Sprite', {
23587
23588     
23589
23590     extend: 'Ext.fx.target.Target',
23591
23592     
23593
23594     type: 'draw',
23595
23596     getFromPrim: function(sprite, attr) {
23597         var o;
23598         if (attr == 'translate') {
23599             o = {
23600                 x: sprite.attr.translation.x || 0,
23601                 y: sprite.attr.translation.y || 0
23602             };
23603         }
23604         else if (attr == 'rotate') {
23605             o = {
23606                 degrees: sprite.attr.rotation.degrees || 0,
23607                 x: sprite.attr.rotation.x,
23608                 y: sprite.attr.rotation.y
23609             };
23610         }
23611         else {
23612             o = sprite.attr[attr];
23613         }
23614         return o;
23615     },
23616
23617     getAttr: function(attr, val) {
23618         return [[this.target, val != undefined ? val : this.getFromPrim(this.target, attr)]];
23619     },
23620
23621     setAttr: function(targetData) {
23622         var ln = targetData.length,
23623             spriteArr = [],
23624             attrs, attr, attrArr, attPtr, spritePtr, idx, value, i, j, x, y, ln2;
23625         for (i = 0; i < ln; i++) {
23626             attrs = targetData[i].attrs;
23627             for (attr in attrs) {
23628                 attrArr = attrs[attr];
23629                 ln2 = attrArr.length;
23630                 for (j = 0; j < ln2; j++) {
23631                     spritePtr = attrArr[j][0];
23632                     attPtr = attrArr[j][1];
23633                     if (attr === 'translate') {
23634                         value = {
23635                             x: attPtr.x,
23636                             y: attPtr.y
23637                         };
23638                     }
23639                     else if (attr === 'rotate') {
23640                         x = attPtr.x;
23641                         if (isNaN(x)) {
23642                             x = null;
23643                         }
23644                         y = attPtr.y;
23645                         if (isNaN(y)) {
23646                             y = null;
23647                         }
23648                         value = {
23649                             degrees: attPtr.degrees,
23650                             x: x,
23651                             y: y
23652                         };
23653                     }
23654                     else if (attr === 'width' || attr === 'height' || attr === 'x' || attr === 'y') {
23655                         value = parseFloat(attPtr);
23656                     }
23657                     else {
23658                         value = attPtr;
23659                     }
23660                     idx = Ext.Array.indexOf(spriteArr, spritePtr);
23661                     if (idx == -1) {
23662                         spriteArr.push([spritePtr, {}]);
23663                         idx = spriteArr.length - 1;
23664                     }
23665                     spriteArr[idx][1][attr] = value;
23666                 }
23667             }
23668         }
23669         ln = spriteArr.length;
23670         for (i = 0; i < ln; i++) {
23671             spritePtr = spriteArr[i];
23672             spritePtr[0].setAttributes(spritePtr[1]);
23673         }
23674         this.target.redraw();
23675     }
23676 });
23677
23678
23679
23680 Ext.define('Ext.fx.target.CompositeSprite', {
23681
23682     
23683
23684     extend: 'Ext.fx.target.Sprite',
23685
23686     
23687
23688     getAttr: function(attr, val) {
23689         var out = [],
23690             target = this.target;
23691         target.each(function(sprite) {
23692             out.push([sprite, val != undefined ? val : this.getFromPrim(sprite, attr)]);
23693         }, this);
23694         return out;
23695     }
23696 });
23697
23698
23699 Ext.define('Ext.fx.target.Component', {
23700
23701     
23702    
23703     extend: 'Ext.fx.target.Target',
23704     
23705     
23706
23707     type: 'component',
23708
23709     
23710     getPropMethod: {
23711         top: function() {
23712             return this.getPosition(true)[1];
23713         },
23714         left: function() {
23715             return this.getPosition(true)[0];
23716         },
23717         x: function() {
23718             return this.getPosition()[0];
23719         },
23720         y: function() {
23721             return this.getPosition()[1];
23722         },
23723         height: function() {
23724             return this.getHeight();
23725         },
23726         width: function() {
23727             return this.getWidth();
23728         },
23729         opacity: function() {
23730             return this.el.getStyle('opacity');
23731         }
23732     },
23733
23734     compMethod: {
23735         top: 'setPosition',
23736         left: 'setPosition',
23737         x: 'setPagePosition',
23738         y: 'setPagePosition',
23739         height: 'setSize',
23740         width: 'setSize',
23741         opacity: 'setOpacity'
23742     },
23743
23744     
23745     getAttr: function(attr, val) {
23746         return [[this.target, val !== undefined ? val : this.getPropMethod[attr].call(this.target)]];
23747     },
23748
23749     setAttr: function(targetData, isFirstFrame, isLastFrame) {
23750         var me = this,
23751             target = me.target,
23752             ln = targetData.length,
23753             attrs, attr, o, i, j, meth, targets, left, top, w, h;
23754         for (i = 0; i < ln; i++) {
23755             attrs = targetData[i].attrs;
23756             for (attr in attrs) {
23757                 targets = attrs[attr].length;
23758                 meth = {
23759                     setPosition: {},
23760                     setPagePosition: {},
23761                     setSize: {},
23762                     setOpacity: {}
23763                 };
23764                 for (j = 0; j < targets; j++) {
23765                     o = attrs[attr][j];
23766                     
23767                     
23768                     
23769                     
23770                     meth[me.compMethod[attr]].target = o[0];
23771                     meth[me.compMethod[attr]][attr] = o[1];
23772                 }
23773                 if (meth.setPosition.target) {
23774                     o = meth.setPosition;
23775                     left = (o.left === undefined) ? undefined : parseInt(o.left, 10);
23776                     top = (o.top === undefined) ? undefined : parseInt(o.top, 10);
23777                     o.target.setPosition(left, top);
23778                 }
23779                 if (meth.setPagePosition.target) {
23780                     o = meth.setPagePosition;
23781                     o.target.setPagePosition(o.x, o.y);
23782                 }
23783                 if (meth.setSize.target) {
23784                     o = meth.setSize;
23785                     
23786                     w = (o.width === undefined) ? o.target.getWidth() : parseInt(o.width, 10);
23787                     h = (o.height === undefined) ? o.target.getHeight() : parseInt(o.height, 10);
23788
23789                     
23790                     
23791                     
23792                     
23793                     
23794                     
23795                     
23796                     if (isLastFrame || me.dynamic) {
23797                         o.target.componentLayout.childrenChanged = true;
23798
23799                         
23800                         if (me.layoutAnimation) {
23801                             o.target.setCalculatedSize(w, h);
23802                         } else {
23803                             o.target.setSize(w, h);
23804                         }
23805                     }
23806                     else {
23807                         o.target.el.setSize(w, h);
23808                     }
23809                 }
23810                 if (meth.setOpacity.target) {
23811                     o = meth.setOpacity;
23812                     o.target.el.setStyle('opacity', o.opacity);
23813                 }
23814             }
23815         }
23816     }
23817 });
23818
23819
23820 Ext.define('Ext.fx.CubicBezier', {
23821
23822     
23823
23824     singleton: true,
23825
23826     
23827
23828     cubicBezierAtTime: function(t, p1x, p1y, p2x, p2y, duration) {
23829         var cx = 3 * p1x,
23830             bx = 3 * (p2x - p1x) - cx,
23831             ax = 1 - cx - bx,
23832             cy = 3 * p1y,
23833             by = 3 * (p2y - p1y) - cy,
23834             ay = 1 - cy - by;
23835         function sampleCurveX(t) {
23836             return ((ax * t + bx) * t + cx) * t;
23837         }
23838         function solve(x, epsilon) {
23839             var t = solveCurveX(x, epsilon);
23840             return ((ay * t + by) * t + cy) * t;
23841         }
23842         function solveCurveX(x, epsilon) {
23843             var t0, t1, t2, x2, d2, i;
23844             for (t2 = x, i = 0; i < 8; i++) {
23845                 x2 = sampleCurveX(t2) - x;
23846                 if (Math.abs(x2) < epsilon) {
23847                     return t2;
23848                 }
23849                 d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
23850                 if (Math.abs(d2) < 1e-6) {
23851                     break;
23852                 }
23853                 t2 = t2 - x2 / d2;
23854             }
23855             t0 = 0;
23856             t1 = 1;
23857             t2 = x;
23858             if (t2 < t0) {
23859                 return t0;
23860             }
23861             if (t2 > t1) {
23862                 return t1;
23863             }
23864             while (t0 < t1) {
23865                 x2 = sampleCurveX(t2);
23866                 if (Math.abs(x2 - x) < epsilon) {
23867                     return t2;
23868                 }
23869                 if (x > x2) {
23870                     t0 = t2;
23871                 } else {
23872                     t1 = t2;
23873                 }
23874                 t2 = (t1 - t0) / 2 + t0;
23875             }
23876             return t2;
23877         }
23878         return solve(t, 1 / (200 * duration));
23879     },
23880
23881     cubicBezier: function(x1, y1, x2, y2) {
23882         var fn = function(pos) {
23883             return Ext.fx.CubicBezier.cubicBezierAtTime(pos, x1, y1, x2, y2, 1);
23884         };
23885         fn.toCSS3 = function() {
23886             return 'cubic-bezier(' + [x1, y1, x2, y2].join(',') + ')';
23887         };
23888         fn.reverse = function() {
23889             return Ext.fx.CubicBezier.cubicBezier(1 - x2, 1 - y2, 1 - x1, 1 - y1);
23890         };
23891         return fn;
23892     }
23893 });
23894
23895 Ext.define('Ext.draw.Color', {
23896
23897     
23898
23899     
23900
23901     colorToHexRe: /(.*?)rgb\((\d+),\s*(\d+),\s*(\d+)\)/,
23902     rgbRe: /\s*rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)\s*/,
23903     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*/,
23904
23905     
23906     lightnessFactor: 0.2,
23907
23908     
23909     constructor : function(red, green, blue) {
23910         var me = this,
23911             clamp = Ext.Number.constrain;
23912         me.r = clamp(red, 0, 255);
23913         me.g = clamp(green, 0, 255);
23914         me.b = clamp(blue, 0, 255);
23915     },
23916
23917     
23918     getRed: function() {
23919         return this.r;
23920     },
23921
23922     
23923     getGreen: function() {
23924         return this.g;
23925     },
23926
23927     
23928     getBlue: function() {
23929         return this.b;
23930     },
23931
23932     
23933     getRGB: function() {
23934         var me = this;
23935         return [me.r, me.g, me.b];
23936     },
23937
23938     
23939     getHSL: function() {
23940         var me = this,
23941             r = me.r / 255,
23942             g = me.g / 255,
23943             b = me.b / 255,
23944             max = Math.max(r, g, b),
23945             min = Math.min(r, g, b),
23946             delta = max - min,
23947             h,
23948             s = 0,
23949             l = 0.5 * (max + min);
23950
23951         
23952         if (min != max) {
23953             s = (l < 0.5) ? delta / (max + min) : delta / (2 - max - min);
23954             if (r == max) {
23955                 h = 60 * (g - b) / delta;
23956             } else if (g == max) {
23957                 h = 120 + 60 * (b - r) / delta;
23958             } else {
23959                 h = 240 + 60 * (r - g) / delta;
23960             }
23961             if (h < 0) {
23962                 h += 360;
23963             }
23964             if (h >= 360) {
23965                 h -= 360;
23966             }
23967         }
23968         return [h, s, l];
23969     },
23970
23971     
23972     getLighter: function(factor) {
23973         var hsl = this.getHSL();
23974         factor = factor || this.lightnessFactor;
23975         hsl[2] = Ext.Number.constrain(hsl[2] + factor, 0, 1);
23976         return this.fromHSL(hsl[0], hsl[1], hsl[2]);
23977     },
23978
23979     
23980     getDarker: function(factor) {
23981         factor = factor || this.lightnessFactor;
23982         return this.getLighter(-factor);
23983     },
23984
23985     
23986     toString: function() {
23987         var me = this,
23988             round = Math.round,
23989             r = round(me.r).toString(16),
23990             g = round(me.g).toString(16),
23991             b = round(me.b).toString(16);
23992         r = (r.length == 1) ? '0' + r : r;
23993         g = (g.length == 1) ? '0' + g : g;
23994         b = (b.length == 1) ? '0' + b : b;
23995         return ['#', r, g, b].join('');
23996     },
23997
23998     
23999     toHex: function(color) {
24000         if (Ext.isArray(color)) {
24001             color = color[0];
24002         }
24003         if (!Ext.isString(color)) {
24004             return '';
24005         }
24006         if (color.substr(0, 1) === '#') {
24007             return color;
24008         }
24009         var digits = this.colorToHexRe.exec(color);
24010
24011         if (Ext.isArray(digits)) {
24012             var red = parseInt(digits[2], 10),
24013                 green = parseInt(digits[3], 10),
24014                 blue = parseInt(digits[4], 10),
24015                 rgb = blue | (green << 8) | (red << 16);
24016             return digits[1] + '#' + ("000000" + rgb.toString(16)).slice(-6);
24017         }
24018         else {
24019             return '';
24020         }
24021     },
24022
24023     
24024     fromString: function(str) {
24025         var values, r, g, b,
24026             parse = parseInt;
24027
24028         if ((str.length == 4 || str.length == 7) && str.substr(0, 1) === '#') {
24029             values = str.match(this.hexRe);
24030             if (values) {
24031                 r = parse(values[1], 16) >> 0;
24032                 g = parse(values[2], 16) >> 0;
24033                 b = parse(values[3], 16) >> 0;
24034                 if (str.length == 4) {
24035                     r += (r * 16);
24036                     g += (g * 16);
24037                     b += (b * 16);
24038                 }
24039             }
24040         }
24041         else {
24042             values = str.match(this.rgbRe);
24043             if (values) {
24044                 r = values[1];
24045                 g = values[2];
24046                 b = values[3];
24047             }
24048         }
24049
24050         return (typeof r == 'undefined') ? undefined : Ext.create('Ext.draw.Color', r, g, b);
24051     },
24052
24053     
24054     getGrayscale: function() {
24055         
24056         return this.r * 0.3 + this.g * 0.59 + this.b * 0.11;
24057     },
24058
24059     
24060     fromHSL: function(h, s, l) {
24061         var C, X, m, i, rgb = [],
24062             abs = Math.abs,
24063             floor = Math.floor;
24064
24065         if (s == 0 || h == null) {
24066             
24067             rgb = [l, l, l];
24068         }
24069         else {
24070             
24071             
24072             
24073             
24074             h /= 60;
24075             C = s * (1 - abs(2 * l - 1));
24076             X = C * (1 - abs(h - 2 * floor(h / 2) - 1));
24077             m = l - C / 2;
24078             switch (floor(h)) {
24079                 case 0:
24080                     rgb = [C, X, 0];
24081                     break;
24082                 case 1:
24083                     rgb = [X, C, 0];
24084                     break;
24085                 case 2:
24086                     rgb = [0, C, X];
24087                     break;
24088                 case 3:
24089                     rgb = [0, X, C];
24090                     break;
24091                 case 4:
24092                     rgb = [X, 0, C];
24093                     break;
24094                 case 5:
24095                     rgb = [C, 0, X];
24096                     break;
24097             }
24098             rgb = [rgb[0] + m, rgb[1] + m, rgb[2] + m];
24099         }
24100         return Ext.create('Ext.draw.Color', rgb[0] * 255, rgb[1] * 255, rgb[2] * 255);
24101     }
24102 }, function() {
24103     var prototype = this.prototype;
24104
24105     
24106     this.addStatics({
24107         fromHSL: function() {
24108             return prototype.fromHSL.apply(prototype, arguments);
24109         },
24110         fromString: function() {
24111             return prototype.fromString.apply(prototype, arguments);
24112         },
24113         toHex: function() {
24114             return prototype.toHex.apply(prototype, arguments);
24115         }
24116     });
24117 });
24118
24119
24120 Ext.define('Ext.dd.StatusProxy', {
24121     animRepair: false,
24122
24123     constructor: function(config){
24124         Ext.apply(this, config);
24125         this.id = this.id || Ext.id();
24126         this.proxy = Ext.createWidget('component', {
24127             floating: true,
24128             id: this.id,
24129             html: '<div class="' + Ext.baseCSSPrefix + 'dd-drop-icon"></div>' +
24130                   '<div class="' + Ext.baseCSSPrefix + 'dd-drag-ghost"></div>',
24131             cls: Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed,
24132             shadow: !config || config.shadow !== false,
24133             renderTo: document.body
24134         });
24135
24136         this.el = this.proxy.el;
24137         this.el.show();
24138         this.el.setVisibilityMode(Ext.core.Element.VISIBILITY);
24139         this.el.hide();
24140
24141         this.ghost = Ext.get(this.el.dom.childNodes[1]);
24142         this.dropStatus = this.dropNotAllowed;
24143     },
24144     
24145     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
24146     
24147     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
24148
24149     
24150     setStatus : function(cssClass){
24151         cssClass = cssClass || this.dropNotAllowed;
24152         if(this.dropStatus != cssClass){
24153             this.el.replaceCls(this.dropStatus, cssClass);
24154             this.dropStatus = cssClass;
24155         }
24156     },
24157
24158     
24159     reset : function(clearGhost){
24160         this.el.dom.className = Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed;
24161         this.dropStatus = this.dropNotAllowed;
24162         if(clearGhost){
24163             this.ghost.update("");
24164         }
24165     },
24166
24167     
24168     update : function(html){
24169         if(typeof html == "string"){
24170             this.ghost.update(html);
24171         }else{
24172             this.ghost.update("");
24173             html.style.margin = "0";
24174             this.ghost.dom.appendChild(html);
24175         }
24176         var el = this.ghost.dom.firstChild; 
24177         if(el){
24178             Ext.fly(el).setStyle('float', 'none');
24179         }
24180     },
24181
24182     
24183     getEl : function(){
24184         return this.el;
24185     },
24186
24187     
24188     getGhost : function(){
24189         return this.ghost;
24190     },
24191
24192     
24193     hide : function(clear) {
24194         this.proxy.hide();
24195         if (clear) {
24196             this.reset(true);
24197         }
24198     },
24199
24200     
24201     stop : function(){
24202         if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
24203             this.anim.stop();
24204         }
24205     },
24206
24207     
24208     show : function() {
24209         this.proxy.show();
24210         this.proxy.toFront();
24211     },
24212
24213     
24214     sync : function(){
24215         this.proxy.el.sync();
24216     },
24217
24218     
24219     repair : function(xy, callback, scope){
24220         this.callback = callback;
24221         this.scope = scope;
24222         if (xy && this.animRepair !== false) {
24223             this.el.addCls(Ext.baseCSSPrefix + 'dd-drag-repair');
24224             this.el.hideUnders(true);
24225             this.anim = this.el.animate({
24226                 duration: this.repairDuration || 500,
24227                 easing: 'ease-out',
24228                 to: {
24229                     x: xy[0],
24230                     y: xy[1]
24231                 },
24232                 stopAnimation: true,
24233                 callback: this.afterRepair,
24234                 scope: this
24235             });
24236         } else {
24237             this.afterRepair();
24238         }
24239     },
24240
24241     
24242     afterRepair : function(){
24243         this.hide(true);
24244         if(typeof this.callback == "function"){
24245             this.callback.call(this.scope || this);
24246         }
24247         this.callback = null;
24248         this.scope = null;
24249     },
24250
24251     destroy: function(){
24252         Ext.destroy(this.ghost, this.proxy, this.el);
24253     }
24254 });
24255
24256 Ext.define('Ext.panel.Proxy', {
24257     
24258     alternateClassName: 'Ext.dd.PanelProxy',
24259     
24260     constructor: function(panel, config){
24261         
24262         this.panel = panel;
24263         this.id = this.panel.id +'-ddproxy';
24264         Ext.apply(this, config);
24265     },
24266
24267     
24268     insertProxy: true,
24269
24270     
24271     setStatus: Ext.emptyFn,
24272     reset: Ext.emptyFn,
24273     update: Ext.emptyFn,
24274     stop: Ext.emptyFn,
24275     sync: Ext.emptyFn,
24276
24277     
24278     getEl: function(){
24279         return this.ghost.el;
24280     },
24281
24282     
24283     getGhost: function(){
24284         return this.ghost;
24285     },
24286
24287     
24288     getProxy: function(){
24289         return this.proxy;
24290     },
24291
24292     
24293     hide : function(){
24294         if (this.ghost) {
24295             if (this.proxy) {
24296                 this.proxy.remove();
24297                 delete this.proxy;
24298             }
24299
24300             
24301             this.panel.unghost(null, false);
24302             delete this.ghost;
24303         }
24304     },
24305
24306     
24307     show: function(){
24308         if (!this.ghost) {
24309             var panelSize = this.panel.getSize();
24310             this.panel.el.setVisibilityMode(Ext.core.Element.DISPLAY);
24311             this.ghost = this.panel.ghost();
24312             if (this.insertProxy) {
24313                 
24314                 
24315                 this.proxy = this.panel.el.insertSibling({cls: Ext.baseCSSPrefix + 'panel-dd-spacer'});
24316                 this.proxy.setSize(panelSize);
24317             }
24318         }
24319     },
24320
24321     
24322     repair: function(xy, callback, scope) {
24323         this.hide();
24324         if (typeof callback == "function") {
24325             callback.call(scope || this);
24326         }
24327     },
24328
24329     
24330     moveProxy : function(parentNode, before){
24331         if (this.proxy) {
24332             parentNode.insertBefore(this.proxy.dom, before);
24333         }
24334     }
24335 });
24336
24337
24338 Ext.define('Ext.layout.component.AbstractDock', {
24339
24340     
24341
24342     extend: 'Ext.layout.component.Component',
24343
24344     
24345
24346     type: 'dock',
24347
24348     
24349     autoSizing: true,
24350
24351     beforeLayout: function() {
24352         var returnValue = this.callParent(arguments);
24353         if (returnValue !== false && (!this.initializedBorders || this.childrenChanged) && (!this.owner.border || this.owner.manageBodyBorders)) {
24354             this.handleItemBorders();
24355             this.initializedBorders = true;
24356         }
24357         return returnValue;
24358     },
24359     
24360     handleItemBorders: function() {
24361         var owner = this.owner,
24362             body = owner.body,
24363             docked = this.getLayoutItems(),
24364             borders = {
24365                 top: [],
24366                 right: [],
24367                 bottom: [],
24368                 left: []
24369             },
24370             oldBorders = this.borders,
24371             opposites = {
24372                 top: 'bottom',
24373                 right: 'left',
24374                 bottom: 'top',
24375                 left: 'right'
24376             },
24377             i, ln, item, dock, side;
24378
24379         for (i = 0, ln = docked.length; i < ln; i++) {
24380             item = docked[i];
24381             dock = item.dock;
24382             
24383             if (item.ignoreBorderManagement) {
24384                 continue;
24385             }
24386             
24387             if (!borders[dock].satisfied) {
24388                 borders[dock].push(item);
24389                 borders[dock].satisfied = true;
24390             }
24391             
24392             if (!borders.top.satisfied && opposites[dock] !== 'top') {
24393                 borders.top.push(item);
24394             }
24395             if (!borders.right.satisfied && opposites[dock] !== 'right') {
24396                 borders.right.push(item);
24397             }            
24398             if (!borders.bottom.satisfied && opposites[dock] !== 'bottom') {
24399                 borders.bottom.push(item);
24400             }            
24401             if (!borders.left.satisfied && opposites[dock] !== 'left') {
24402                 borders.left.push(item);
24403             }
24404         }
24405
24406         if (oldBorders) {
24407             for (side in oldBorders) {
24408                 if (oldBorders.hasOwnProperty(side)) {
24409                     ln = oldBorders[side].length;
24410                     if (!owner.manageBodyBorders) {
24411                         for (i = 0; i < ln; i++) {
24412                             oldBorders[side][i].removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
24413                         }
24414                         if (!oldBorders[side].satisfied && !owner.bodyBorder) {
24415                             body.removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);                   
24416                         }                    
24417                     }
24418                     else if (oldBorders[side].satisfied) {
24419                         body.setStyle('border-' + side + '-width', '');
24420                     }
24421                 }
24422             }
24423         }
24424                 
24425         for (side in borders) {
24426             if (borders.hasOwnProperty(side)) {
24427                 ln = borders[side].length;
24428                 if (!owner.manageBodyBorders) {
24429                     for (i = 0; i < ln; i++) {
24430                         borders[side][i].addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
24431                     }
24432                     if ((!borders[side].satisfied && !owner.bodyBorder) || owner.bodyBorder === false) {
24433                         body.addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);                   
24434                     }                    
24435                 }
24436                 else if (borders[side].satisfied) {
24437                     body.setStyle('border-' + side + '-width', '1px');
24438                 }
24439             }
24440         }
24441         
24442         this.borders = borders;
24443     },
24444     
24445     
24446     onLayout: function(width, height) {
24447         var me = this,
24448             owner = me.owner,
24449             body = owner.body,
24450             layout = owner.layout,
24451             target = me.getTarget(),
24452             autoWidth = false,
24453             autoHeight = false,
24454             padding, border, frameSize;
24455
24456         
24457         var info = me.info = {
24458             boxes: [],
24459             size: {
24460                 width: width,
24461                 height: height
24462             },
24463             bodyBox: {}
24464         };
24465
24466         Ext.applyIf(info, me.getTargetInfo());
24467
24468         
24469         if (owner && owner.ownerCt && owner.ownerCt.layout && owner.ownerCt.layout.isLayout) {
24470             if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
24471                 owner.ownerCt.layout.bindToOwnerCtComponent = true;
24472             }
24473             else {
24474                 owner.ownerCt.layout.bindToOwnerCtComponent = false;
24475             }
24476         }
24477
24478         
24479         if (height === undefined || height === null || width === undefined || width === null) {
24480             padding = info.padding;
24481             border = info.border;
24482             frameSize = me.frameSize;
24483
24484             
24485             if ((height === undefined || height === null) && (width === undefined || width === null)) {
24486                 autoHeight = true;
24487                 autoWidth = true;
24488                 me.setTargetSize(null);
24489                 me.setBodyBox({width: null, height: null});
24490             }
24491             
24492             else if (height === undefined || height === null) {
24493                 autoHeight = true;
24494                 
24495                 me.setTargetSize(width);
24496                 me.setBodyBox({width: width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right, height: null});
24497             
24498             }
24499             else {
24500                 autoWidth = true;
24501                 
24502                 me.setTargetSize(null, height);
24503                 me.setBodyBox({width: null, height: height - padding.top - padding.bottom - border.top - border.bottom - frameSize.top - frameSize.bottom});
24504             }
24505
24506             
24507             if (layout && layout.isLayout) {
24508                 
24509                 layout.bindToOwnerCtComponent = true;
24510                 layout.layout();
24511
24512                 
24513                 
24514                 
24515                 
24516                 
24517                 
24518                 
24519                 
24520                 
24521                 
24522                 
24523                 
24524                 info.autoSizedCtLayout = layout.autoSize === true;
24525             }
24526
24527             
24528             
24529             
24530             
24531             
24532             me.dockItems(autoWidth, autoHeight);
24533             me.setTargetSize(info.size.width, info.size.height);
24534         }
24535         else {
24536             me.setTargetSize(width, height);
24537             me.dockItems();
24538         }
24539         me.callParent(arguments);
24540     },
24541
24542     
24543     dockItems : function(autoWidth, autoHeight) {
24544         this.calculateDockBoxes(autoWidth, autoHeight);
24545
24546         
24547         
24548         
24549         var info = this.info,
24550             boxes = info.boxes,
24551             ln = boxes.length,
24552             dock, i;
24553
24554         
24555         
24556         for (i = 0; i < ln; i++) {
24557             dock = boxes[i];
24558             dock.item.setPosition(dock.x, dock.y);
24559             if ((autoWidth || autoHeight) && dock.layout && dock.layout.isLayout) {
24560                 
24561                 dock.layout.bindToOwnerCtComponent = true;
24562             }
24563         }
24564
24565         
24566         
24567         if (!info.autoSizedCtLayout) {
24568             if (autoWidth) {
24569                 info.bodyBox.width = null;
24570             }
24571             if (autoHeight) {
24572                 info.bodyBox.height = null;
24573             }
24574         }
24575
24576         
24577         
24578         this.setBodyBox(info.bodyBox);
24579     },
24580
24581     
24582     calculateDockBoxes : function(autoWidth, autoHeight) {
24583         
24584         
24585         
24586         var me = this,
24587             target = me.getTarget(),
24588             items = me.getLayoutItems(),
24589             owner = me.owner,
24590             bodyEl = owner.body,
24591             info = me.info,
24592             size = info.size,
24593             ln = items.length,
24594             padding = info.padding,
24595             border = info.border,
24596             frameSize = me.frameSize,
24597             item, i, box, rect;
24598
24599         
24600         
24601         if (autoHeight) {
24602             size.height = bodyEl.getHeight() + padding.top + border.top + padding.bottom + border.bottom + frameSize.top + frameSize.bottom;
24603         }
24604         else {
24605             size.height = target.getHeight();
24606         }
24607         if (autoWidth) {
24608             size.width = bodyEl.getWidth() + padding.left + border.left + padding.right + border.right + frameSize.left + frameSize.right;
24609         }
24610         else {
24611             size.width = target.getWidth();
24612         }
24613
24614         info.bodyBox = {
24615             x: padding.left + frameSize.left,
24616             y: padding.top + frameSize.top,
24617             width: size.width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right,
24618             height: size.height - border.top - padding.top - border.bottom - padding.bottom - frameSize.top - frameSize.bottom
24619         };
24620
24621         
24622         for (i = 0; i < ln; i++) {
24623             item = items[i];
24624             
24625             
24626             
24627             box = me.initBox(item);
24628
24629             if (autoHeight === true) {
24630                 box = me.adjustAutoBox(box, i);
24631             }
24632             else {
24633                 box = me.adjustSizedBox(box, i);
24634             }
24635
24636             
24637             
24638             
24639             info.boxes.push(box);
24640         }
24641     },
24642
24643     
24644     adjustSizedBox : function(box, index) {
24645         var bodyBox = this.info.bodyBox,
24646             frameSize = this.frameSize,
24647             info = this.info,
24648             padding = info.padding,
24649             pos = box.type,
24650             border = info.border;
24651
24652         switch (pos) {
24653             case 'top':
24654                 box.y = bodyBox.y;
24655                 break;
24656
24657             case 'left':
24658                 box.x = bodyBox.x;
24659                 break;
24660
24661             case 'bottom':
24662                 box.y = (bodyBox.y + bodyBox.height) - box.height;
24663                 break;
24664
24665             case 'right':
24666                 box.x = (bodyBox.x + bodyBox.width) - box.width;
24667                 break;
24668         }
24669
24670         if (box.ignoreFrame) {
24671             if (pos == 'bottom') {
24672                 box.y += (frameSize.bottom + padding.bottom + border.bottom);
24673             }
24674             else {
24675                 box.y -= (frameSize.top + padding.top + border.top);
24676             }
24677             if (pos == 'right') {
24678                 box.x += (frameSize.right + padding.right + border.right);
24679             }
24680             else {
24681                 box.x -= (frameSize.left + padding.left + border.left);
24682             }
24683         }
24684
24685         
24686         if (!box.overlay) {
24687             switch (pos) {
24688                 case 'top':
24689                     bodyBox.y += box.height;
24690                     bodyBox.height -= box.height;
24691                     break;
24692
24693                 case 'left':
24694                     bodyBox.x += box.width;
24695                     bodyBox.width -= box.width;
24696                     break;
24697
24698                 case 'bottom':
24699                     bodyBox.height -= box.height;
24700                     break;
24701
24702                 case 'right':
24703                     bodyBox.width -= box.width;
24704                     break;
24705             }
24706         }
24707         return box;
24708     },
24709
24710     
24711     adjustAutoBox : function (box, index) {
24712         var info = this.info,
24713             bodyBox = info.bodyBox,
24714             size = info.size,
24715             boxes = info.boxes,
24716             boxesLn = boxes.length,
24717             pos = box.type,
24718             frameSize = this.frameSize,
24719             padding = info.padding,
24720             border = info.border,
24721             autoSizedCtLayout = info.autoSizedCtLayout,
24722             ln = (boxesLn < index) ? boxesLn : index,
24723             i, adjustBox;
24724
24725         if (pos == 'top' || pos == 'bottom') {
24726             
24727             for (i = 0; i < ln; i++) {
24728                 adjustBox = boxes[i];
24729                 if (adjustBox.stretched && adjustBox.type == 'left' || adjustBox.type == 'right') {
24730                     adjustBox.height += box.height;
24731                 }
24732                 else if (adjustBox.type == 'bottom') {
24733                     adjustBox.y += box.height;
24734                 }
24735             }
24736         }
24737
24738         switch (pos) {
24739             case 'top':
24740                 box.y = bodyBox.y;
24741                 if (!box.overlay) {
24742                     bodyBox.y += box.height;
24743                 }
24744                 size.height += box.height;
24745                 break;
24746
24747             case 'bottom':
24748                 box.y = (bodyBox.y + bodyBox.height);
24749                 size.height += box.height;
24750                 break;
24751
24752             case 'left':
24753                 box.x = bodyBox.x;
24754                 if (!box.overlay) {
24755                     bodyBox.x += box.width;
24756                     if (autoSizedCtLayout) {
24757                         size.width += box.width;
24758                     } else {
24759                         bodyBox.width -= box.width;
24760                     }
24761                 }
24762                 break;
24763
24764             case 'right':
24765                 if (!box.overlay) {
24766                     if (autoSizedCtLayout) {
24767                         size.width += box.width;
24768                     } else {
24769                         bodyBox.width -= box.width;
24770                     }
24771                 }
24772                 box.x = (bodyBox.x + bodyBox.width);
24773                 break;
24774         }
24775
24776         if (box.ignoreFrame) {
24777             if (pos == 'bottom') {
24778                 box.y += (frameSize.bottom + padding.bottom + border.bottom);
24779             }
24780             else {
24781                 box.y -= (frameSize.top + padding.top + border.top);
24782             }
24783             if (pos == 'right') {
24784                 box.x += (frameSize.right + padding.right + border.right);
24785             }
24786             else {
24787                 box.x -= (frameSize.left + padding.left + border.left);
24788             }
24789         }
24790         return box;
24791     },
24792
24793     
24794     initBox : function(item) {
24795         var me = this,
24796             bodyBox = me.info.bodyBox,
24797             horizontal = (item.dock == 'top' || item.dock == 'bottom'),
24798             owner = me.owner,
24799             frameSize = me.frameSize,
24800             info = me.info,
24801             padding = info.padding,
24802             border = info.border,
24803             box = {
24804                 item: item,
24805                 overlay: item.overlay,
24806                 type: item.dock,
24807                 offsets: Ext.core.Element.parseBox(item.offsets || {}),
24808                 ignoreFrame: item.ignoreParentFrame
24809             };
24810         
24811         if (item.stretch !== false) {
24812             box.stretched = true;
24813             if (horizontal) {
24814                 box.x = bodyBox.x + box.offsets.left;
24815                 box.width = bodyBox.width - (box.offsets.left + box.offsets.right);
24816                 if (box.ignoreFrame) {
24817                     box.width += (frameSize.left + frameSize.right + border.left + border.right + padding.left + padding.right);
24818                 }
24819                 item.setCalculatedSize(box.width - item.el.getMargin('lr'), undefined, owner);
24820             }
24821             else {
24822                 box.y = bodyBox.y + box.offsets.top;
24823                 box.height = bodyBox.height - (box.offsets.bottom + box.offsets.top);
24824                 if (box.ignoreFrame) {
24825                     box.height += (frameSize.top + frameSize.bottom + border.top + border.bottom + padding.top + padding.bottom);
24826                 }
24827                 item.setCalculatedSize(undefined, box.height - item.el.getMargin('tb'), owner);
24828
24829                 
24830                 
24831                 if (!Ext.supports.ComputedStyle) {
24832                     item.el.repaint();
24833                 }
24834             }
24835         }
24836         else {
24837             item.doComponentLayout();
24838             box.width = item.getWidth() - (box.offsets.left + box.offsets.right);
24839             box.height = item.getHeight() - (box.offsets.bottom + box.offsets.top);
24840             box.y += box.offsets.top;
24841             if (horizontal) {
24842                 box.x = (item.align == 'right') ? bodyBox.width - box.width : bodyBox.x;
24843                 box.x += box.offsets.left;
24844             }
24845         }
24846
24847         
24848         
24849         if (box.width == undefined) {
24850             box.width = item.getWidth() + item.el.getMargin('lr');
24851         }
24852         if (box.height == undefined) {
24853             box.height = item.getHeight() + item.el.getMargin('tb');
24854         }
24855
24856         return box;
24857     },
24858
24859     
24860     getLayoutItems : function() {
24861         var it = this.owner.getDockedItems(),
24862             ln = it.length,
24863             i = 0,
24864             result = [];
24865         for (; i < ln; i++) {
24866             if (it[i].isVisible(true)) {
24867                 result.push(it[i]);
24868             }
24869         }
24870         return result;
24871     },
24872
24873     
24874     renderItems: function(items, target) {
24875         var cns = target.dom.childNodes,
24876             cnsLn = cns.length,
24877             ln = items.length,
24878             domLn = 0,
24879             i, j, cn, item;
24880
24881         
24882         for (i = 0; i < cnsLn; i++) {
24883             cn = Ext.get(cns[i]);
24884             for (j = 0; j < ln; j++) {
24885                 item = items[j];
24886                 if (item.rendered && (cn.id == item.el.id || cn.down('#' + item.el.id))) {
24887                     break;
24888                 }
24889             }
24890
24891             if (j === ln) {
24892                 domLn++;
24893             }
24894         }
24895
24896         
24897         for (i = 0, j = 0; i < ln; i++, j++) {
24898             item = items[i];
24899
24900             
24901             
24902             
24903             
24904             
24905             
24906             
24907             
24908             if (i === j && (item.dock === 'right' || item.dock === 'bottom')) {
24909                 j += domLn;
24910             }
24911
24912             
24913             if (item && !item.rendered) {
24914                 this.renderItem(item, target, j);
24915             }
24916             else if (!this.isValidParent(item, target, j)) {
24917                 this.moveItem(item, target, j);
24918             }
24919         }
24920     },
24921
24922     
24923     setBodyBox : function(box) {
24924         var me = this,
24925             owner = me.owner,
24926             body = owner.body,
24927             info = me.info,
24928             bodyMargin = info.bodyMargin,
24929             padding = info.padding,
24930             border = info.border,
24931             frameSize = me.frameSize;
24932         
24933         
24934         if (owner.collapsed) {
24935             return;
24936         }
24937         
24938         if (Ext.isNumber(box.width)) {
24939             box.width -= bodyMargin.left + bodyMargin.right;
24940         }
24941         
24942         if (Ext.isNumber(box.height)) {
24943             box.height -= bodyMargin.top + bodyMargin.bottom;
24944         }
24945         
24946         me.setElementSize(body, box.width, box.height);
24947         if (Ext.isNumber(box.x)) {
24948             body.setLeft(box.x - padding.left - frameSize.left);
24949         }
24950         if (Ext.isNumber(box.y)) {
24951             body.setTop(box.y - padding.top - frameSize.top);
24952         }
24953     },
24954
24955     
24956     configureItem : function(item, pos) {
24957         this.callParent(arguments);
24958         
24959         item.addCls(Ext.baseCSSPrefix + 'docked');
24960         item.addClsWithUI('docked-' + item.dock);
24961     },
24962
24963     afterRemove : function(item) {
24964         this.callParent(arguments);
24965         if (this.itemCls) {
24966             item.el.removeCls(this.itemCls + '-' + item.dock);
24967         }
24968         var dom = item.el.dom;
24969
24970         if (!item.destroying && dom) {
24971             dom.parentNode.removeChild(dom);
24972         }
24973         this.childrenChanged = true;
24974     }
24975 });
24976
24977 Ext.define('Ext.app.EventBus', {
24978     requires: [
24979         'Ext.util.Event'
24980     ],
24981     mixins: {
24982         observable: 'Ext.util.Observable'
24983     },
24984     
24985     constructor: function() {
24986         this.mixins.observable.constructor.call(this);
24987         
24988         this.bus = {};
24989         
24990         var me = this;
24991         Ext.override(Ext.Component, {
24992             fireEvent: function(ev) {
24993                 if (Ext.util.Observable.prototype.fireEvent.apply(this, arguments) !== false) {
24994                     return me.dispatch.call(me, ev, this, arguments);
24995                 }
24996                 return false;
24997             }
24998         });
24999     },
25000
25001     dispatch: function(ev, target, args) {
25002         var bus = this.bus,
25003             selectors = bus[ev],
25004             selector, controllers, id, events, event, i, ln;
25005         
25006         if (selectors) {
25007             
25008             for (selector in selectors) {
25009                 
25010                 if (target.is(selector)) {
25011                     
25012                     controllers = selectors[selector];
25013                     for (id in controllers) {
25014                         
25015                         events = controllers[id];
25016                         for (i = 0, ln = events.length; i < ln; i++) {
25017                             event = events[i];
25018                             
25019                             return event.fire.apply(event, Array.prototype.slice.call(args, 1));
25020                         }
25021                     }
25022                 }
25023             }
25024         }
25025     },
25026     
25027     control: function(selectors, listeners, controller) {
25028         var bus = this.bus,
25029             selector, fn;
25030         
25031         if (Ext.isString(selectors)) {
25032             selector = selectors;
25033             selectors = {};
25034             selectors[selector] = listeners;
25035             this.control(selectors, null, controller);
25036             return;
25037         }
25038     
25039         Ext.Object.each(selectors, function(selector, listeners) {
25040             Ext.Object.each(listeners, function(ev, listener) {
25041                 var options = {},   
25042                     scope = controller,
25043                     event = Ext.create('Ext.util.Event', controller, ev);
25044                 
25045                 
25046                 if (Ext.isObject(listener)) {
25047                     options = listener;
25048                     listener = options.fn;
25049                     scope = options.scope || controller;
25050                     delete options.fn;
25051                     delete options.scope;
25052                 }
25053                 
25054                 event.addListener(listener, scope, options);
25055
25056                 
25057                 bus[ev] = bus[ev] || {};
25058                 bus[ev][selector] = bus[ev][selector] || {};
25059                 bus[ev][selector][controller.id] = bus[ev][selector][controller.id] || [];            
25060                 
25061                 
25062                 bus[ev][selector][controller.id].push(event);
25063             });
25064         });
25065     }
25066 });
25067
25068 Ext.define('Ext.data.Types', {
25069     singleton: true,
25070     requires: ['Ext.data.SortTypes']
25071 }, function() {
25072     var st = Ext.data.SortTypes;
25073     
25074     Ext.apply(Ext.data.Types, {
25075         
25076         stripRe: /[\$,%]/g,
25077         
25078         
25079         AUTO: {
25080             convert: function(v) {
25081                 return v;
25082             },
25083             sortType: st.none,
25084             type: 'auto'
25085         },
25086
25087         
25088         STRING: {
25089             convert: function(v) {
25090                 var defaultValue = this.useNull ? null : '';
25091                 return (v === undefined || v === null) ? defaultValue : String(v);
25092             },
25093             sortType: st.asUCString,
25094             type: 'string'
25095         },
25096
25097         
25098         INT: {
25099             convert: function(v) {
25100                 return v !== undefined && v !== null && v !== '' ?
25101                     parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
25102             },
25103             sortType: st.none,
25104             type: 'int'
25105         },
25106         
25107         
25108         FLOAT: {
25109             convert: function(v) {
25110                 return v !== undefined && v !== null && v !== '' ?
25111                     parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0);
25112             },
25113             sortType: st.none,
25114             type: 'float'
25115         },
25116         
25117         
25118         BOOL: {
25119             convert: function(v) {
25120                 if (this.useNull && v === undefined || v === null || v === '') {
25121                     return null;
25122                 }
25123                 return v === true || v === 'true' || v == 1;
25124             },
25125             sortType: st.none,
25126             type: 'bool'
25127         },
25128         
25129         
25130         DATE: {
25131             convert: function(v) {
25132                 var df = this.dateFormat;
25133                 if (!v) {
25134                     return null;
25135                 }
25136                 if (Ext.isDate(v)) {
25137                     return v;
25138                 }
25139                 if (df) {
25140                     if (df == 'timestamp') {
25141                         return new Date(v*1000);
25142                     }
25143                     if (df == 'time') {
25144                         return new Date(parseInt(v, 10));
25145                     }
25146                     return Ext.Date.parse(v, df);
25147                 }
25148                 
25149                 var parsed = Date.parse(v);
25150                 return parsed ? new Date(parsed) : null;
25151             },
25152             sortType: st.asDate,
25153             type: 'date'
25154         }
25155     });
25156     
25157     Ext.apply(Ext.data.Types, {
25158         
25159         BOOLEAN: this.BOOL,
25160         
25161         
25162         INTEGER: this.INT,
25163         
25164         
25165         NUMBER: this.FLOAT    
25166     });
25167 });
25168
25169
25170 Ext.define('Ext.data.Field', {
25171     requires: ['Ext.data.Types', 'Ext.data.SortTypes'],
25172     alias: 'data.field',
25173     
25174     constructor : function(config) {
25175         if (Ext.isString(config)) {
25176             config = {name: config};
25177         }
25178         Ext.apply(this, config);
25179         
25180         var types = Ext.data.Types,
25181             st = this.sortType,
25182             t;
25183
25184         if (this.type) {
25185             if (Ext.isString(this.type)) {
25186                 this.type = types[this.type.toUpperCase()] || types.AUTO;
25187             }
25188         } else {
25189             this.type = types.AUTO;
25190         }
25191
25192         
25193         if (Ext.isString(st)) {
25194             this.sortType = Ext.data.SortTypes[st];
25195         } else if(Ext.isEmpty(st)) {
25196             this.sortType = this.type.sortType;
25197         }
25198
25199         if (!this.convert) {
25200             this.convert = this.type.convert;
25201         }
25202     },
25203     
25204     
25205     
25206     
25207     
25208     
25209     
25210     dateFormat: null,
25211     
25212     
25213     useNull: false,
25214     
25215     
25216     defaultValue: "",
25217     
25218     mapping: null,
25219     
25220     sortType : null,
25221     
25222     sortDir : "ASC",
25223     
25224     allowBlank : true,
25225     
25226     
25227     persist: true
25228 });
25229
25230
25231 Ext.define('Ext.data.reader.Reader', {
25232     requires: ['Ext.data.ResultSet'],
25233     alternateClassName: ['Ext.data.Reader', 'Ext.data.DataReader'],
25234     
25235     
25236
25237     
25238     totalProperty: 'total',
25239
25240     
25241     successProperty: 'success',
25242
25243     
25244     root: '',
25245     
25246     
25247     
25248     
25249     implicitIncludes: true,
25250     
25251     isReader: true,
25252     
25253     constructor: function(config) {
25254         var me = this;
25255         
25256         Ext.apply(me, config || {});
25257         me.fieldCount = 0;
25258         me.model = Ext.ModelManager.getModel(config.model);
25259         if (me.model) {
25260             me.buildExtractors();
25261         }
25262     },
25263
25264     
25265     setModel: function(model, setOnProxy) {
25266         var me = this;
25267         
25268         me.model = Ext.ModelManager.getModel(model);
25269         me.buildExtractors(true);
25270         
25271         if (setOnProxy && me.proxy) {
25272             me.proxy.setModel(me.model, true);
25273         }
25274     },
25275
25276     
25277     read: function(response) {
25278         var data = response;
25279         
25280         if (response && response.responseText) {
25281             data = this.getResponseData(response);
25282         }
25283         
25284         if (data) {
25285             return this.readRecords(data);
25286         } else {
25287             return this.nullResultSet;
25288         }
25289     },
25290
25291     
25292     readRecords: function(data) {
25293         var me  = this;
25294         
25295         
25296         if (me.fieldCount !== me.getFields().length) {
25297             me.buildExtractors(true);
25298         }
25299         
25300         
25301         me.rawData = data;
25302
25303         data = me.getData(data);
25304
25305         
25306         
25307         var root    = Ext.isArray(data) ? data : me.getRoot(data),
25308             success = true,
25309             recordCount = 0,
25310             total, value, records, message;
25311             
25312         if (root) {
25313             total = root.length;
25314         }
25315
25316         if (me.totalProperty) {
25317             value = parseInt(me.getTotal(data), 10);
25318             if (!isNaN(value)) {
25319                 total = value;
25320             }
25321         }
25322
25323         if (me.successProperty) {
25324             value = me.getSuccess(data);
25325             if (value === false || value === 'false') {
25326                 success = false;
25327             }
25328         }
25329         
25330         if (me.messageProperty) {
25331             message = me.getMessage(data);
25332         }
25333         
25334         if (root) {
25335             records = me.extractData(root);
25336             recordCount = records.length;
25337         } else {
25338             recordCount = 0;
25339             records = [];
25340         }
25341
25342         return Ext.create('Ext.data.ResultSet', {
25343             total  : total || recordCount,
25344             count  : recordCount,
25345             records: records,
25346             success: success,
25347             message: message
25348         });
25349     },
25350
25351     
25352     extractData : function(root) {
25353         var me = this,
25354             values  = [],
25355             records = [],
25356             Model   = me.model,
25357             i       = 0,
25358             length  = root.length,
25359             idProp  = me.getIdProperty(),
25360             node, id, record;
25361             
25362         if (!root.length && Ext.isObject(root)) {
25363             root = [root];
25364             length = 1;
25365         }
25366
25367         for (; i < length; i++) {
25368             node   = root[i];
25369             values = me.extractValues(node);
25370             id     = me.getId(node);
25371
25372             
25373             record = new Model(values, id, node);
25374             records.push(record);
25375                 
25376             if (me.implicitIncludes) {
25377                 me.readAssociated(record, node);
25378             }
25379         }
25380
25381         return records;
25382     },
25383     
25384     
25385     readAssociated: function(record, data) {
25386         var associations = record.associations.items,
25387             i            = 0,
25388             length       = associations.length,
25389             association, associationData, proxy, reader;
25390         
25391         for (; i < length; i++) {
25392             association     = associations[i];
25393             associationData = this.getAssociatedDataRoot(data, association.associationKey || association.name);
25394             
25395             if (associationData) {
25396                 reader = association.getReader();
25397                 if (!reader) {
25398                     proxy = association.associatedModel.proxy;
25399                     
25400                     if (proxy) {
25401                         reader = proxy.getReader();
25402                     } else {
25403                         reader = new this.constructor({
25404                             model: association.associatedName
25405                         });
25406                     }
25407                 }
25408                 association.read(record, reader, associationData);
25409             }  
25410         }
25411     },
25412     
25413     
25414     getAssociatedDataRoot: function(data, associationName) {
25415         return data[associationName];
25416     },
25417     
25418     getFields: function() {
25419         return this.model.prototype.fields.items;
25420     },
25421
25422     
25423     extractValues: function(data) {
25424         var fields = this.getFields(),
25425             i      = 0,
25426             length = fields.length,
25427             output = {},
25428             field, value;
25429
25430         for (; i < length; i++) {
25431             field = fields[i];
25432             value = this.extractorFunctions[i](data);
25433
25434             output[field.name] = value;
25435         }
25436
25437         return output;
25438     },
25439
25440     
25441     getData: function(data) {
25442         return data;
25443     },
25444
25445     
25446     getRoot: function(data) {
25447         return data;
25448     },
25449
25450     
25451     getResponseData: function(response) {
25452         Ext.Error.raise("getResponseData must be implemented in the Ext.data.reader.Reader subclass");
25453     },
25454
25455     
25456     onMetaChange : function(meta) {
25457         var fields = meta.fields,
25458             newModel;
25459         
25460         Ext.apply(this, meta);
25461         
25462         if (fields) {
25463             newModel = Ext.define("Ext.data.reader.Json-Model" + Ext.id(), {
25464                 extend: 'Ext.data.Model',
25465                 fields: fields
25466             });
25467             this.setModel(newModel, true);
25468         } else {
25469             this.buildExtractors(true);
25470         }
25471     },
25472     
25473     
25474     getIdProperty: function(){
25475         var prop = this.idProperty;
25476         if (Ext.isEmpty(prop)) {
25477             prop = this.model.prototype.idProperty;
25478         }
25479         return prop;
25480     },
25481
25482     
25483     buildExtractors: function(force) {
25484         var me          = this,
25485             idProp      = me.getIdProperty(),
25486             totalProp   = me.totalProperty,
25487             successProp = me.successProperty,
25488             messageProp = me.messageProperty,
25489             accessor;
25490             
25491         if (force === true) {
25492             delete me.extractorFunctions;
25493         }
25494         
25495         if (me.extractorFunctions) {
25496             return;
25497         }   
25498
25499         
25500         if (totalProp) {
25501             me.getTotal = me.createAccessor(totalProp);
25502         }
25503
25504         if (successProp) {
25505             me.getSuccess = me.createAccessor(successProp);
25506         }
25507
25508         if (messageProp) {
25509             me.getMessage = me.createAccessor(messageProp);
25510         }
25511
25512         if (idProp) {
25513             accessor = me.createAccessor(idProp);
25514
25515             me.getId = function(record) {
25516                 var id = accessor.call(me, record);
25517                 return (id === undefined || id === '') ? null : id;
25518             };
25519         } else {
25520             me.getId = function() {
25521                 return null;
25522             };
25523         }
25524         me.buildFieldExtractors();
25525     },
25526
25527     
25528     buildFieldExtractors: function() {
25529         
25530         var me = this,
25531             fields = me.getFields(),
25532             ln = fields.length,
25533             i  = 0,
25534             extractorFunctions = [],
25535             field, map;
25536
25537         for (; i < ln; i++) {
25538             field = fields[i];
25539             map   = (field.mapping !== undefined && field.mapping !== null) ? field.mapping : field.name;
25540
25541             extractorFunctions.push(me.createAccessor(map));
25542         }
25543         me.fieldCount = ln;
25544
25545         me.extractorFunctions = extractorFunctions;
25546     }
25547 }, function() {
25548     Ext.apply(this, {
25549         
25550         nullResultSet: Ext.create('Ext.data.ResultSet', {
25551             total  : 0,
25552             count  : 0,
25553             records: [],
25554             success: true
25555         })
25556     });
25557 });
25558
25559 Ext.define('Ext.data.reader.Json', {
25560     extend: 'Ext.data.reader.Reader',
25561     alternateClassName: 'Ext.data.JsonReader',
25562     alias : 'reader.json',
25563     
25564     root: '',
25565     
25566     
25567     
25568     
25569     useSimpleAccessors: false,
25570     
25571     
25572     readRecords: function(data) {
25573         
25574         if (data.metaData) {
25575             this.onMetaChange(data.metaData);
25576         }
25577
25578         
25579         this.jsonData = data;
25580         return this.callParent([data]);
25581     },
25582
25583     
25584     getResponseData: function(response) {
25585         try {
25586             var data = Ext.decode(response.responseText);
25587         }
25588         catch (ex) {
25589             Ext.Error.raise({
25590                 response: response,
25591                 json: response.responseText,
25592                 parseError: ex,
25593                 msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
25594             });
25595         }
25596         if (!data) {
25597             Ext.Error.raise('JSON object not found');
25598         }
25599
25600         return data;
25601     },
25602
25603     
25604     buildExtractors : function() {
25605         var me = this;
25606         
25607         me.callParent(arguments);
25608
25609         if (me.root) {
25610             me.getRoot = me.createAccessor(me.root);
25611         } else {
25612             me.getRoot = function(root) {
25613                 return root;
25614             };
25615         }
25616     },
25617     
25618     
25619     extractData: function(root) {
25620         var recordName = this.record,
25621             data = [],
25622             length, i;
25623         
25624         if (recordName) {
25625             length = root.length;
25626             
25627             for (i = 0; i < length; i++) {
25628                 data[i] = root[i][recordName];
25629             }
25630         } else {
25631             data = root;
25632         }
25633         return this.callParent([data]);
25634     },
25635
25636     
25637     createAccessor: function() {
25638         var re = /[\[\.]/;
25639         
25640         return function(expr) {
25641             if (Ext.isEmpty(expr)) {
25642                 return Ext.emptyFn;
25643             }
25644             if (Ext.isFunction(expr)) {
25645                 return expr;
25646             }
25647             if (this.useSimpleAccessors !== true) {
25648                 var i = String(expr).search(re);
25649                 if (i >= 0) {
25650                     return Ext.functionFactory('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
25651                 }
25652             }
25653             return function(obj) {
25654                 return obj[expr];
25655             };
25656         };
25657     }()
25658 });
25659
25660 Ext.define('Ext.data.writer.Json', {
25661     extend: 'Ext.data.writer.Writer',
25662     alternateClassName: 'Ext.data.JsonWriter',
25663     alias: 'writer.json',
25664     
25665     
25666     root: undefined,
25667     
25668     
25669     encode: false,
25670     
25671     
25672     allowSingle: true,
25673     
25674     
25675     writeRecords: function(request, data) {
25676         var root = this.root;
25677         
25678         if (this.allowSingle && data.length == 1) {
25679             
25680             data = data[0];
25681         }
25682         
25683         if (this.encode) {
25684             if (root) {
25685                 
25686                 request.params[root] = Ext.encode(data);
25687             } else {
25688                 Ext.Error.raise('Must specify a root when using encode');
25689             }
25690         } else {
25691             
25692             request.jsonData = request.jsonData || {};
25693             if (root) {
25694                 request.jsonData[root] = data;
25695             } else {
25696                 request.jsonData = data;
25697             }
25698         }
25699         return request;
25700     }
25701 });
25702
25703
25704 Ext.define('Ext.data.proxy.Proxy', {
25705     alias: 'proxy.proxy',
25706     alternateClassName: ['Ext.data.DataProxy', 'Ext.data.Proxy'],
25707     requires: [
25708         'Ext.data.reader.Json',
25709         'Ext.data.writer.Json'
25710     ],
25711     uses: [
25712         'Ext.data.Batch', 
25713         'Ext.data.Operation', 
25714         'Ext.data.Model'
25715     ],
25716     mixins: {
25717         observable: 'Ext.util.Observable'
25718     },
25719     
25720     
25721     batchOrder: 'create,update,destroy',
25722     
25723     
25724     batchActions: true,
25725     
25726     
25727     defaultReaderType: 'json',
25728     
25729     
25730     defaultWriterType: 'json',
25731     
25732     
25733     
25734     isProxy: true,
25735     
25736     constructor: function(config) {
25737         config = config || {};
25738         
25739         if (config.model === undefined) {
25740             delete config.model;
25741         }
25742
25743         this.mixins.observable.constructor.call(this, config);
25744         
25745         if (this.model !== undefined && !(this.model instanceof Ext.data.Model)) {
25746             this.setModel(this.model);
25747         }
25748     },
25749     
25750     
25751     setModel: function(model, setOnStore) {
25752         this.model = Ext.ModelManager.getModel(model);
25753         
25754         var reader = this.reader,
25755             writer = this.writer;
25756         
25757         this.setReader(reader);
25758         this.setWriter(writer);
25759         
25760         if (setOnStore && this.store) {
25761             this.store.setModel(this.model);
25762         }
25763     },
25764     
25765     
25766     getModel: function() {
25767         return this.model;
25768     },
25769     
25770     
25771     setReader: function(reader) {
25772         var me = this;
25773         
25774         if (reader === undefined || typeof reader == 'string') {
25775             reader = {
25776                 type: reader
25777             };
25778         }
25779
25780         if (reader.isReader) {
25781             reader.setModel(me.model);
25782         } else {
25783             Ext.applyIf(reader, {
25784                 proxy: me,
25785                 model: me.model,
25786                 type : me.defaultReaderType
25787             });
25788
25789             reader = Ext.createByAlias('reader.' + reader.type, reader);
25790         }
25791         
25792         me.reader = reader;
25793         return me.reader;
25794     },
25795     
25796     
25797     getReader: function() {
25798         return this.reader;
25799     },
25800     
25801     
25802     setWriter: function(writer) {
25803         if (writer === undefined || typeof writer == 'string') {
25804             writer = {
25805                 type: writer
25806             };
25807         }
25808
25809         if (!(writer instanceof Ext.data.writer.Writer)) {
25810             Ext.applyIf(writer, {
25811                 model: this.model,
25812                 type : this.defaultWriterType
25813             });
25814
25815             writer = Ext.createByAlias('writer.' + writer.type, writer);
25816         }
25817         
25818         this.writer = writer;
25819         
25820         return this.writer;
25821     },
25822     
25823     
25824     getWriter: function() {
25825         return this.writer;
25826     },
25827     
25828     
25829     create: Ext.emptyFn,
25830     
25831     
25832     read: Ext.emptyFn,
25833     
25834     
25835     update: Ext.emptyFn,
25836     
25837     
25838     destroy: Ext.emptyFn,
25839     
25840     
25841     batch: function(operations, listeners) {
25842         var me = this,
25843             batch = Ext.create('Ext.data.Batch', {
25844                 proxy: me,
25845                 listeners: listeners || {}
25846             }),
25847             useBatch = me.batchActions, 
25848             records;
25849         
25850         Ext.each(me.batchOrder.split(','), function(action) {
25851             records = operations[action];
25852             if (records) {
25853                 if (useBatch) {
25854                     batch.add(Ext.create('Ext.data.Operation', {
25855                         action: action,
25856                         records: records
25857                     }));
25858                 } else {
25859                     Ext.each(records, function(record){
25860                         batch.add(Ext.create('Ext.data.Operation', {
25861                             action : action, 
25862                             records: [record]
25863                         }));
25864                     });
25865                 }
25866             }
25867         }, me);
25868         
25869         batch.start();
25870         return batch;
25871     }
25872 }, function() {
25873     
25874     
25875     
25876     Ext.data.DataProxy = this;
25877     
25878     
25879     
25880 });
25881
25882
25883 Ext.define('Ext.data.proxy.Server', {
25884     extend: 'Ext.data.proxy.Proxy',
25885     alias : 'proxy.server',
25886     alternateClassName: 'Ext.data.ServerProxy',
25887     uses  : ['Ext.data.Request'],
25888     
25889     
25890     
25891     
25892     
25893     
25894     
25895     
25896     pageParam: 'page',
25897     
25898     
25899     startParam: 'start',
25900
25901     
25902     limitParam: 'limit',
25903     
25904     
25905     groupParam: 'group',
25906     
25907     
25908     sortParam: 'sort',
25909     
25910     
25911     filterParam: 'filter',
25912     
25913     
25914     directionParam: 'dir',
25915     
25916     
25917     simpleSortMode: false,
25918     
25919     
25920     noCache : true,
25921     
25922     
25923     cacheString: "_dc",
25924     
25925     
25926     timeout : 30000,
25927     
25928     
25929     
25930     
25931     constructor: function(config) {
25932         var me = this;
25933         
25934         config = config || {};
25935         this.addEvents(
25936             
25937             'exception'
25938         );
25939         me.callParent([config]);
25940         
25941         
25942         me.extraParams = config.extraParams || {};
25943         
25944         me.api = config.api || {};
25945         
25946         
25947         me.nocache = me.noCache;
25948     },
25949     
25950     
25951     create: function() {
25952         return this.doRequest.apply(this, arguments);
25953     },
25954     
25955     read: function() {
25956         return this.doRequest.apply(this, arguments);
25957     },
25958     
25959     update: function() {
25960         return this.doRequest.apply(this, arguments);
25961     },
25962     
25963     destroy: function() {
25964         return this.doRequest.apply(this, arguments);
25965     },
25966     
25967     
25968     buildRequest: function(operation) {
25969         var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
25970             request;
25971         
25972         
25973         params = Ext.applyIf(params, this.getParams(params, operation));
25974         
25975         if (operation.id && !params.id) {
25976             params.id = operation.id;
25977         }
25978         
25979         request = Ext.create('Ext.data.Request', {
25980             params   : params,
25981             action   : operation.action,
25982             records  : operation.records,
25983             operation: operation,
25984             url      : operation.url
25985         });
25986         
25987         request.url = this.buildUrl(request);
25988         
25989         
25990         operation.request = request;
25991         
25992         return request;
25993     },
25994     
25995     
25996     processResponse: function(success, operation, request, response, callback, scope){
25997         var me = this,
25998             reader,
25999             result,
26000             records,
26001             length,
26002             mc,
26003             record,
26004             i;
26005             
26006         if (success === true) {
26007             reader = me.getReader();
26008             result = reader.read(me.extractResponseData(response));
26009             records = result.records;
26010             length = records.length;
26011             
26012             if (result.success !== false) {
26013                 mc = Ext.create('Ext.util.MixedCollection', true, function(r) {return r.getId();});
26014                 mc.addAll(operation.records);
26015                 for (i = 0; i < length; i++) {
26016                     record = mc.get(records[i].getId());
26017                     
26018                     if (record) {
26019                         record.beginEdit();
26020                         record.set(record.data);
26021                         record.endEdit(true);
26022                     }
26023                 }
26024                 
26025                 
26026                 Ext.apply(operation, {
26027                     response: response,
26028                     resultSet: result
26029                 });
26030                 
26031                 operation.setCompleted();
26032                 operation.setSuccessful();
26033             } else {
26034                 operation.setException(result.message);
26035                 me.fireEvent('exception', this, response, operation);
26036             }
26037         } else {
26038             me.setException(operation, response);
26039             me.fireEvent('exception', this, response, operation);              
26040         }
26041             
26042         
26043         if (typeof callback == 'function') {
26044             callback.call(scope || me, operation);
26045         }
26046             
26047         me.afterRequest(request, success);
26048     },
26049     
26050     
26051     setException: function(operation, response){
26052         operation.setException({
26053             status: response.status,
26054             statusText: response.statusText
26055         });     
26056     },
26057     
26058     
26059     extractResponseData: function(response){
26060         return response; 
26061     },
26062     
26063     
26064     applyEncoding: function(value){
26065         return Ext.encode(value);
26066     },
26067     
26068     
26069     encodeSorters: function(sorters) {
26070         var min = [],
26071             length = sorters.length,
26072             i = 0;
26073         
26074         for (; i < length; i++) {
26075             min[i] = {
26076                 property : sorters[i].property,
26077                 direction: sorters[i].direction
26078             };
26079         }
26080         return this.applyEncoding(min);
26081         
26082     },
26083     
26084     
26085     encodeFilters: function(filters) {
26086         var min = [],
26087             length = filters.length,
26088             i = 0;
26089         
26090         for (; i < length; i++) {
26091             min[i] = {
26092                 property: filters[i].property,
26093                 value   : filters[i].value
26094             };
26095         }
26096         return this.applyEncoding(min);
26097     },
26098     
26099     
26100     getParams: function(params, operation) {
26101         params = params || {};
26102         
26103         var me             = this,
26104             isDef          = Ext.isDefined,
26105             groupers       = operation.groupers,
26106             sorters        = operation.sorters,
26107             filters        = operation.filters,
26108             page           = operation.page,
26109             start          = operation.start,
26110             limit          = operation.limit,
26111             
26112             simpleSortMode = me.simpleSortMode,
26113             
26114             pageParam      = me.pageParam,
26115             startParam     = me.startParam,
26116             limitParam     = me.limitParam,
26117             groupParam     = me.groupParam,
26118             sortParam      = me.sortParam,
26119             filterParam    = me.filterParam,
26120             directionParam       = me.directionParam;
26121         
26122         if (pageParam && isDef(page)) {
26123             params[pageParam] = page;
26124         }
26125         
26126         if (startParam && isDef(start)) {
26127             params[startParam] = start;
26128         }
26129         
26130         if (limitParam && isDef(limit)) {
26131             params[limitParam] = limit;
26132         }
26133         
26134         if (groupParam && groupers && groupers.length > 0) {
26135             
26136             params[groupParam] = me.encodeSorters(groupers);
26137         }
26138         
26139         if (sortParam && sorters && sorters.length > 0) {
26140             if (simpleSortMode) {
26141                 params[sortParam] = sorters[0].property;
26142                 params[directionParam] = sorters[0].direction;
26143             } else {
26144                 params[sortParam] = me.encodeSorters(sorters);
26145             }
26146             
26147         }
26148         
26149         if (filterParam && filters && filters.length > 0) {
26150             params[filterParam] = me.encodeFilters(filters);
26151         }
26152         
26153         return params;
26154     },
26155     
26156     
26157     buildUrl: function(request) {
26158         var me = this,
26159             url = me.getUrl(request);
26160         
26161         if (!url) {
26162             Ext.Error.raise("You are using a ServerProxy but have not supplied it with a url.");
26163         }
26164         
26165         if (me.noCache) {
26166             url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.cacheString, Ext.Date.now()));
26167         }
26168         
26169         return url;
26170     },
26171     
26172     
26173     getUrl: function(request){
26174         return request.url || this.api[request.action] || this.url;
26175     },
26176     
26177     
26178     doRequest: function(operation, callback, scope) {
26179         Ext.Error.raise("The doRequest function has not been implemented on your Ext.data.proxy.Server subclass. See src/data/ServerProxy.js for details");
26180     },
26181     
26182     
26183     afterRequest: Ext.emptyFn,
26184     
26185     onDestroy: function() {
26186         Ext.destroy(this.reader, this.writer);
26187     }
26188 });
26189
26190
26191 Ext.define('Ext.data.proxy.Ajax', {
26192     requires: ['Ext.util.MixedCollection', 'Ext.Ajax'],
26193     extend: 'Ext.data.proxy.Server',
26194     alias: 'proxy.ajax',
26195     alternateClassName: ['Ext.data.HttpProxy', 'Ext.data.AjaxProxy'],
26196     
26197     
26198     actionMethods: {
26199         create : 'POST',
26200         read   : 'GET',
26201         update : 'POST',
26202         destroy: 'POST'
26203     },
26204     
26205     
26206     
26207     
26208     doRequest: function(operation, callback, scope) {
26209         var writer  = this.getWriter(),
26210             request = this.buildRequest(operation, callback, scope);
26211             
26212         if (operation.allowWrite()) {
26213             request = writer.write(request);
26214         }
26215         
26216         Ext.apply(request, {
26217             headers       : this.headers,
26218             timeout       : this.timeout,
26219             scope         : this,
26220             callback      : this.createRequestCallback(request, operation, callback, scope),
26221             method        : this.getMethod(request),
26222             disableCaching: false 
26223         });
26224         
26225         Ext.Ajax.request(request);
26226         
26227         return request;
26228     },
26229     
26230     
26231     getMethod: function(request) {
26232         return this.actionMethods[request.action];
26233     },
26234     
26235     
26236     createRequestCallback: function(request, operation, callback, scope) {
26237         var me = this;
26238         
26239         return function(options, success, response) {
26240             me.processResponse(success, operation, request, response, callback, scope);
26241         };
26242     }
26243 }, function() {
26244     
26245     Ext.data.HttpProxy = this;
26246 });
26247
26248
26249 Ext.define('Ext.data.Model', {
26250     alternateClassName: 'Ext.data.Record',
26251     
26252     mixins: {
26253         observable: 'Ext.util.Observable'
26254     },
26255
26256     requires: [
26257         'Ext.ModelManager',
26258         'Ext.data.Field',
26259         'Ext.data.Errors',
26260         'Ext.data.Operation',
26261         'Ext.data.validations',
26262         'Ext.data.proxy.Ajax',
26263         'Ext.util.MixedCollection'
26264     ],
26265
26266     onClassExtended: function(cls, data) {
26267         var onBeforeClassCreated = data.onBeforeClassCreated;
26268
26269         data.onBeforeClassCreated = function(cls, data) {
26270             var me = this,
26271                 name = Ext.getClassName(cls),
26272                 prototype = cls.prototype,
26273                 superCls = cls.prototype.superclass,
26274
26275                 validations = data.validations || [],
26276                 fields = data.fields || [],
26277                 associations = data.associations || [],
26278                 belongsTo = data.belongsTo,
26279                 hasMany = data.hasMany,
26280
26281                 fieldsMixedCollection = new Ext.util.MixedCollection(false, function(field) {
26282                     return field.name;
26283                 }),
26284
26285                 associationsMixedCollection = new Ext.util.MixedCollection(false, function(association) {
26286                     return association.name;
26287                 }),
26288
26289                 superValidations = superCls.validations,
26290                 superFields = superCls.fields,
26291                 superAssociations = superCls.associations,
26292
26293                 association, i, ln,
26294                 dependencies = [];
26295
26296             
26297             cls.modelName = name;
26298             prototype.modelName = name;
26299
26300             
26301             if (superValidations) {
26302                 validations = superValidations.concat(validations);
26303             }
26304
26305             data.validations = validations;
26306
26307             
26308             if (superFields) {
26309                 fields = superFields.items.concat(fields);
26310             }
26311
26312             for (i = 0, ln = fields.length; i < ln; ++i) {
26313                 fieldsMixedCollection.add(new Ext.data.Field(fields[i]));
26314             }
26315
26316             data.fields = fieldsMixedCollection;
26317
26318             
26319             
26320             if (belongsTo) {
26321                 belongsTo = Ext.Array.from(belongsTo);
26322
26323                 for (i = 0, ln = belongsTo.length; i < ln; ++i) {
26324                     association = belongsTo[i];
26325
26326                     if (!Ext.isObject(association)) {
26327                         association = {model: association};
26328                     }
26329
26330                     association.type = 'belongsTo';
26331                     associations.push(association);
26332                 }
26333
26334                 delete data.belongsTo;
26335             }
26336
26337             if (hasMany) {
26338                 hasMany = Ext.Array.from(hasMany);
26339                 for (i = 0, ln = hasMany.length; i < ln; ++i) {
26340                     association = hasMany[i];
26341
26342                     if (!Ext.isObject(association)) {
26343                         association = {model: association};
26344                     }
26345
26346                     association.type = 'hasMany';
26347                     associations.push(association);
26348                 }
26349
26350                 delete data.hasMany;
26351             }
26352
26353             if (superAssociations) {
26354                 associations = superAssociations.items.concat(associations);
26355             }
26356
26357             for (i = 0, ln = associations.length; i < ln; ++i) {
26358                 dependencies.push('association.' + associations[i].type.toLowerCase());
26359             }
26360
26361             if (data.proxy) {
26362                 if (typeof data.proxy === 'string') {
26363                     dependencies.push('proxy.' + data.proxy);
26364                 }
26365                 else if (typeof data.proxy.type === 'string') {
26366                     dependencies.push('proxy.' + data.proxy.type);
26367                 }
26368             }
26369
26370             Ext.require(dependencies, function() {
26371                 Ext.ModelManager.registerType(name, cls);
26372
26373                 for (i = 0, ln = associations.length; i < ln; ++i) {
26374                     association = associations[i];
26375
26376                     Ext.apply(association, {
26377                         ownerModel: name,
26378                         associatedModel: association.model
26379                     });
26380
26381                     if (Ext.ModelManager.getModel(association.model) === undefined) {
26382                         Ext.ModelManager.registerDeferredAssociation(association);
26383                     } else {
26384                         associationsMixedCollection.add(Ext.data.Association.create(association));
26385                     }
26386                 }
26387
26388                 data.associations = associationsMixedCollection;
26389
26390                 onBeforeClassCreated.call(me, cls, data);
26391
26392                 cls.setProxy(cls.prototype.proxy || cls.prototype.defaultProxyType);
26393
26394                 
26395                 Ext.ModelManager.onModelDefined(cls);
26396             });
26397         };
26398     },
26399
26400     inheritableStatics: {
26401         
26402         setProxy: function(proxy) {
26403             
26404             if (!proxy.isProxy) {
26405                 if (typeof proxy == "string") {
26406                     proxy = {
26407                         type: proxy
26408                     };
26409                 }
26410                 proxy = Ext.createByAlias("proxy." + proxy.type, proxy);
26411             }
26412             proxy.setModel(this);
26413             this.proxy = this.prototype.proxy = proxy;
26414
26415             return proxy;
26416         },
26417
26418         
26419         getProxy: function() {
26420             return this.proxy;
26421         },
26422
26423         
26424         load: function(id, config) {
26425             config = Ext.apply({}, config);
26426             config = Ext.applyIf(config, {
26427                 action: 'read',
26428                 id    : id
26429             });
26430
26431             var operation  = Ext.create('Ext.data.Operation', config),
26432                 scope      = config.scope || this,
26433                 record     = null,
26434                 callback;
26435
26436             callback = function(operation) {
26437                 if (operation.wasSuccessful()) {
26438                     record = operation.getRecords()[0];
26439                     Ext.callback(config.success, scope, [record, operation]);
26440                 } else {
26441                     Ext.callback(config.failure, scope, [record, operation]);
26442                 }
26443                 Ext.callback(config.callback, scope, [record, operation]);
26444             };
26445
26446             this.proxy.read(operation, callback, this);
26447         }
26448     },
26449
26450     statics: {
26451         PREFIX : 'ext-record',
26452         AUTO_ID: 1,
26453         EDIT   : 'edit',
26454         REJECT : 'reject',
26455         COMMIT : 'commit',
26456
26457         
26458         id: function(rec) {
26459             var id = [this.PREFIX, '-', this.AUTO_ID++].join('');
26460             rec.phantom = true;
26461             rec.internalId = id;
26462             return id;
26463         }
26464     },
26465     
26466     
26467     editing : false,
26468
26469     
26470     dirty : false,
26471
26472     
26473     persistanceProperty: 'data',
26474
26475     evented: false,
26476     isModel: true,
26477
26478     
26479     phantom : false,
26480
26481     
26482     idProperty: 'id',
26483
26484     
26485     defaultProxyType: 'ajax',
26486
26487     
26488
26489     
26490     constructor: function(data, id, raw) {
26491         data = data || {};
26492         
26493         var me = this,
26494             fields,
26495             length,
26496             field,
26497             name,
26498             i,
26499             isArray = Ext.isArray(data),
26500             newData = isArray ? {} : null; 
26501
26502         
26503         me.internalId = (id || id === 0) ? id : Ext.data.Model.id(me);
26504         
26505         
26506         me.raw = raw;
26507
26508         Ext.applyIf(me, {
26509             data: {}    
26510         });
26511         
26512         
26513         me.modified = {};
26514
26515         me[me.persistanceProperty] = {};
26516
26517         me.mixins.observable.constructor.call(me);
26518
26519         
26520         fields = me.fields.items;
26521         length = fields.length;
26522
26523         for (i = 0; i < length; i++) {
26524             field = fields[i];
26525             name  = field.name;
26526
26527             if (isArray){ 
26528                 
26529                 
26530                 newData[name] = data[i];
26531             }
26532             else if (data[name] === undefined) {
26533                 data[name] = field.defaultValue;
26534             }
26535         }
26536
26537         me.set(newData || data);
26538         
26539         me.dirty = false;
26540         me.modified = {};
26541
26542         if (me.getId()) {
26543             me.phantom = false;
26544         }
26545
26546         if (typeof me.init == 'function') {
26547             me.init();
26548         }
26549
26550         me.id = me.modelName + '-' + me.internalId;
26551
26552         Ext.ModelManager.register(me);
26553     },
26554     
26555     
26556     get: function(field) {
26557         return this[this.persistanceProperty][field];
26558     },
26559     
26560     
26561     set: function(fieldName, value) {
26562         var me = this,
26563             fields = me.fields,
26564             modified = me.modified,
26565             convertFields = [],
26566             field, key, i, currentValue;
26567
26568         
26569         if (arguments.length == 1 && Ext.isObject(fieldName)) {
26570             for (key in fieldName) {
26571                 if (fieldName.hasOwnProperty(key)) {
26572                 
26573                     
26574                     
26575                     field = fields.get(key);
26576                     if (field && field.convert !== field.type.convert) {
26577                         convertFields.push(key);
26578                         continue;
26579                     }
26580                     
26581                     me.set(key, fieldName[key]);
26582                 }
26583             }
26584
26585             for (i = 0; i < convertFields.length; i++) {
26586                 field = convertFields[i];
26587                 me.set(field, fieldName[field]);
26588             }
26589
26590         } else {
26591             if (fields) {
26592                 field = fields.get(fieldName);
26593
26594                 if (field && field.convert) {
26595                     value = field.convert(value, me);
26596                 }
26597             }
26598             currentValue = me.get(fieldName);
26599             me[me.persistanceProperty][fieldName] = value;
26600             
26601             if (field && field.persist && !me.isEqual(currentValue, value)) {
26602                 me.dirty = true;
26603                 me.modified[fieldName] = currentValue;
26604             }
26605
26606             if (!me.editing) {
26607                 me.afterEdit();
26608             }
26609         }
26610     },
26611     
26612     
26613     isEqual: function(a, b){
26614         if (Ext.isDate(a) && Ext.isDate(b)) {
26615             return a.getTime() === b.getTime();
26616         }
26617         return a === b;
26618     },
26619     
26620     
26621     beginEdit : function(){
26622         var me = this;
26623         if (!me.editing) {
26624             me.editing = true;
26625             me.dirtySave = me.dirty;
26626             me.dataSave = Ext.apply({}, me[me.persistanceProperty]);
26627             me.modifiedSave = Ext.apply({}, me.modified);
26628         }
26629     },
26630     
26631     
26632     cancelEdit : function(){
26633         var me = this;
26634         if (me.editing) {
26635             me.editing = false;
26636             
26637             me.modified = me.modifiedSave;
26638             me[me.persistanceProperty] = me.dataSave;
26639             me.dirty = me.dirtySave;
26640             delete me.modifiedSave;
26641             delete me.dataSave;
26642             delete me.dirtySave;
26643         }
26644     },
26645     
26646     
26647     endEdit : function(silent){
26648         var me = this;
26649         if (me.editing) {
26650             me.editing = false;
26651             delete me.modifiedSave;
26652             delete me.dataSave;
26653             delete me.dirtySave;
26654             if (silent !== true && me.dirty) {
26655                 me.afterEdit();
26656             }
26657         }
26658     },
26659     
26660     
26661     getChanges : function(){
26662         var modified = this.modified,
26663             changes  = {},
26664             field;
26665
26666         for (field in modified) {
26667             if (modified.hasOwnProperty(field)){
26668                 changes[field] = this.get(field);
26669             }
26670         }
26671
26672         return changes;
26673     },
26674     
26675     
26676     isModified : function(fieldName) {
26677         return this.modified.hasOwnProperty(fieldName);
26678     },
26679     
26680     
26681     setDirty : function() {
26682         var me = this,
26683             name;
26684         
26685         me.dirty = true;
26686
26687         me.fields.each(function(field) {
26688             if (field.persist) {
26689                 name = field.name;
26690                 me.modified[name] = me.get(name);
26691             }
26692         }, me);
26693     },
26694
26695     markDirty : function() {
26696         if (Ext.isDefined(Ext.global.console)) {
26697             Ext.global.console.warn('Ext.data.Model: markDirty has been deprecated. Use setDirty instead.');
26698         }
26699         return this.setDirty.apply(this, arguments);
26700     },
26701     
26702     
26703     reject : function(silent) {
26704         var me = this,
26705             modified = me.modified,
26706             field;
26707
26708         for (field in modified) {
26709             if (modified.hasOwnProperty(field)) {
26710                 if (typeof modified[field] != "function") {
26711                     me[me.persistanceProperty][field] = modified[field];
26712                 }
26713             }
26714         }
26715
26716         me.dirty = false;
26717         me.editing = false;
26718         me.modified = {};
26719
26720         if (silent !== true) {
26721             me.afterReject();
26722         }
26723     },
26724
26725     
26726     commit : function(silent) {
26727         var me = this;
26728         
26729         me.dirty = false;
26730         me.editing = false;
26731
26732         me.modified = {};
26733
26734         if (silent !== true) {
26735             me.afterCommit();
26736         }
26737     },
26738
26739     
26740     copy : function(newId) {
26741         var me = this;
26742         
26743         return new me.self(Ext.apply({}, me[me.persistanceProperty]), newId || me.internalId);
26744     },
26745
26746     
26747     setProxy: function(proxy) {
26748         
26749         if (!proxy.isProxy) {
26750             if (typeof proxy === "string") {
26751                 proxy = {
26752                     type: proxy
26753                 };
26754             }
26755             proxy = Ext.createByAlias("proxy." + proxy.type, proxy);
26756         }
26757         proxy.setModel(this.self);
26758         this.proxy = proxy;
26759
26760         return proxy;
26761     },
26762
26763     
26764     getProxy: function() {
26765         return this.proxy;
26766     },
26767
26768     
26769     validate: function() {
26770         var errors      = Ext.create('Ext.data.Errors'),
26771             validations = this.validations,
26772             validators  = Ext.data.validations,
26773             length, validation, field, valid, type, i;
26774
26775         if (validations) {
26776             length = validations.length;
26777
26778             for (i = 0; i < length; i++) {
26779                 validation = validations[i];
26780                 field = validation.field || validation.name;
26781                 type  = validation.type;
26782                 valid = validators[type](validation, this.get(field));
26783
26784                 if (!valid) {
26785                     errors.add({
26786                         field  : field,
26787                         message: validation.message || validators[type + 'Message']
26788                     });
26789                 }
26790             }
26791         }
26792
26793         return errors;
26794     },
26795
26796     
26797     isValid: function(){
26798         return this.validate().isValid();
26799     },
26800
26801     
26802     save: function(options) {
26803         options = Ext.apply({}, options);
26804
26805         var me     = this,
26806             action = me.phantom ? 'create' : 'update',
26807             record = null,
26808             scope  = options.scope || me,
26809             operation,
26810             callback;
26811
26812         Ext.apply(options, {
26813             records: [me],
26814             action : action
26815         });
26816
26817         operation = Ext.create('Ext.data.Operation', options);
26818
26819         callback = function(operation) {
26820             if (operation.wasSuccessful()) {
26821                 record = operation.getRecords()[0];
26822                 
26823                 
26824                 me.set(record.data);
26825                 record.dirty = false;
26826
26827                 Ext.callback(options.success, scope, [record, operation]);
26828             } else {
26829                 Ext.callback(options.failure, scope, [record, operation]);
26830             }
26831
26832             Ext.callback(options.callback, scope, [record, operation]);
26833         };
26834
26835         me.getProxy()[action](operation, callback, me);
26836
26837         return me;
26838     },
26839
26840     
26841     destroy: function(options){
26842         options = Ext.apply({}, options);
26843
26844         var me     = this,
26845             record = null,
26846             scope  = options.scope || me,
26847             operation,
26848             callback;
26849
26850         Ext.apply(options, {
26851             records: [me],
26852             action : 'destroy'
26853         });
26854
26855         operation = Ext.create('Ext.data.Operation', options);
26856         callback = function(operation) {
26857             if (operation.wasSuccessful()) {
26858                 Ext.callback(options.success, scope, [record, operation]);
26859             } else {
26860                 Ext.callback(options.failure, scope, [record, operation]);
26861             }
26862             Ext.callback(options.callback, scope, [record, operation]);
26863         };
26864
26865         me.getProxy().destroy(operation, callback, me);
26866         return me;
26867     },
26868
26869     
26870     getId: function() {
26871         return this.get(this.idProperty);
26872     },
26873
26874     
26875     setId: function(id) {
26876         this.set(this.idProperty, id);
26877     },
26878
26879     
26880     join : function(store) {
26881         
26882         this.store = store;
26883     },
26884
26885     
26886     unjoin: function() {
26887         delete this.store;
26888     },
26889
26890     
26891     afterEdit : function() {
26892         this.callStore('afterEdit');
26893     },
26894
26895     
26896     afterReject : function() {
26897         this.callStore("afterReject");
26898     },
26899
26900     
26901     afterCommit: function() {
26902         this.callStore('afterCommit');
26903     },
26904
26905     
26906     callStore: function(fn) {
26907         var store = this.store;
26908
26909         if (store !== undefined && typeof store[fn] == "function") {
26910             store[fn](this);
26911         }
26912     },
26913
26914     
26915     getAssociatedData: function(){
26916         return this.prepareAssociatedData(this, [], null);
26917     },
26918
26919     
26920     prepareAssociatedData: function(record, ids, associationType) {
26921         
26922         var associations     = record.associations.items,
26923             associationCount = associations.length,
26924             associationData  = {},
26925             associatedStore, associatedName, associatedRecords, associatedRecord,
26926             associatedRecordCount, association, id, i, j, type, allow;
26927
26928         for (i = 0; i < associationCount; i++) {
26929             association = associations[i];
26930             type = association.type;
26931             allow = true;
26932             if (associationType) {
26933                 allow = type == associationType;
26934             }
26935             if (allow && type == 'hasMany') {
26936
26937                 
26938                 associatedStore = record[association.storeName];
26939
26940                 
26941                 associationData[association.name] = [];
26942
26943                 
26944                 if (associatedStore && associatedStore.data.length > 0) {
26945                     associatedRecords = associatedStore.data.items;
26946                     associatedRecordCount = associatedRecords.length;
26947
26948                     
26949                     for (j = 0; j < associatedRecordCount; j++) {
26950                         associatedRecord = associatedRecords[j];
26951                         
26952                         id = associatedRecord.id;
26953
26954                         
26955                         
26956                         if (Ext.Array.indexOf(ids, id) == -1) {
26957                             ids.push(id);
26958
26959                             associationData[association.name][j] = associatedRecord.data;
26960                             Ext.apply(associationData[association.name][j], this.prepareAssociatedData(associatedRecord, ids, type));
26961                         }
26962                     }
26963                 }
26964             } else if (allow && type == 'belongsTo') {
26965                 associatedRecord = record[association.instanceName];
26966                 if (associatedRecord !== undefined) {
26967                     id = associatedRecord.id;
26968                     if (Ext.Array.indexOf(ids, id) == -1) {
26969                         ids.push(id);
26970                         associationData[association.name] = associatedRecord.data;
26971                         Ext.apply(associationData[association.name], this.prepareAssociatedData(associatedRecord, ids, type));
26972                     }
26973                 }
26974             }
26975         }
26976
26977         return associationData;
26978     }
26979 });
26980
26981
26982
26983 Ext.define('Ext.Component', {
26984
26985     
26986
26987     alias: ['widget.component', 'widget.box'],
26988
26989     extend: 'Ext.AbstractComponent',
26990
26991     requires: [
26992         'Ext.util.DelayedTask'
26993     ],
26994
26995     uses: [
26996         'Ext.Layer',
26997         'Ext.resizer.Resizer',
26998         'Ext.util.ComponentDragger'
26999     ],
27000
27001     mixins: {
27002         floating: 'Ext.util.Floating'
27003     },
27004
27005     statics: {
27006         
27007         DIRECTION_TOP: 'top',
27008         DIRECTION_RIGHT: 'right',
27009         DIRECTION_BOTTOM: 'bottom',
27010         DIRECTION_LEFT: 'left'
27011     },
27012
27013     
27014
27015     
27016
27017     
27018     resizeHandles: 'all',
27019
27020     
27021
27022     
27023     floating: false,
27024
27025     
27026     toFrontOnShow: true,
27027
27028     
27029
27030      
27031
27032     
27033
27034     
27035
27036     hideMode: 'display',
27037     
27038     hideParent: false,
27039
27040     ariaRole: 'presentation',
27041
27042     bubbleEvents: [],
27043
27044     actionMode: 'el',
27045     monPropRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
27046
27047     
27048     
27049     
27050     
27051     
27052     
27053     constructor: function(config) {
27054         config = config || {};
27055         if (config.initialConfig) {
27056
27057             
27058             if (config.isAction) {
27059                 this.baseAction = config;
27060             }
27061             config = config.initialConfig;
27062             
27063         }
27064         else if (config.tagName || config.dom || Ext.isString(config)) {
27065             
27066             config = {
27067                 applyTo: config,
27068                 id: config.id || config
27069             };
27070         }
27071
27072         this.callParent([config]);
27073
27074         
27075         
27076         if (this.baseAction){
27077             this.baseAction.addComponent(this);
27078         }
27079     },
27080
27081     initComponent: function() {
27082         var me = this;
27083
27084         if (me.listeners) {
27085             me.on(me.listeners);
27086             delete me.listeners;
27087         }
27088         me.enableBubble(me.bubbleEvents);
27089         me.mons = [];
27090     },
27091
27092     
27093     afterRender: function() {
27094         var me = this,
27095             resizable = me.resizable;
27096
27097         if (me.floating) {
27098             me.makeFloating(me.floating);
27099         } else {
27100             me.el.setVisibilityMode(Ext.core.Element[me.hideMode.toUpperCase()]);
27101         }
27102
27103         if (Ext.isDefined(me.autoScroll)) {
27104             me.setAutoScroll(me.autoScroll);
27105         }
27106         me.callParent();
27107
27108         if (!(me.x && me.y) && (me.pageX || me.pageY)) {
27109             me.setPagePosition(me.pageX, me.pageY);
27110         }
27111
27112         if (resizable) {
27113             me.initResizable(resizable);
27114         }
27115
27116         if (me.draggable) {
27117             me.initDraggable();
27118         }
27119
27120         me.initAria();
27121     },
27122
27123     initAria: function() {
27124         var actionEl = this.getActionEl(),
27125             role = this.ariaRole;
27126         if (role) {
27127             actionEl.dom.setAttribute('role', role);
27128         }
27129     },
27130
27131     
27132     setAutoScroll : function(scroll){
27133         var me = this,
27134             targetEl;
27135         scroll = !!scroll;
27136         if (me.rendered) {
27137             targetEl = me.getTargetEl();
27138             targetEl.setStyle('overflow', scroll ? 'auto' : '');
27139             if (scroll && (Ext.isIE6 || Ext.isIE7)) {
27140                 
27141                 
27142                 targetEl.position();
27143             }
27144         }
27145         me.autoScroll = scroll;
27146         return me;
27147     },
27148
27149     
27150     makeFloating : function(cfg){
27151         this.mixins.floating.constructor.call(this, cfg);
27152     },
27153
27154     initResizable: function(resizable) {
27155         resizable = Ext.apply({
27156             target: this,
27157             dynamic: false,
27158             constrainTo: this.constrainTo,
27159             handles: this.resizeHandles
27160         }, resizable);
27161         resizable.target = this;
27162         this.resizer = Ext.create('Ext.resizer.Resizer', resizable);
27163     },
27164
27165     getDragEl: function() {
27166         return this.el;
27167     },
27168
27169     initDraggable: function() {
27170         var me = this,
27171             ddConfig = Ext.applyIf({
27172                 el: this.getDragEl(),
27173                 constrainTo: me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.el.dom.parentNode)
27174             }, this.draggable);
27175
27176         
27177         if (me.constrain || me.constrainDelegate) {
27178             ddConfig.constrain = me.constrain;
27179             ddConfig.constrainDelegate = me.constrainDelegate;
27180         }
27181
27182         this.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig);
27183     },
27184
27185     
27186     setPosition: function(x, y, animate) {
27187         var me = this,
27188             el = me.el,
27189             to = {},
27190             adj, adjX, adjY, xIsNumber, yIsNumber;
27191
27192         if (Ext.isArray(x)) {
27193             animate = y;
27194             y = x[1];
27195             x = x[0];
27196         }
27197         me.x = x;
27198         me.y = y;
27199
27200         if (!me.rendered) {
27201             return me;
27202         }
27203
27204         adj = me.adjustPosition(x, y);
27205         adjX = adj.x;
27206         adjY = adj.y;
27207         xIsNumber = Ext.isNumber(adjX);
27208         yIsNumber = Ext.isNumber(adjY);
27209
27210         if (xIsNumber || yIsNumber) {
27211             if (animate) {
27212                 if (xIsNumber) {
27213                     to.left = adjX;
27214                 }
27215                 if (yIsNumber) {
27216                     to.top = adjY;
27217                 }
27218
27219                 me.stopAnimation();
27220                 me.animate(Ext.apply({
27221                     duration: 1000,
27222                     listeners: {
27223                         afteranimate: Ext.Function.bind(me.afterSetPosition, me, [adjX, adjY])
27224                     },
27225                     to: to
27226                 }, animate));
27227             }
27228             else {
27229                 if (!xIsNumber) {
27230                     el.setTop(adjY);
27231                 }
27232                 else if (!yIsNumber) {
27233                     el.setLeft(adjX);
27234                 }
27235                 else {
27236                     el.setLeftTop(adjX, adjY);
27237                 }
27238                 me.afterSetPosition(adjX, adjY);
27239             }
27240         }
27241         return me;
27242     },
27243
27244     
27245     afterSetPosition: function(ax, ay) {
27246         this.onPosition(ax, ay);
27247         this.fireEvent('move', this, ax, ay);
27248     },
27249
27250     showAt: function(x, y, animate) {
27251         
27252         if (this.floating) {
27253             this.setPosition(x, y, animate);
27254         } else {
27255             this.setPagePosition(x, y, animate);
27256         }
27257         this.show();
27258     },
27259
27260     
27261     setPagePosition: function(x, y, animate) {
27262         var me = this,
27263             p;
27264
27265         if (Ext.isArray(x)) {
27266             y = x[1];
27267             x = x[0];
27268         }
27269         me.pageX = x;
27270         me.pageY = y;
27271         if (me.floating && me.floatParent) {
27272             
27273             p = me.floatParent.getTargetEl().getViewRegion();
27274             if (Ext.isNumber(x) && Ext.isNumber(p.left)) {
27275                 x -= p.left;
27276             }
27277             if (Ext.isNumber(y) && Ext.isNumber(p.top)) {
27278                 y -= p.top;
27279             }
27280             me.setPosition(x, y, animate);
27281         }
27282         else {
27283             p = me.el.translatePoints(x, y);
27284             me.setPosition(p.left, p.top, animate);
27285         }
27286         return me;
27287     },
27288
27289     
27290     getBox : function(local){
27291         var pos = this.getPosition(local);
27292         var s = this.getSize();
27293         s.x = pos[0];
27294         s.y = pos[1];
27295         return s;
27296     },
27297
27298     
27299     updateBox : function(box){
27300         this.setSize(box.width, box.height);
27301         this.setPagePosition(box.x, box.y);
27302         return this;
27303     },
27304
27305     
27306     getOuterSize: function() {
27307         var el = this.el;
27308         return {
27309             width: el.getWidth() + el.getMargin('lr'),
27310             height: el.getHeight() + el.getMargin('tb')
27311         };
27312     },
27313
27314     
27315     adjustSize: function(w, h) {
27316         if (this.autoWidth) {
27317             w = 'auto';
27318         }
27319
27320         if (this.autoHeight) {
27321             h = 'auto';
27322         }
27323
27324         return {
27325             width: w,
27326             height: h
27327         };
27328     },
27329
27330     
27331     adjustPosition: function(x, y) {
27332
27333         
27334         if (this.floating && this.floatParent) {
27335             var o = this.floatParent.getTargetEl().getViewRegion();
27336             x += o.left;
27337             y += o.top;
27338         }
27339
27340         return {
27341             x: x,
27342             y: y
27343         };
27344     },
27345
27346     
27347     getPosition: function(local) {
27348         var el = this.el,
27349             xy;
27350
27351         if (local === true) {
27352             return [el.getLeft(true), el.getTop(true)];
27353         }
27354         xy = this.xy || el.getXY();
27355
27356         
27357         if (this.floating && this.floatParent) {
27358             var o = this.floatParent.getTargetEl().getViewRegion();
27359             xy[0] -= o.left;
27360             xy[1] -= o.top;
27361         }
27362         return xy;
27363     },
27364
27365     
27366     getId: function() {
27367         return this.id || (this.id = (this.getXType() || 'ext-comp') + '-' + this.getAutoId());
27368     },
27369
27370     onEnable: function() {
27371         var actionEl = this.getActionEl();
27372         actionEl.dom.removeAttribute('aria-disabled');
27373         actionEl.dom.disabled = false;
27374         this.callParent();
27375     },
27376
27377     onDisable: function() {
27378         var actionEl = this.getActionEl();
27379         actionEl.dom.setAttribute('aria-disabled', true);
27380         actionEl.dom.disabled = true;
27381         this.callParent();
27382     },
27383
27384     
27385     show: function(animateTarget, cb, scope) {
27386         if (this.rendered && this.isVisible()) {
27387             if (this.toFrontOnShow && this.floating) {
27388                 this.toFront();
27389             }
27390         } else if (this.fireEvent('beforeshow', this) !== false) {
27391             this.hidden = false;
27392
27393             
27394             if (!this.rendered && (this.autoRender || this.floating)) {
27395                 this.doAutoRender();
27396             }
27397             if (this.rendered) {
27398                 this.beforeShow();
27399                 this.onShow.apply(this, arguments);
27400
27401                 
27402                 
27403                 if (this.ownerCt && !this.floating && !(this.ownerCt.suspendLayout || this.ownerCt.layout.layoutBusy)) {
27404                     this.ownerCt.doLayout();
27405                 }
27406                 this.afterShow.apply(this, arguments);
27407             }
27408         }
27409         return this;
27410     },
27411
27412     beforeShow: Ext.emptyFn,
27413
27414     
27415     onShow: function() {
27416         var me = this;
27417
27418         me.el.show();
27419         if (this.floating && this.constrain) {
27420             this.doConstrain();
27421         }
27422         me.callParent(arguments);
27423     },
27424
27425     afterShow: function(animateTarget, cb, scope) {
27426         var me = this,
27427             fromBox,
27428             toBox,
27429             ghostPanel;
27430
27431         
27432         animateTarget = animateTarget || me.animateTarget;
27433
27434         
27435         if (!me.ghost) {
27436             animateTarget = null;
27437         }
27438         
27439         if (animateTarget) {
27440             animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget);
27441             toBox = me.el.getBox();
27442             fromBox = animateTarget.getBox();
27443             fromBox.width += 'px';
27444             fromBox.height += 'px';
27445             toBox.width += 'px';
27446             toBox.height += 'px';
27447             me.el.addCls(Ext.baseCSSPrefix + 'hide-offsets');
27448             ghostPanel = me.ghost();
27449             ghostPanel.el.stopAnimation();
27450
27451             ghostPanel.el.animate({
27452                 from: fromBox,
27453                 to: toBox,
27454                 listeners: {
27455                     afteranimate: function() {
27456                         delete ghostPanel.componentLayout.lastComponentSize;
27457                         me.unghost();
27458                         me.el.removeCls(Ext.baseCSSPrefix + 'hide-offsets');
27459                         if (me.floating) {
27460                             me.toFront();
27461                         }
27462                         Ext.callback(cb, scope || me);
27463                     }
27464                 }
27465             });
27466         }
27467         else {
27468             if (me.floating) {
27469                 me.toFront();
27470             }
27471             Ext.callback(cb, scope || me);
27472         }
27473         me.fireEvent('show', me);
27474     },
27475
27476     
27477     hide: function() {
27478
27479         
27480         
27481         this.showOnParentShow = false;
27482
27483         if (!(this.rendered && !this.isVisible()) && this.fireEvent('beforehide', this) !== false) {
27484             this.hidden = true;
27485             if (this.rendered) {
27486                 this.onHide.apply(this, arguments);
27487
27488                 
27489                 
27490                 if (this.ownerCt && !this.floating && !(this.ownerCt.suspendLayout || this.ownerCt.layout.layoutBusy)) {
27491                     this.ownerCt.doLayout();
27492                 }
27493             }
27494         }
27495         return this;
27496     },
27497
27498     
27499     onHide: function(animateTarget, cb, scope) {
27500         var me = this,
27501             ghostPanel,
27502             toBox;
27503
27504         
27505         animateTarget = animateTarget || me.animateTarget;
27506
27507         
27508         if (!me.ghost) {
27509             animateTarget = null;
27510         }
27511         
27512         if (animateTarget) {
27513             animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget);
27514             ghostPanel = me.ghost();
27515             ghostPanel.el.stopAnimation();
27516             toBox = animateTarget.getBox();
27517             toBox.width += 'px';
27518             toBox.height += 'px';
27519             ghostPanel.el.animate({
27520                 to: toBox,
27521                 listeners: {
27522                     afteranimate: function() {
27523                         delete ghostPanel.componentLayout.lastComponentSize;
27524                         ghostPanel.el.hide();
27525                         me.afterHide(cb, scope);
27526                     }
27527                 }
27528             });
27529         }
27530         me.el.hide();
27531         if (!animateTarget) {
27532             me.afterHide(cb, scope);
27533         }
27534     },
27535
27536     afterHide: function(cb, scope) {
27537         Ext.callback(cb, scope || this);
27538         this.fireEvent('hide', this);
27539     },
27540
27541     
27542     onDestroy: function() {
27543         var me = this;
27544
27545         
27546         if (me.rendered) {
27547             Ext.destroy(
27548                 me.proxy,
27549                 me.resizer
27550             );
27551             
27552             if (me.actionMode == 'container' || me.removeMode == 'container') {
27553                 me.container.remove();
27554             }
27555         }
27556         delete me.focusTask;
27557         me.callParent();
27558     },
27559
27560     deleteMembers: function() {
27561         var args = arguments,
27562             len = args.length,
27563             i = 0;
27564         for (; i < len; ++i) {
27565             delete this[args[i]];
27566         }
27567     },
27568
27569     
27570     focus: function(selectText, delay) {
27571         var me = this,
27572                 focusEl;
27573
27574         if (delay) {
27575             if (!me.focusTask) {
27576                 me.focusTask = Ext.create('Ext.util.DelayedTask', me.focus);
27577             }
27578             me.focusTask.delay(Ext.isNumber(delay) ? delay : 10, null, me, [selectText, false]);
27579             return me;
27580         }
27581
27582         if (me.rendered && !me.isDestroyed) {
27583             
27584             focusEl = me.getFocusEl();
27585             focusEl.focus();
27586             if (focusEl.dom && selectText === true) {
27587                 focusEl.dom.select();
27588             }
27589
27590             
27591             
27592             if (me.floating) {
27593                 me.toFront(true);
27594             }
27595         }
27596         return me;
27597     },
27598
27599     
27600     getFocusEl: function() {
27601         return this.el;
27602     },
27603
27604     
27605     blur: function() {
27606         if (this.rendered) {
27607             this.getFocusEl().blur();
27608         }
27609         return this;
27610     },
27611
27612     getEl: function() {
27613         return this.el;
27614     },
27615
27616     
27617     getResizeEl: function() {
27618         return this.el;
27619     },
27620
27621     
27622     getPositionEl: function() {
27623         return this.el;
27624     },
27625
27626     
27627     getActionEl: function() {
27628         return this.el;
27629     },
27630
27631     
27632     getVisibilityEl: function() {
27633         return this.el;
27634     },
27635
27636     
27637     onResize: Ext.emptyFn,
27638
27639     
27640     getBubbleTarget: function() {
27641         return this.ownerCt;
27642     },
27643
27644     
27645     getContentTarget: function() {
27646         return this.el;
27647     },
27648
27649     
27650     cloneConfig: function(overrides) {
27651         overrides = overrides || {};
27652         var id = overrides.id || Ext.id();
27653         var cfg = Ext.applyIf(overrides, this.initialConfig);
27654         cfg.id = id;
27655
27656         var self = Ext.getClass(this);
27657
27658         
27659         return new self(cfg);
27660     },
27661
27662     
27663     getXType: function() {
27664         return this.self.xtype;
27665     },
27666
27667     
27668     findParentBy: function(fn) {
27669         var p;
27670
27671         
27672         for (p = this.ownerCt; p && !fn(p, this); p = p.ownerCt);
27673         return p || null;
27674     },
27675
27676     
27677     findParentByType: function(xtype) {
27678         return Ext.isFunction(xtype) ?
27679             this.findParentBy(function(p) {
27680                 return p.constructor === xtype;
27681             })
27682         :
27683             this.up(xtype);
27684     },
27685
27686     
27687     bubble: function(fn, scope, args) {
27688         var p = this;
27689         while (p) {
27690             if (fn.apply(scope || p, args || [p]) === false) {
27691                 break;
27692             }
27693             p = p.ownerCt;
27694         }
27695         return this;
27696     },
27697
27698     getProxy: function() {
27699         if (!this.proxy) {
27700             this.proxy = this.el.createProxy(Ext.baseCSSPrefix + 'proxy-el', Ext.getBody(), true);
27701         }
27702         return this.proxy;
27703     }
27704
27705 });
27706
27707
27708 Ext.define('Ext.layout.container.Container', {
27709
27710     
27711
27712     extend: 'Ext.layout.container.AbstractContainer',
27713     alternateClassName: 'Ext.layout.ContainerLayout',
27714     
27715     
27716
27717     layoutItem: function(item, box) {
27718         box = box || {};
27719         if (item.componentLayout.initialized !== true) {
27720             this.setItemSize(item, box.width || item.width || undefined, box.height || item.height || undefined);
27721             
27722         }
27723     },
27724
27725     getLayoutTargetSize : function() {
27726         var target = this.getTarget(),
27727             ret;
27728
27729         if (target) {
27730             ret = target.getViewSize();
27731
27732             
27733             
27734             
27735             if (Ext.isIE && ret.width == 0){
27736                 ret = target.getStyleSize();
27737             }
27738
27739             ret.width -= target.getPadding('lr');
27740             ret.height -= target.getPadding('tb');
27741         }
27742         return ret;
27743     },
27744
27745     beforeLayout: function() {
27746         if (this.owner.beforeLayout(arguments) !== false) {
27747             return this.callParent(arguments);
27748         }
27749         else {
27750             return false;
27751         }
27752     },
27753
27754     afterLayout: function() {
27755         this.owner.afterLayout(arguments);
27756         this.callParent(arguments);
27757     },
27758
27759     
27760     getRenderedItems: function() {
27761         var me = this,
27762             target = me.getTarget(),
27763             items = me.getLayoutItems(),
27764             ln = items.length,
27765             renderedItems = [],
27766             i, item;
27767
27768         for (i = 0; i < ln; i++) {
27769             item = items[i];
27770             if (item.rendered && me.isValidParent(item, target, i)) {
27771                 renderedItems.push(item);
27772             }
27773         }
27774
27775         return renderedItems;
27776     },
27777
27778     
27779     getVisibleItems: function() {
27780         var target   = this.getTarget(),
27781             items = this.getLayoutItems(),
27782             ln = items.length,
27783             visibleItems = [],
27784             i, item;
27785
27786         for (i = 0; i < ln; i++) {
27787             item = items[i];
27788             if (item.rendered && this.isValidParent(item, target, i) && item.hidden !== true) {
27789                 visibleItems.push(item);
27790             }
27791         }
27792
27793         return visibleItems;
27794     }
27795 });
27796
27797
27798 Ext.define('Ext.layout.container.Auto', {
27799
27800     
27801
27802     alias: ['layout.auto', 'layout.autocontainer'],
27803
27804     extend: 'Ext.layout.container.Container',
27805
27806     
27807
27808     type: 'autocontainer',
27809
27810     fixedLayout: false,
27811
27812     bindToOwnerCtComponent: true,
27813
27814     
27815     onLayout : function(owner, target) {
27816         var me = this,
27817             items = me.getLayoutItems(),
27818             ln = items.length,
27819             i;
27820
27821         
27822         if (ln) {
27823             
27824             
27825             
27826             if (!me.clearEl) {
27827                 me.clearEl = me.getRenderTarget().createChild({
27828                     cls: Ext.baseCSSPrefix + 'clear',
27829                     role: 'presentation'
27830                 });
27831             }
27832
27833             
27834             for (i = 0; i < ln; i++) {
27835                 me.setItemSize(items[i]);
27836             }
27837         }
27838     }
27839 });
27840
27841 Ext.define('Ext.container.AbstractContainer', {
27842
27843     
27844
27845     extend: 'Ext.Component',
27846
27847     requires: [
27848         'Ext.util.MixedCollection',
27849         'Ext.layout.container.Auto',
27850         'Ext.ZIndexManager'
27851     ],
27852
27853     
27854     
27855
27856     
27857     
27858     
27859
27860     
27861     suspendLayout : false,
27862
27863     
27864     autoDestroy : true,
27865
27866      
27867     defaultType: 'panel',
27868
27869     isContainer : true,
27870
27871     baseCls: Ext.baseCSSPrefix + 'container',
27872
27873     
27874     bubbleEvents: ['add', 'remove'],
27875     
27876     
27877     initComponent : function(){
27878         var me = this;
27879         me.addEvents(
27880             
27881             'afterlayout',
27882             
27883             'beforeadd',
27884             
27885             'beforeremove',
27886             
27887             'add',
27888             
27889             'remove',
27890             
27891             'beforecardswitch',
27892             
27893             'cardswitch'
27894         );
27895
27896         
27897         me.layoutOnShow = Ext.create('Ext.util.MixedCollection');
27898         me.callParent();
27899         me.initItems();
27900     },
27901
27902     
27903     initItems : function() {
27904         var me = this,
27905             items = me.items;
27906
27907         
27908         me.items = Ext.create('Ext.util.MixedCollection', false, me.getComponentId);
27909
27910         if (items) {
27911             if (!Ext.isArray(items)) {
27912                 items = [items];
27913             }
27914
27915             me.add(items);
27916         }
27917     },
27918
27919     
27920     afterRender : function() {
27921         this.getLayout();
27922         this.callParent();
27923     },
27924
27925     
27926     setLayout : function(layout) {
27927         var currentLayout = this.layout;
27928
27929         if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
27930             currentLayout.setOwner(null);
27931         }
27932
27933         this.layout = layout;
27934         layout.setOwner(this);
27935     },
27936
27937     
27938     getLayout : function() {
27939         var me = this;
27940         if (!me.layout || !me.layout.isLayout) {
27941             me.setLayout(Ext.layout.Layout.create(me.layout, 'autocontainer'));
27942         }
27943
27944         return me.layout;
27945     },
27946
27947     
27948     doLayout : function() {
27949         var me = this,
27950             layout = me.getLayout();
27951
27952         if (me.rendered && layout && !me.suspendLayout) {
27953             
27954             if ((!Ext.isNumber(me.width) || !Ext.isNumber(me.height)) && me.componentLayout.type !== 'autocomponent') {
27955                 
27956                 if (me.componentLayout.layoutBusy !== true) {
27957                     me.doComponentLayout();
27958                     if (me.componentLayout.layoutCancelled === true) {
27959                         layout.layout();
27960                     }
27961                 }
27962             }
27963             
27964             else {
27965                 
27966                 if (layout.layoutBusy !== true) {
27967                     layout.layout();
27968                 }
27969             }
27970         }
27971
27972         return me;
27973     },
27974
27975     
27976     afterLayout : function(layout) {
27977         this.fireEvent('afterlayout', this, layout);
27978     },
27979
27980     
27981     prepareItems : function(items, applyDefaults) {
27982         if (!Ext.isArray(items)) {
27983             items = [items];
27984         }
27985
27986         
27987         var i = 0,
27988             len = items.length,
27989             item;
27990
27991         for (; i < len; i++) {
27992             item = items[i];
27993             if (applyDefaults) {
27994                 item = this.applyDefaults(item);
27995             }
27996             items[i] = this.lookupComponent(item);
27997         }
27998         return items;
27999     },
28000
28001     
28002     applyDefaults : function(config) {
28003         var defaults = this.defaults;
28004
28005         if (defaults) {
28006             if (Ext.isFunction(defaults)) {
28007                 defaults = defaults.call(this, config);
28008             }
28009
28010             if (Ext.isString(config)) {
28011                 config = Ext.ComponentManager.get(config);
28012                 Ext.applyIf(config, defaults);
28013             } else if (!config.isComponent) {
28014                 Ext.applyIf(config, defaults);
28015             } else {
28016                 Ext.applyIf(config, defaults);
28017             }
28018         }
28019
28020         return config;
28021     },
28022
28023     
28024     lookupComponent : function(comp) {
28025         return Ext.isString(comp) ? Ext.ComponentManager.get(comp) : this.createComponent(comp);
28026     },
28027
28028     
28029     createComponent : function(config, defaultType) {
28030         
28031         
28032         
28033         
28034         
28035         
28036
28037         return Ext.ComponentManager.create(config, defaultType || this.defaultType);
28038     },
28039
28040     
28041     getComponentId : function(comp) {
28042         return comp.getItemId();
28043     },
28044
28045     
28046     add : function() {
28047         var me = this,
28048             args = Array.prototype.slice.call(arguments),
28049             hasMultipleArgs,
28050             items,
28051             results = [],
28052             i,
28053             ln,
28054             item,
28055             index = -1,
28056             cmp;
28057
28058         if (typeof args[0] == 'number') {
28059             index = args.shift();
28060         }
28061
28062         hasMultipleArgs = args.length > 1;
28063         if (hasMultipleArgs || Ext.isArray(args[0])) {
28064
28065             items = hasMultipleArgs ? args : args[0];
28066             
28067             me.suspendLayout = true;
28068             for (i = 0, ln = items.length; i < ln; i++) {
28069                 item = items[i];
28070                 
28071                 if (!item) {
28072                     Ext.Error.raise("Trying to add a null item as a child of Container with itemId/id: " + me.getItemId());
28073                 }
28074                 
28075                 if (index != -1) {
28076                     item = me.add(index + i, item);
28077                 } else {
28078                     item = me.add(item);
28079                 }
28080                 results.push(item);
28081             }
28082             
28083             me.suspendLayout = false;
28084             me.doLayout();
28085             return results;
28086         }
28087
28088         cmp = me.prepareItems(args[0], true)[0];
28089
28090         
28091         
28092         
28093         if (cmp.floating) {
28094             cmp.onAdded(me, index);
28095         } else {
28096             index = (index !== -1) ? index : me.items.length;
28097             if (me.fireEvent('beforeadd', me, cmp, index) !== false && me.onBeforeAdd(cmp) !== false) {
28098                 me.items.insert(index, cmp);
28099                 cmp.onAdded(me, index);
28100                 me.onAdd(cmp, index);
28101                 me.fireEvent('add', me, cmp, index);
28102             }
28103             me.doLayout();
28104         }
28105         return cmp;
28106     },
28107
28108     
28109     registerFloatingItem: function(cmp) {
28110         var me = this;
28111         if (!me.floatingItems) {
28112             me.floatingItems = Ext.create('Ext.ZIndexManager', me);
28113         }
28114         me.floatingItems.register(cmp);
28115     },
28116
28117     onAdd : Ext.emptyFn,
28118     onRemove : Ext.emptyFn,
28119
28120     
28121     insert : function(index, comp) {
28122         return this.add(index, comp);
28123     },
28124
28125     
28126     move : function(fromIdx, toIdx) {
28127         var items = this.items,
28128             item;
28129         item = items.removeAt(fromIdx);
28130         if (item === false) {
28131             return false;
28132         }
28133         items.insert(toIdx, item);
28134         this.doLayout();
28135         return item;
28136     },
28137
28138     
28139     onBeforeAdd : function(item) {
28140         var me = this;
28141         
28142         if (item.ownerCt) {
28143             item.ownerCt.remove(item, false);
28144         }
28145
28146         if (me.border === false || me.border === 0) {
28147             item.border = (item.border === true);
28148         }
28149     },
28150
28151     
28152     remove : function(comp, autoDestroy) {
28153         var me = this,
28154             c = me.getComponent(comp);
28155             if (Ext.isDefined(Ext.global.console) && !c) {
28156                 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.");
28157             }
28158
28159         if (c && me.fireEvent('beforeremove', me, c) !== false) {
28160             me.doRemove(c, autoDestroy);
28161             me.fireEvent('remove', me, c);
28162         }
28163
28164         return c;
28165     },
28166
28167     
28168     doRemove : function(component, autoDestroy) {
28169         var me = this,
28170             layout = me.layout,
28171             hasLayout = layout && me.rendered;
28172
28173         me.items.remove(component);
28174         component.onRemoved();
28175
28176         if (hasLayout) {
28177             layout.onRemove(component);
28178         }
28179
28180         me.onRemove(component, autoDestroy);
28181
28182         if (autoDestroy === true || (autoDestroy !== false && me.autoDestroy)) {
28183             component.destroy();
28184         }
28185
28186         if (hasLayout && !autoDestroy) {
28187             layout.afterRemove(component);
28188         }
28189
28190         if (!me.destroying) {
28191             me.doLayout();
28192         }
28193     },
28194
28195     
28196     removeAll : function(autoDestroy) {
28197         var me = this,
28198             removeItems = me.items.items.slice(),
28199             items = [],
28200             i = 0,
28201             len = removeItems.length,
28202             item;
28203
28204         
28205         me.suspendLayout = true;
28206         for (; i < len; i++) {
28207             item = removeItems[i];
28208             me.remove(item, autoDestroy);
28209
28210             if (item.ownerCt !== me) {
28211                 items.push(item);
28212             }
28213         }
28214
28215         
28216         me.suspendLayout = false;
28217         me.doLayout();
28218         return items;
28219     },
28220
28221     
28222     
28223     
28224     
28225     
28226     
28227     
28228     
28229     getRefItems : function(deep) {
28230         var me = this,
28231             items = me.items.items,
28232             len = items.length,
28233             i = 0,
28234             item,
28235             result = [];
28236
28237         for (; i < len; i++) {
28238             item = items[i];
28239             result.push(item);
28240             if (deep && item.getRefItems) {
28241                 result.push.apply(result, item.getRefItems(true));
28242             }
28243         }
28244
28245         
28246         
28247         if (me.floatingItems && me.floatingItems.accessList) {
28248             result.push.apply(result, me.floatingItems.accessList);
28249         }
28250
28251         return result;
28252     },
28253
28254     
28255     cascade : function(fn, scope, origArgs){
28256         var me = this,
28257             cs = me.items ? me.items.items : [],
28258             len = cs.length,
28259             i = 0,
28260             c,
28261             args = origArgs ? origArgs.concat(me) : [me],
28262             componentIndex = args.length - 1;
28263
28264         if (fn.apply(scope || me, args) !== false) {
28265             for(; i < len; i++){
28266                 c = cs[i];
28267                 if (c.cascade) {
28268                     c.cascade(fn, scope, origArgs);
28269                 } else {
28270                     args[componentIndex] = c;
28271                     fn.apply(scope || cs, args);
28272                 }
28273             }
28274         }
28275         return this;
28276     },
28277
28278     
28279     getComponent : function(comp) {
28280         if (Ext.isObject(comp)) {
28281             comp = comp.getItemId();
28282         }
28283
28284         return this.items.get(comp);
28285     },
28286
28287     
28288     query : function(selector) {
28289         return Ext.ComponentQuery.query(selector, this);
28290     },
28291
28292     
28293     child : function(selector) {
28294         return this.query('> ' + selector)[0] || null;
28295     },
28296
28297     
28298     down : function(selector) {
28299         return this.query(selector)[0] || null;
28300     },
28301
28302     
28303     show : function() {
28304         this.callParent(arguments);
28305         this.performDeferredLayouts();
28306         return this;
28307     },
28308
28309     
28310     
28311     performDeferredLayouts: function() {
28312         var layoutCollection = this.layoutOnShow,
28313             ln = layoutCollection.getCount(),
28314             i = 0,
28315             needsLayout,
28316             item;
28317
28318         for (; i < ln; i++) {
28319             item = layoutCollection.get(i);
28320             needsLayout = item.needsLayout;
28321
28322             if (Ext.isObject(needsLayout)) {
28323                 item.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
28324             }
28325         }
28326         layoutCollection.clear();
28327     },    
28328     
28329     //@private
28330
28331     
28332     onEnable: function() {
28333         Ext.Array.each(this.query('[isFormField]'), function(item) {
28334             if (item.resetDisable) {
28335                 item.enable();
28336                 delete item.resetDisable;             
28337             }
28338         });
28339         this.callParent();
28340     },
28341     
28342     
28343     
28344     onDisable: function() {
28345         Ext.Array.each(this.query('[isFormField]'), function(item) {
28346             if (item.resetDisable !== false && !item.disabled) {
28347                 item.disable();
28348                 item.resetDisable = true;
28349             }
28350         });
28351         this.callParent();
28352     },
28353
28354     
28355     beforeLayout: function() {
28356         return true;
28357     },
28358
28359     
28360     beforeDestroy : function() {
28361         var me = this,
28362             items = me.items,
28363             c;
28364
28365         if (items) {
28366             while ((c = items.first())) {
28367                 me.doRemove(c, true);
28368             }
28369         }
28370
28371         Ext.destroy(
28372             me.layout,
28373             me.floatingItems
28374         );
28375         me.callParent();
28376     }
28377 });
28378
28379 Ext.define('Ext.container.Container', {
28380     extend: 'Ext.container.AbstractContainer',
28381     alias: 'widget.container',
28382     alternateClassName: 'Ext.Container',
28383
28384     
28385     getChildByElement: function(el) {
28386         var item,
28387             itemEl,
28388             i = 0,
28389             it = this.items.items,
28390             ln = it.length;
28391
28392         el = Ext.getDom(el);
28393         for (; i < ln; i++) {
28394             item = it[i];
28395             itemEl = item.getEl();
28396             if ((itemEl.dom === el) || itemEl.contains(el)) {
28397                 return item;
28398             }
28399         }
28400         return null;
28401     }
28402 });
28403
28404
28405 Ext.define('Ext.toolbar.Fill', {
28406     extend: 'Ext.Component',
28407     alias: 'widget.tbfill',
28408     alternateClassName: 'Ext.Toolbar.Fill',
28409     isFill : true,
28410     flex: 1
28411 });
28412
28413 Ext.define('Ext.toolbar.Item', {
28414     extend: 'Ext.Component',
28415     alias: 'widget.tbitem',
28416     alternateClassName: 'Ext.Toolbar.Item',
28417     enable:Ext.emptyFn,
28418     disable:Ext.emptyFn,
28419     focus:Ext.emptyFn
28420     
28421 });
28422
28423 Ext.define('Ext.toolbar.Separator', {
28424     extend: 'Ext.toolbar.Item',
28425     alias: 'widget.tbseparator',
28426     alternateClassName: 'Ext.Toolbar.Separator',
28427     baseCls: Ext.baseCSSPrefix + 'toolbar-separator',
28428     focusable: false
28429 });
28430
28431 Ext.define('Ext.menu.Manager', {
28432     singleton: true,
28433     requires: [
28434         'Ext.util.MixedCollection',
28435         'Ext.util.KeyMap'
28436     ],
28437     alternateClassName: 'Ext.menu.MenuMgr',
28438
28439     uses: ['Ext.menu.Menu'],
28440
28441     menus: {},
28442     groups: {},
28443     attached: false,
28444     lastShow: new Date(),
28445
28446     init: function() {
28447         var me = this;
28448         
28449         me.active = Ext.create('Ext.util.MixedCollection');
28450         Ext.getDoc().addKeyListener(27, function() {
28451             if (me.active.length > 0) {
28452                 me.hideAll();
28453             }
28454         }, me);
28455     },
28456
28457     
28458     hideAll: function() {
28459         var active = this.active,
28460             c;
28461         if (active && active.length > 0) {
28462             c = active.clone();
28463             c.each(function(m) {
28464                 m.hide();
28465             });
28466             return true;
28467         }
28468         return false;
28469     },
28470
28471     onHide: function(m) {
28472         var me = this,
28473             active = me.active;
28474         active.remove(m);
28475         if (active.length < 1) {
28476             Ext.getDoc().un('mousedown', me.onMouseDown, me);
28477             me.attached = false;
28478         }
28479     },
28480
28481     onShow: function(m) {
28482         var me = this,
28483             active   = me.active,
28484             last     = active.last(),
28485             attached = me.attached,
28486             menuEl   = m.getEl(),
28487             zIndex;
28488
28489         me.lastShow = new Date();
28490         active.add(m);
28491         if (!attached) {
28492             Ext.getDoc().on('mousedown', me.onMouseDown, me);
28493             me.attached = true;
28494         }
28495         m.toFront();
28496     },
28497
28498     onBeforeHide: function(m) {
28499         if (m.activeChild) {
28500             m.activeChild.hide();
28501         }
28502         if (m.autoHideTimer) {
28503             clearTimeout(m.autoHideTimer);
28504             delete m.autoHideTimer;
28505         }
28506     },
28507
28508     onBeforeShow: function(m) {
28509         var active = this.active,
28510             parentMenu = m.parentMenu;
28511             
28512         active.remove(m);
28513         if (!parentMenu && !m.allowOtherMenus) {
28514             this.hideAll();
28515         }
28516         else if (parentMenu && parentMenu.activeChild && m != parentMenu.activeChild) {
28517             parentMenu.activeChild.hide();
28518         }
28519     },
28520
28521     
28522     onMouseDown: function(e) {
28523         var me = this,
28524             active = me.active,
28525             lastShow = me.lastShow;
28526
28527         if (Ext.Date.getElapsed(lastShow) > 50 && active.length > 0 && !e.getTarget('.' + Ext.baseCSSPrefix + 'menu')) {
28528             me.hideAll();
28529         }
28530     },
28531
28532     
28533     register: function(menu) {
28534         var me = this;
28535
28536         if (!me.active) {
28537             me.init();
28538         }
28539
28540         if (menu.floating) {
28541             me.menus[menu.id] = menu;
28542             menu.on({
28543                 beforehide: me.onBeforeHide,
28544                 hide: me.onHide,
28545                 beforeshow: me.onBeforeShow,
28546                 show: me.onShow,
28547                 scope: me
28548             });
28549         }
28550     },
28551
28552     
28553     get: function(menu) {
28554         var menus = this.menus;
28555         
28556         if (typeof menu == 'string') { 
28557             if (!menus) {  
28558                 return null;
28559             }
28560             return menus[menu];
28561         } else if (menu.isMenu) {  
28562             return menu;
28563         } else if (Ext.isArray(menu)) { 
28564             return Ext.create('Ext.menu.Menu', {items:menu});
28565         } else { 
28566             return Ext.ComponentManager.create(menu, 'menu');
28567         }
28568     },
28569
28570     
28571     unregister: function(menu) {
28572         var me = this,
28573             menus = me.menus,
28574             active = me.active;
28575
28576         delete menus[menu.id];
28577         active.remove(menu);
28578         menu.un({
28579             beforehide: me.onBeforeHide,
28580             hide: me.onHide,
28581             beforeshow: me.onBeforeShow,
28582             show: me.onShow,
28583             scope: me
28584         });
28585     },
28586
28587     
28588     registerCheckable: function(menuItem) {
28589         var groups  = this.groups,
28590             groupId = menuItem.group;
28591
28592         if (groupId) {
28593             if (!groups[groupId]) {
28594                 groups[groupId] = [];
28595             }
28596
28597             groups[groupId].push(menuItem);
28598         }
28599     },
28600
28601     
28602     unregisterCheckable: function(menuItem) {
28603         var groups  = this.groups,
28604             groupId = menuItem.group;
28605
28606         if (groupId) {
28607             Ext.Array.remove(groups[groupId], menuItem);
28608         }
28609     },
28610
28611     onCheckChange: function(menuItem, state) {
28612         var groups  = this.groups,
28613             groupId = menuItem.group,
28614             i       = 0,
28615             group, ln, curr;
28616
28617         if (groupId && state) {
28618             group = groups[groupId];
28619             ln = group.length;
28620             for (; i < ln; i++) {
28621                 curr = group[i];
28622                 if (curr != menuItem) {
28623                     curr.setChecked(false);
28624                 }
28625             }
28626         }
28627     }
28628 });
28629
28630 Ext.define('Ext.button.Button', {
28631
28632     
28633     alias: 'widget.button',
28634     extend: 'Ext.Component',
28635
28636     requires: [
28637         'Ext.menu.Manager',
28638         'Ext.util.ClickRepeater',
28639         'Ext.layout.component.Button',
28640         'Ext.util.TextMetrics',
28641         'Ext.util.KeyMap'
28642     ],
28643
28644     alternateClassName: 'Ext.Button',
28645     
28646
28647     isButton: true,
28648     componentLayout: 'button',
28649
28650     
28651     hidden: false,
28652
28653     
28654     disabled: false,
28655
28656     
28657     pressed: false,
28658
28659     
28660
28661     
28662
28663     
28664
28665     
28666
28667     
28668
28669     
28670
28671     
28672
28673     
28674
28675     
28676
28677     
28678
28679     
28680
28681     
28682
28683     
28684     enableToggle: false,
28685
28686     
28687
28688     
28689
28690     
28691     menuAlign: 'tl-bl?',
28692
28693     
28694
28695     
28696
28697     
28698     type: 'button',
28699
28700     
28701     clickEvent: 'click',
28702     
28703     
28704     preventDefault: true,
28705
28706     
28707     handleMouseEvents: true,
28708
28709     
28710     tooltipType: 'qtip',
28711
28712     
28713     baseCls: Ext.baseCSSPrefix + 'btn',
28714
28715     
28716     pressedCls: 'pressed',
28717     
28718     
28719     overCls: 'over',
28720     
28721     
28722     focusCls: 'focus',
28723     
28724     
28725     menuActiveCls: 'menu-active',
28726     
28727     
28728     
28729     
28730
28731     ariaRole: 'button',
28732
28733     
28734     renderTpl:
28735         '<em class="{splitCls}">' +
28736             '<tpl if="href">' +
28737                 '<a href="{href}" target="{target}"<tpl if="tabIndex"> tabIndex="{tabIndex}"</tpl> role="link">' +
28738                     '<span class="{baseCls}-inner">{text}</span>' +
28739                 '</a>' +
28740             '</tpl>' +
28741             '<tpl if="!href">' +
28742                 '<button type="{type}" hidefocus="true"' +
28743                     
28744                     
28745                     '<tpl if="tabIndex"> tabIndex="{tabIndex}"</tpl> role="button" autocomplete="off">' +
28746                     '<span class="{baseCls}-inner" style="{innerSpanStyle}">{text}</span>' +
28747                 '</button>' +
28748             '</tpl>' +
28749         '</em>' ,
28750
28751     
28752     scale: 'small',
28753     
28754     
28755     allowedScales: ['small', 'medium', 'large'],
28756     
28757     
28758
28759     
28760     iconAlign: 'left',
28761
28762     
28763     arrowAlign: 'right',
28764
28765     
28766     arrowCls: 'arrow',
28767
28768     
28769
28770     
28771
28772     
28773
28774     
28775      
28776     maskOnDisable: false,
28777
28778     
28779     initComponent: function() {
28780         var me = this;
28781         me.callParent(arguments);
28782
28783         me.addEvents(
28784             
28785             'click',
28786
28787             
28788             'toggle',
28789
28790             
28791             'mouseover',
28792
28793             
28794             'mouseout',
28795
28796             
28797             'menushow',
28798
28799             
28800             'menuhide',
28801
28802             
28803             'menutriggerover',
28804
28805             
28806             'menutriggerout'
28807         );
28808
28809         if (me.menu) {
28810             
28811             me.split = true;
28812
28813             
28814             me.menu = Ext.menu.Manager.get(me.menu);
28815             me.menu.ownerCt = me;
28816         }
28817
28818         
28819         if (me.url) {
28820             me.href = me.url;
28821         }
28822
28823         
28824         if (me.href && !me.hasOwnProperty('preventDefault')) {
28825             me.preventDefault = false;
28826         }
28827
28828         if (Ext.isString(me.toggleGroup)) {
28829             me.enableToggle = true;
28830         }
28831
28832     },
28833
28834     
28835     initAria: function() {
28836         this.callParent();
28837         var actionEl = this.getActionEl();
28838         if (this.menu) {
28839             actionEl.dom.setAttribute('aria-haspopup', true);
28840         }
28841     },
28842
28843     
28844     getActionEl: function() {
28845         return this.btnEl;
28846     },
28847
28848     
28849     getFocusEl: function() {
28850         return this.btnEl;
28851     },
28852
28853     
28854     setButtonCls: function() {
28855         var me = this,
28856             el = me.el,
28857             cls = [];
28858
28859         if (me.useSetClass) {
28860             if (!Ext.isEmpty(me.oldCls)) {
28861                 me.removeClsWithUI(me.oldCls);
28862                 me.removeClsWithUI(me.pressedCls);
28863             }
28864             
28865             
28866             if (me.iconCls || me.icon) {
28867                 if (me.text) {
28868                     cls.push('icon-text-' + me.iconAlign);
28869                 } else {
28870                     cls.push('icon');
28871                 }
28872             } else if (me.text) {
28873                 cls.push('noicon');
28874             }
28875             
28876             me.oldCls = cls;
28877             me.addClsWithUI(cls);
28878             me.addClsWithUI(me.pressed ? me.pressedCls : null);
28879         }
28880     },
28881     
28882     
28883     onRender: function(ct, position) {
28884         
28885         var me = this,
28886             repeater, btn;
28887             
28888         
28889         Ext.applyIf(me.renderData, me.getTemplateArgs());
28890
28891         
28892         Ext.applyIf(me.renderSelectors, {
28893             btnEl  : me.href ? 'a' : 'button',
28894             btnWrap: 'em',
28895             btnInnerEl: '.' + me.baseCls + '-inner'
28896         });
28897         
28898         if (me.scale) {
28899             me.ui = me.ui + '-' + me.scale;
28900         }
28901
28902         
28903         me.callParent(arguments);
28904
28905         
28906         if (me.split && me.arrowTooltip) {
28907             me.arrowEl.dom[me.tooltipType] = me.arrowTooltip;
28908         }
28909
28910         
28911         me.mon(me.btnEl, {
28912             scope: me,
28913             focus: me.onFocus,
28914             blur : me.onBlur
28915         });
28916
28917         
28918         btn = me.el;
28919
28920         if (me.icon) {
28921             me.setIcon(me.icon);
28922         }
28923
28924         if (me.iconCls) {
28925             me.setIconCls(me.iconCls);
28926         }
28927
28928         if (me.tooltip) {
28929             me.setTooltip(me.tooltip, true);
28930         }
28931
28932         
28933         if (me.handleMouseEvents) {
28934             me.mon(btn, {
28935                 scope: me,
28936                 mouseover: me.onMouseOver,
28937                 mouseout: me.onMouseOut,
28938                 mousedown: me.onMouseDown
28939             });
28940
28941             if (me.split) {
28942                 me.mon(btn, {
28943                     mousemove: me.onMouseMove,
28944                     scope: me
28945                 });
28946             }
28947         }
28948
28949         
28950         if (me.menu) {
28951             me.mon(me.menu, {
28952                 scope: me,
28953                 show: me.onMenuShow,
28954                 hide: me.onMenuHide
28955             });
28956
28957             me.keyMap = Ext.create('Ext.util.KeyMap', me.el, {
28958                 key: Ext.EventObject.DOWN,
28959                 handler: me.onDownKey,
28960                 scope: me
28961             });
28962         }
28963
28964         
28965         if (me.repeat) {
28966             repeater = Ext.create('Ext.util.ClickRepeater', btn, Ext.isObject(me.repeat) ? me.repeat: {});
28967             me.mon(repeater, 'click', me.onRepeatClick, me);
28968         } else {
28969             me.mon(btn, me.clickEvent, me.onClick, me);
28970         }
28971
28972         
28973         Ext.ButtonToggleManager.register(me);
28974     },
28975
28976     
28977     getTemplateArgs: function() {
28978         var me = this,
28979             persistentPadding = me.getPersistentBtnPadding(),
28980             innerSpanStyle = '';
28981
28982         
28983         if (Math.max.apply(Math, persistentPadding) > 0) {
28984             innerSpanStyle = 'margin:' + Ext.Array.map(persistentPadding, function(pad) {
28985                 return -pad + 'px';
28986             }).join(' ');
28987         }
28988
28989         return {
28990             href     : me.getHref(),
28991             target   : me.target || '_blank',
28992             type     : me.type,
28993             splitCls : me.getSplitCls(),
28994             cls      : me.cls,
28995             text     : me.text || '&#160;',
28996             tabIndex : me.tabIndex,
28997             innerSpanStyle: innerSpanStyle
28998         };
28999     },
29000
29001     
29002     getHref: function() {
29003         var me = this,
29004             params = Ext.apply({}, me.baseParams);
29005             
29006         
29007         params = Ext.apply(params, me.params);
29008         return me.href ? Ext.urlAppend(me.href, Ext.Object.toQueryString(params)) : false;
29009     },
29010
29011     
29012     setParams: function(params) {
29013         this.params = params;
29014         this.btnEl.dom.href = this.getHref();
29015     },
29016
29017     getSplitCls: function() {
29018         var me = this;
29019         return me.split ? (me.baseCls + '-' + me.arrowCls) + ' ' + (me.baseCls + '-' + me.arrowCls + '-' + me.arrowAlign) : '';
29020     },
29021
29022     
29023     afterRender: function() {
29024         var me = this;
29025         me.useSetClass = true;
29026         me.setButtonCls();
29027         me.doc = Ext.getDoc();
29028         this.callParent(arguments);
29029     },
29030
29031     
29032     setIconCls: function(cls) {
29033         var me = this,
29034             btnInnerEl = me.btnInnerEl;
29035         if (btnInnerEl) {
29036             
29037             btnInnerEl.removeCls(me.iconCls);
29038             btnInnerEl.addCls(cls || '');
29039             me.setButtonCls();
29040         }
29041         me.iconCls = cls;
29042         return me;
29043     },
29044
29045     
29046     setTooltip: function(tooltip, initial) {
29047         var me = this;
29048
29049         if (me.rendered) {
29050             if (!initial) {
29051                 me.clearTip();
29052             }
29053             if (Ext.isObject(tooltip)) {
29054                 Ext.tip.QuickTipManager.register(Ext.apply({
29055                     target: me.btnEl.id
29056                 },
29057                 tooltip));
29058                 me.tooltip = tooltip;
29059             } else {
29060                 me.btnEl.dom.setAttribute('data-' + this.tooltipType, tooltip);
29061             }
29062         } else {
29063             me.tooltip = tooltip;
29064         }
29065         return me;
29066     },
29067
29068     
29069     getRefItems: function(deep){
29070         var menu = this.menu,
29071             items;
29072
29073         if (menu) {
29074             items = menu.getRefItems(deep);
29075             items.unshift(menu);
29076         }
29077         return items || [];
29078     },
29079
29080     
29081     clearTip: function() {
29082         if (Ext.isObject(this.tooltip)) {
29083             Ext.tip.QuickTipManager.unregister(this.btnEl);
29084         }
29085     },
29086
29087     
29088     beforeDestroy: function() {
29089         var me = this;
29090         if (me.rendered) {
29091             me.clearTip();
29092         }
29093         if (me.menu && me.destroyMenu !== false) {
29094             Ext.destroy(me.btnEl, me.btnInnerEl, me.menu);
29095         }
29096         Ext.destroy(me.repeater);
29097     },
29098
29099     
29100     onDestroy: function() {
29101         var me = this;
29102         if (me.rendered) {
29103             me.doc.un('mouseover', me.monitorMouseOver, me);
29104             me.doc.un('mouseup', me.onMouseUp, me);
29105             delete me.doc;
29106             delete me.btnEl;
29107             delete me.btnInnerEl;
29108             Ext.ButtonToggleManager.unregister(me);
29109             
29110             Ext.destroy(me.keyMap);
29111             delete me.keyMap;
29112         }
29113         me.callParent();
29114     },
29115
29116     
29117     setHandler: function(handler, scope) {
29118         this.handler = handler;
29119         this.scope = scope;
29120         return this;
29121     },
29122
29123     
29124     setText: function(text) {
29125         var me = this;
29126         me.text = text;
29127         if (me.el) {
29128             me.btnInnerEl.update(text || '&#160;');
29129             me.setButtonCls();
29130         }
29131         me.doComponentLayout();
29132         return me;
29133     },
29134
29135     
29136     setIcon: function(icon) {
29137         var me = this,
29138             btnInnerEl = me.btnInnerEl;
29139         me.icon = icon;
29140         if (btnInnerEl) {
29141             btnInnerEl.setStyle('background-image', icon ? 'url(' + icon + ')': '');
29142             me.setButtonCls();
29143         }
29144         return me;
29145     },
29146
29147     
29148     getText: function() {
29149         return this.text;
29150     },
29151
29152     
29153     toggle: function(state, suppressEvent) {
29154         var me = this;
29155         state = state === undefined ? !me.pressed: !!state;
29156         if (state !== me.pressed) {
29157             if (me.rendered) {
29158                 me[state ? 'addClsWithUI': 'removeClsWithUI'](me.pressedCls);
29159             }
29160             me.btnEl.dom.setAttribute('aria-pressed', state);
29161             me.pressed = state;
29162             if (!suppressEvent) {
29163                 me.fireEvent('toggle', me, state);
29164                 Ext.callback(me.toggleHandler, me.scope || me, [me, state]);
29165             }
29166         }
29167         return me;
29168     },
29169
29170     
29171     showMenu: function() {
29172         var me = this;
29173         if (me.rendered && me.menu) {
29174             if (me.tooltip) {
29175                 Ext.tip.QuickTipManager.getQuickTip().cancelShow(me.btnEl);
29176             }
29177             if (me.menu.isVisible()) {
29178                 me.menu.hide();
29179             }
29180
29181             me.menu.showBy(me.el, me.menuAlign);
29182         }
29183         return me;
29184     },
29185
29186     
29187     hideMenu: function() {
29188         if (this.hasVisibleMenu()) {
29189             this.menu.hide();
29190         }
29191         return this;
29192     },
29193
29194     
29195     hasVisibleMenu: function() {
29196         var menu = this.menu;
29197         return menu && menu.rendered && menu.isVisible();
29198     },
29199
29200     
29201     onRepeatClick: function(repeat, e) {
29202         this.onClick(e);
29203     },
29204
29205     
29206     onClick: function(e) {
29207         var me = this;
29208         if (me.preventDefault || (me.disabled && me.getHref()) && e) {
29209             e.preventDefault();
29210         }
29211         if (e.button !== 0) {
29212             return;
29213         }
29214         if (!me.disabled) {
29215             if (me.enableToggle && (me.allowDepress !== false || !me.pressed)) {
29216                 me.toggle();
29217             }
29218             if (me.menu && !me.hasVisibleMenu() && !me.ignoreNextClick) {
29219                 me.showMenu();
29220             }
29221             me.fireEvent('click', me, e);
29222             if (me.handler) {
29223                 me.handler.call(me.scope || me, me, e);
29224             }
29225             me.onBlur();
29226         }
29227     },
29228
29229     
29230     onMouseOver: function(e) {
29231         var me = this;
29232         if (!me.disabled && !e.within(me.el, true, true)) {
29233             me.onMouseEnter(e);
29234         }
29235     },
29236
29237     
29238     onMouseOut: function(e) {
29239         var me = this;
29240         if (!e.within(me.el, true, true)) {
29241             if (me.overMenuTrigger) {
29242                 me.onMenuTriggerOut(e);
29243             }
29244             me.onMouseLeave(e);
29245         }
29246     },
29247
29248     
29249     onMouseMove: function(e) {
29250         var me = this,
29251             el = me.el,
29252             over = me.overMenuTrigger,
29253             overlap, btnSize;
29254
29255         if (me.split) {
29256             if (me.arrowAlign === 'right') {
29257                 overlap = e.getX() - el.getX();
29258                 btnSize = el.getWidth();
29259             } else {
29260                 overlap = e.getY() - el.getY();
29261                 btnSize = el.getHeight();
29262             }
29263
29264             if (overlap > (btnSize - me.getTriggerSize())) {
29265                 if (!over) {
29266                     me.onMenuTriggerOver(e);
29267                 }
29268             } else {
29269                 if (over) {
29270                     me.onMenuTriggerOut(e);
29271                 }
29272             }
29273         }
29274     },
29275
29276     
29277     getTriggerSize: function() {
29278         var me = this,
29279             size = me.triggerSize,
29280             side, sideFirstLetter, undef;
29281             
29282         if (size === undef) {
29283             side = me.arrowAlign;
29284             sideFirstLetter = side.charAt(0);
29285             size = me.triggerSize = me.el.getFrameWidth(sideFirstLetter) + me.btnWrap.getFrameWidth(sideFirstLetter) + (me.frameSize && me.frameSize[side] || 0);
29286         }
29287         return size;
29288     },
29289
29290     
29291     onMouseEnter: function(e) {
29292         var me = this;
29293         me.addClsWithUI(me.overCls);
29294         me.fireEvent('mouseover', me, e);
29295     },
29296
29297     
29298     onMouseLeave: function(e) {
29299         var me = this;
29300         me.removeClsWithUI(me.overCls);
29301         me.fireEvent('mouseout', me, e);
29302     },
29303
29304     
29305     onMenuTriggerOver: function(e) {
29306         var me = this;
29307         me.overMenuTrigger = true;
29308         me.fireEvent('menutriggerover', me, me.menu, e);
29309     },
29310
29311     
29312     onMenuTriggerOut: function(e) {
29313         var me = this;
29314         delete me.overMenuTrigger;
29315         me.fireEvent('menutriggerout', me, me.menu, e);
29316     },
29317     
29318     
29319     enable : function(silent) {
29320         var me = this;
29321
29322         me.callParent(arguments);
29323         
29324         me.removeClsWithUI('disabled');
29325
29326         return me;
29327     },
29328
29329     
29330     disable : function(silent) {
29331         var me = this;
29332         
29333         me.callParent(arguments);
29334         
29335         me.addClsWithUI('disabled');
29336
29337         return me;
29338     },
29339     
29340     
29341     setScale: function(scale) {
29342         var me = this,
29343             ui = me.ui.replace('-' + me.scale, '');
29344         
29345         
29346         if (!Ext.Array.contains(me.allowedScales, scale)) {
29347             throw('#setScale: scale must be an allowed scale (' + me.allowedScales.join(', ') + ')');
29348         }
29349         
29350         me.scale = scale;
29351         me.setUI(ui);
29352     },
29353     
29354     
29355     setUI: function(ui) {
29356         var me = this;
29357         
29358         
29359         if (me.scale && !ui.match(me.scale)) {
29360             ui = ui + '-' + me.scale;
29361         }
29362         
29363         me.callParent([ui]);
29364         
29365         
29366         
29367     },
29368     
29369     
29370     onFocus: function(e) {
29371         var me = this;
29372         if (!me.disabled) {
29373             me.addClsWithUI(me.focusCls);
29374         }
29375     },
29376
29377     
29378     onBlur: function(e) {
29379         var me = this;
29380         me.removeClsWithUI(me.focusCls);
29381     },
29382
29383     
29384     onMouseDown: function(e) {
29385         var me = this;
29386         if (!me.disabled && e.button === 0) {
29387             me.addClsWithUI(me.pressedCls);
29388             me.doc.on('mouseup', me.onMouseUp, me);
29389         }
29390     },
29391     
29392     onMouseUp: function(e) {
29393         var me = this;
29394         if (e.button === 0) {
29395             if (!me.pressed) {
29396                 me.removeClsWithUI(me.pressedCls);
29397             }
29398             me.doc.un('mouseup', me.onMouseUp, me);
29399         }
29400     },
29401     
29402     onMenuShow: function(e) {
29403         var me = this;
29404         me.ignoreNextClick = 0;
29405         me.addClsWithUI(me.menuActiveCls);
29406         me.fireEvent('menushow', me, me.menu);
29407     },
29408
29409     
29410     onMenuHide: function(e) {
29411         var me = this;
29412         me.removeClsWithUI(me.menuActiveCls);
29413         me.ignoreNextClick = Ext.defer(me.restoreClick, 250, me);
29414         me.fireEvent('menuhide', me, me.menu);
29415     },
29416
29417     
29418     restoreClick: function() {
29419         this.ignoreNextClick = 0;
29420     },
29421
29422     
29423     onDownKey: function() {
29424         var me = this;
29425
29426         if (!me.disabled) {
29427             if (me.menu) {
29428                 me.showMenu();
29429             }
29430         }
29431     },
29432
29433     
29434     getPersistentBtnPadding: function() {
29435         var cls = Ext.button.Button,
29436             padding = cls.persistentPadding,
29437             btn, leftTop, btnEl, btnInnerEl;
29438
29439         if (!padding) {
29440             padding = cls.persistentPadding = [0, 0, 0, 0]; 
29441
29442             if (!Ext.isIE) { 
29443                 
29444                 btn = Ext.create('Ext.button.Button', {
29445                     renderTo: Ext.getBody(),
29446                     text: 'test',
29447                     style: 'position:absolute;top:-999px;'
29448                 });
29449                 btnEl = btn.btnEl;
29450                 btnInnerEl = btn.btnInnerEl;
29451                 btnEl.setSize(null, null); 
29452
29453                 leftTop = btnInnerEl.getOffsetsTo(btnEl);
29454                 padding[0] = leftTop[1];
29455                 padding[1] = btnEl.getWidth() - btnInnerEl.getWidth() - leftTop[0];
29456                 padding[2] = btnEl.getHeight() - btnInnerEl.getHeight() - leftTop[1];
29457                 padding[3] = leftTop[0];
29458
29459                 btn.destroy();
29460             }
29461         }
29462
29463         return padding;
29464     }
29465
29466 }, function() {
29467     var groups = {},
29468         g, i, l;
29469
29470     function toggleGroup(btn, state) {
29471         if (state) {
29472             g = groups[btn.toggleGroup];
29473             for (i = 0, l = g.length; i < l; i++) {
29474                 if (g[i] !== btn) {
29475                     g[i].toggle(false);
29476                 }
29477             }
29478         }
29479     }
29480     
29481     Ext.ButtonToggleManager = {
29482         register: function(btn) {
29483             if (!btn.toggleGroup) {
29484                 return;
29485             }
29486             var group = groups[btn.toggleGroup];
29487             if (!group) {
29488                 group = groups[btn.toggleGroup] = [];
29489             }
29490             group.push(btn);
29491             btn.on('toggle', toggleGroup);
29492         },
29493
29494         unregister: function(btn) {
29495             if (!btn.toggleGroup) {
29496                 return;
29497             }
29498             var group = groups[btn.toggleGroup];
29499             if (group) {
29500                 Ext.Array.remove(group, btn);
29501                 btn.un('toggle', toggleGroup);
29502             }
29503         },
29504
29505         
29506         getPressed: function(group) {
29507             var g = groups[group],
29508                 i = 0,
29509                 len;
29510             if (g) {
29511                 for (len = g.length; i < len; i++) {
29512                     if (g[i].pressed === true) {
29513                         return g[i];
29514                     }
29515                 }
29516             }
29517             return null;
29518         }
29519     };
29520 });
29521
29522
29523 Ext.define('Ext.layout.container.boxOverflow.Menu', {
29524
29525     
29526
29527     extend: 'Ext.layout.container.boxOverflow.None',
29528     requires: ['Ext.toolbar.Separator', 'Ext.button.Button'],
29529     alternateClassName: 'Ext.layout.boxOverflow.Menu',
29530     
29531     
29532
29533     
29534
29535     
29536     noItemsMenuText : '<div class="' + Ext.baseCSSPrefix + 'toolbar-no-items">(None)</div>',
29537
29538     constructor: function(layout) {
29539         var me = this;
29540
29541         me.callParent(arguments);
29542
29543         
29544         layout.beforeLayout = Ext.Function.createInterceptor(layout.beforeLayout, this.clearOverflow, this);
29545
29546         me.afterCtCls = me.afterCtCls || Ext.baseCSSPrefix + 'box-menu-' + layout.parallelAfter;
29547         
29548         me.menuItems = [];
29549     },
29550     
29551     onRemove: function(comp){
29552         Ext.Array.remove(this.menuItems, comp);
29553     },
29554
29555     handleOverflow: function(calculations, targetSize) {
29556         var me = this,
29557             layout = me.layout,
29558             methodName = 'get' + layout.parallelPrefixCap,
29559             newSize = {},
29560             posArgs = [null, null];
29561
29562         me.callParent(arguments);
29563         this.createMenu(calculations, targetSize);
29564         newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
29565         newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - me.afterCt[methodName]();
29566
29567         
29568         
29569         posArgs[layout.perpendicularSizeIndex] = (calculations.meta.maxSize - me.menuTrigger['get' + layout.perpendicularPrefixCap]()) / 2;
29570         me.menuTrigger.setPosition.apply(me.menuTrigger, posArgs);
29571
29572         return { targetSize: newSize };
29573     },
29574
29575     
29576     clearOverflow: function(calculations, targetSize) {
29577         var me = this,
29578             newWidth = targetSize ? targetSize.width + (me.afterCt ? me.afterCt.getWidth() : 0) : 0,
29579             items = me.menuItems,
29580             i = 0,
29581             length = items.length,
29582             item;
29583
29584         me.hideTrigger();
29585         for (; i < length; i++) {
29586             items[i].show();
29587         }
29588         items.length = 0;
29589
29590         return targetSize ? {
29591             targetSize: {
29592                 height: targetSize.height,
29593                 width : newWidth
29594             }
29595         } : null;
29596     },
29597
29598     
29599     showTrigger: function() {
29600         this.menuTrigger.show();
29601     },
29602
29603     
29604     hideTrigger: function() {
29605         if (this.menuTrigger !== undefined) {
29606             this.menuTrigger.hide();
29607         }
29608     },
29609
29610     
29611     beforeMenuShow: function(menu) {
29612         var me = this,
29613             items = me.menuItems,
29614             i = 0,
29615             len   = items.length,
29616             item,
29617             prev;
29618
29619         var needsSep = function(group, prev){
29620             return group.isXType('buttongroup') && !(prev instanceof Ext.toolbar.Separator);
29621         };
29622
29623         me.clearMenu();
29624         menu.removeAll();
29625
29626         for (; i < len; i++) {
29627             item = items[i];
29628
29629             
29630             if (!i && (item instanceof Ext.toolbar.Separator)) {
29631                 continue;
29632             }
29633             if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
29634                 menu.add('-');
29635             }
29636
29637             me.addComponentToMenu(menu, item);
29638             prev = item;
29639         }
29640
29641         
29642         if (menu.items.length < 1) {
29643             menu.add(me.noItemsMenuText);
29644         }
29645     },
29646     
29647     
29648     createMenuConfig : function(component, hideOnClick) {
29649         var config = Ext.apply({}, component.initialConfig),
29650             group  = component.toggleGroup;
29651
29652         Ext.copyTo(config, component, [
29653             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
29654         ]);
29655
29656         Ext.apply(config, {
29657             text       : component.overflowText || component.text,
29658             hideOnClick: hideOnClick,
29659             destroyMenu: false
29660         });
29661
29662         if (group || component.enableToggle) {
29663             Ext.apply(config, {
29664                 group  : group,
29665                 checked: component.pressed,
29666                 listeners: {
29667                     checkchange: function(item, checked){
29668                         component.toggle(checked);
29669                     }
29670                 }
29671             });
29672         }
29673
29674         delete config.ownerCt;
29675         delete config.xtype;
29676         delete config.id;
29677         return config;
29678     },
29679
29680     
29681     addComponentToMenu : function(menu, component) {
29682         var me = this;
29683         if (component instanceof Ext.toolbar.Separator) {
29684             menu.add('-');
29685         } else if (component.isComponent) {
29686             if (component.isXType('splitbutton')) {
29687                 menu.add(me.createMenuConfig(component, true));
29688
29689             } else if (component.isXType('button')) {
29690                 menu.add(me.createMenuConfig(component, !component.menu));
29691
29692             } else if (component.isXType('buttongroup')) {
29693                 component.items.each(function(item){
29694                      me.addComponentToMenu(menu, item);
29695                 });
29696             } else {
29697                 menu.add(Ext.create(Ext.getClassName(component), me.createMenuConfig(component)));
29698             }
29699         }
29700     },
29701
29702     
29703     clearMenu : function() {
29704         var menu = this.moreMenu;
29705         if (menu && menu.items) {
29706             menu.items.each(function(item) {
29707                 if (item.menu) {
29708                     delete item.menu;
29709                 }
29710             });
29711         }
29712     },
29713
29714     
29715     createMenu: function(calculations, targetSize) {
29716         var me = this,
29717             layout = me.layout,
29718             startProp = layout.parallelBefore,
29719             sizeProp = layout.parallelPrefix,
29720             available = targetSize[sizeProp],
29721             boxes = calculations.boxes,
29722             i = 0,
29723             len = boxes.length,
29724             box;
29725
29726         if (!me.menuTrigger) {
29727             me.createInnerElements();
29728
29729             
29730             me.menu = Ext.create('Ext.menu.Menu', {
29731                 hideMode: 'offsets',
29732                 listeners: {
29733                     scope: me,
29734                     beforeshow: me.beforeMenuShow
29735                 }
29736             });
29737
29738             
29739             me.menuTrigger = Ext.create('Ext.button.Button', {
29740                 ownerCt : me.layout.owner, 
29741                 iconCls : Ext.baseCSSPrefix + layout.owner.getXType() + '-more-icon',
29742                 ui      : layout.owner instanceof Ext.toolbar.Toolbar ? 'default-toolbar' : 'default',
29743                 menu    : me.menu,
29744                 getSplitCls: function() { return '';},
29745                 renderTo: me.afterCt
29746             });
29747         }
29748         me.showTrigger();
29749         available -= me.afterCt.getWidth();
29750
29751         
29752         
29753         me.menuItems.length = 0;
29754         for (; i < len; i++) {
29755             box = boxes[i];
29756             if (box[startProp] + box[sizeProp] > available) {
29757                 me.menuItems.push(box.component);
29758                 box.component.hide();
29759             }
29760         }
29761     },
29762
29763     
29764     createInnerElements: function() {
29765         var me = this,
29766             target = me.layout.getRenderTarget();
29767
29768         if (!this.afterCt) {
29769             target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
29770             this.afterCt  = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + this.afterCtCls}, 'before');
29771         }
29772     },
29773
29774     
29775     destroy: function() {
29776         Ext.destroy(this.menu, this.menuTrigger);
29777     }
29778 });
29779
29780
29781 Ext.define('Ext.util.Region', {
29782
29783     
29784
29785     requires: ['Ext.util.Offset'],
29786
29787     statics: {
29788         
29789         getRegion: function(el) {
29790             return Ext.fly(el).getPageBox(true);
29791         },
29792
29793         
29794         from: function(o) {
29795             return new this(o.top, o.right, o.bottom, o.left);
29796         }
29797     },
29798
29799     
29800
29801     
29802     constructor : function(t, r, b, l) {
29803         var me = this;
29804         me.y = me.top = me[1] = t;
29805         me.right = r;
29806         me.bottom = b;
29807         me.x = me.left = me[0] = l;
29808     },
29809
29810     
29811     contains : function(region) {
29812         var me = this;
29813         return (region.x >= me.x &&
29814                 region.right <= me.right &&
29815                 region.y >= me.y &&
29816                 region.bottom <= me.bottom);
29817
29818     },
29819
29820     
29821     intersect : function(region) {
29822         var me = this,
29823             t = Math.max(me.y, region.y),
29824             r = Math.min(me.right, region.right),
29825             b = Math.min(me.bottom, region.bottom),
29826             l = Math.max(me.x, region.x);
29827
29828         if (b > t && r > l) {
29829             return new this.self(t, r, b, l);
29830         }
29831         else {
29832             return false;
29833         }
29834     },
29835
29836     
29837     union : function(region) {
29838         var me = this,
29839             t = Math.min(me.y, region.y),
29840             r = Math.max(me.right, region.right),
29841             b = Math.max(me.bottom, region.bottom),
29842             l = Math.min(me.x, region.x);
29843
29844         return new this.self(t, r, b, l);
29845     },
29846
29847     
29848     constrainTo : function(r) {
29849         var me = this,
29850             constrain = Ext.Number.constrain;
29851         me.top = me.y = constrain(me.top, r.y, r.bottom);
29852         me.bottom = constrain(me.bottom, r.y, r.bottom);
29853         me.left = me.x = constrain(me.left, r.x, r.right);
29854         me.right = constrain(me.right, r.x, r.right);
29855         return me;
29856     },
29857
29858     
29859     adjust : function(t, r, b, l) {
29860         var me = this;
29861         me.top = me.y += t;
29862         me.left = me.x += l;
29863         me.right += r;
29864         me.bottom += b;
29865         return me;
29866     },
29867
29868     
29869     getOutOfBoundOffset: function(axis, p) {
29870         if (!Ext.isObject(axis)) {
29871             if (axis == 'x') {
29872                 return this.getOutOfBoundOffsetX(p);
29873             } else {
29874                 return this.getOutOfBoundOffsetY(p);
29875             }
29876         } else {
29877             p = axis;
29878             var d = Ext.create('Ext.util.Offset');
29879             d.x = this.getOutOfBoundOffsetX(p.x);
29880             d.y = this.getOutOfBoundOffsetY(p.y);
29881             return d;
29882         }
29883
29884     },
29885
29886     
29887     getOutOfBoundOffsetX: function(p) {
29888         if (p <= this.x) {
29889             return this.x - p;
29890         } else if (p >= this.right) {
29891             return this.right - p;
29892         }
29893
29894         return 0;
29895     },
29896
29897     
29898     getOutOfBoundOffsetY: function(p) {
29899         if (p <= this.y) {
29900             return this.y - p;
29901         } else if (p >= this.bottom) {
29902             return this.bottom - p;
29903         }
29904
29905         return 0;
29906     },
29907
29908     
29909     isOutOfBound: function(axis, p) {
29910         if (!Ext.isObject(axis)) {
29911             if (axis == 'x') {
29912                 return this.isOutOfBoundX(p);
29913             } else {
29914                 return this.isOutOfBoundY(p);
29915             }
29916         } else {
29917             p = axis;
29918             return (this.isOutOfBoundX(p.x) || this.isOutOfBoundY(p.y));
29919         }
29920     },
29921
29922     
29923     isOutOfBoundX: function(p) {
29924         return (p < this.x || p > this.right);
29925     },
29926
29927     
29928     isOutOfBoundY: function(p) {
29929         return (p < this.y || p > this.bottom);
29930     },
29931
29932     
29933     restrict: function(axis, p, factor) {
29934         if (Ext.isObject(axis)) {
29935             var newP;
29936
29937             factor = p;
29938             p = axis;
29939
29940             if (p.copy) {
29941                 newP = p.copy();
29942             }
29943             else {
29944                 newP = {
29945                     x: p.x,
29946                     y: p.y
29947                 };
29948             }
29949
29950             newP.x = this.restrictX(p.x, factor);
29951             newP.y = this.restrictY(p.y, factor);
29952             return newP;
29953         } else {
29954             if (axis == 'x') {
29955                 return this.restrictX(p, factor);
29956             } else {
29957                 return this.restrictY(p, factor);
29958             }
29959         }
29960     },
29961
29962     
29963     restrictX : function(p, factor) {
29964         if (!factor) {
29965             factor = 1;
29966         }
29967
29968         if (p <= this.x) {
29969             p -= (p - this.x) * factor;
29970         }
29971         else if (p >= this.right) {
29972             p -= (p - this.right) * factor;
29973         }
29974         return p;
29975     },
29976
29977     
29978     restrictY : function(p, factor) {
29979         if (!factor) {
29980             factor = 1;
29981         }
29982
29983         if (p <= this.y) {
29984             p -= (p - this.y) * factor;
29985         }
29986         else if (p >= this.bottom) {
29987             p -= (p - this.bottom) * factor;
29988         }
29989         return p;
29990     },
29991
29992     
29993     getSize: function() {
29994         return {
29995             width: this.right - this.x,
29996             height: this.bottom - this.y
29997         };
29998     },
29999
30000     
30001     copy: function() {
30002         return new this.self(this.y, this.right, this.bottom, this.x);
30003     },
30004
30005     
30006     copyFrom: function(p) {
30007         var me = this;
30008         me.top = me.y = me[1] = p.y;
30009         me.right = p.right;
30010         me.bottom = p.bottom;
30011         me.left = me.x = me[0] = p.x;
30012
30013         return this;
30014     },
30015
30016     
30017     toString: function() {
30018         return "Region[" + this.top + "," + this.right + "," + this.bottom + "," + this.left + "]";
30019     },
30020
30021
30022     
30023     translateBy: function(x, y) {
30024         if (arguments.length == 1) {
30025             y = x.y;
30026             x = x.x;
30027         }
30028         var me = this;
30029         me.top = me.y += y;
30030         me.right += x;
30031         me.bottom += y;
30032         me.left = me.x += x;
30033
30034         return me;
30035     },
30036
30037     
30038     round: function() {
30039         var me = this;
30040         me.top = me.y = Math.round(me.y);
30041         me.right = Math.round(me.right);
30042         me.bottom = Math.round(me.bottom);
30043         me.left = me.x = Math.round(me.x);
30044
30045         return me;
30046     },
30047
30048     
30049     equals: function(region) {
30050         return (this.top == region.top && this.right == region.right && this.bottom == region.bottom && this.left == region.left);
30051     }
30052 });
30053
30054
30055
30056
30057
30058 Ext.define('Ext.dd.DragDropManager', {
30059     singleton: true,
30060
30061     requires: ['Ext.util.Region'],
30062
30063     uses: ['Ext.tip.QuickTipManager'],
30064
30065     
30066     alternateClassName: ['Ext.dd.DragDropMgr', 'Ext.dd.DDM'],
30067     
30068     
30069     ids: {},
30070
30071     
30072     handleIds: {},
30073
30074     
30075     dragCurrent: null,
30076
30077     
30078     dragOvers: {},
30079
30080     
30081     deltaX: 0,
30082
30083     
30084     deltaY: 0,
30085
30086     
30087     preventDefault: true,
30088
30089     
30090     stopPropagation: true,
30091
30092     
30093     initialized: false,
30094
30095     
30096     locked: false,
30097
30098     
30099     init: function() {
30100         this.initialized = true;
30101     },
30102
30103     
30104     POINT: 0,
30105
30106     
30107     INTERSECT: 1,
30108
30109     
30110     mode: 0,
30111
30112     
30113     _execOnAll: function(sMethod, args) {
30114         for (var i in this.ids) {
30115             for (var j in this.ids[i]) {
30116                 var oDD = this.ids[i][j];
30117                 if (! this.isTypeOfDD(oDD)) {
30118                     continue;
30119                 }
30120                 oDD[sMethod].apply(oDD, args);
30121             }
30122         }
30123     },
30124
30125     
30126     _onLoad: function() {
30127
30128         this.init();
30129
30130         var Event = Ext.EventManager;
30131         Event.on(document, "mouseup",   this.handleMouseUp, this, true);
30132         Event.on(document, "mousemove", this.handleMouseMove, this, true);
30133         Event.on(window,   "unload",    this._onUnload, this, true);
30134         Event.on(window,   "resize",    this._onResize, this, true);
30135         
30136
30137     },
30138
30139     
30140     _onResize: function(e) {
30141         this._execOnAll("resetConstraints", []);
30142     },
30143
30144     
30145     lock: function() { this.locked = true; },
30146
30147     
30148     unlock: function() { this.locked = false; },
30149
30150     
30151     isLocked: function() { return this.locked; },
30152
30153     
30154     locationCache: {},
30155
30156     
30157     useCache: true,
30158
30159     
30160     clickPixelThresh: 3,
30161
30162     
30163     clickTimeThresh: 350,
30164
30165     
30166     dragThreshMet: false,
30167
30168     
30169     clickTimeout: null,
30170
30171     
30172     startX: 0,
30173
30174     
30175     startY: 0,
30176
30177     
30178     regDragDrop: function(oDD, sGroup) {
30179         if (!this.initialized) { this.init(); }
30180
30181         if (!this.ids[sGroup]) {
30182             this.ids[sGroup] = {};
30183         }
30184         this.ids[sGroup][oDD.id] = oDD;
30185     },
30186
30187     
30188     removeDDFromGroup: function(oDD, sGroup) {
30189         if (!this.ids[sGroup]) {
30190             this.ids[sGroup] = {};
30191         }
30192
30193         var obj = this.ids[sGroup];
30194         if (obj && obj[oDD.id]) {
30195             delete obj[oDD.id];
30196         }
30197     },
30198
30199     
30200     _remove: function(oDD) {
30201         for (var g in oDD.groups) {
30202             if (g && this.ids[g] && this.ids[g][oDD.id]) {
30203                 delete this.ids[g][oDD.id];
30204             }
30205         }
30206         delete this.handleIds[oDD.id];
30207     },
30208
30209     
30210     regHandle: function(sDDId, sHandleId) {
30211         if (!this.handleIds[sDDId]) {
30212             this.handleIds[sDDId] = {};
30213         }
30214         this.handleIds[sDDId][sHandleId] = sHandleId;
30215     },
30216
30217     
30218     isDragDrop: function(id) {
30219         return ( this.getDDById(id) ) ? true : false;
30220     },
30221
30222     
30223     getRelated: function(p_oDD, bTargetsOnly) {
30224         var oDDs = [];
30225         for (var i in p_oDD.groups) {
30226             for (var j in this.ids[i]) {
30227                 var dd = this.ids[i][j];
30228                 if (! this.isTypeOfDD(dd)) {
30229                     continue;
30230                 }
30231                 if (!bTargetsOnly || dd.isTarget) {
30232                     oDDs[oDDs.length] = dd;
30233                 }
30234             }
30235         }
30236
30237         return oDDs;
30238     },
30239
30240     
30241     isLegalTarget: function (oDD, oTargetDD) {
30242         var targets = this.getRelated(oDD, true);
30243         for (var i=0, len=targets.length;i<len;++i) {
30244             if (targets[i].id == oTargetDD.id) {
30245                 return true;
30246             }
30247         }
30248
30249         return false;
30250     },
30251
30252     
30253     isTypeOfDD: function (oDD) {
30254         return (oDD && oDD.__ygDragDrop);
30255     },
30256
30257     
30258     isHandle: function(sDDId, sHandleId) {
30259         return ( this.handleIds[sDDId] &&
30260                         this.handleIds[sDDId][sHandleId] );
30261     },
30262
30263     
30264     getDDById: function(id) {
30265         for (var i in this.ids) {
30266             if (this.ids[i][id]) {
30267                 return this.ids[i][id];
30268             }
30269         }
30270         return null;
30271     },
30272
30273     
30274     handleMouseDown: function(e, oDD) {
30275         if(Ext.tip.QuickTipManager){
30276             Ext.tip.QuickTipManager.ddDisable();
30277         }
30278         if(this.dragCurrent){
30279             
30280             
30281             this.handleMouseUp(e);
30282         }
30283         
30284         this.currentTarget = e.getTarget();
30285         this.dragCurrent = oDD;
30286
30287         var el = oDD.getEl();
30288
30289         
30290         this.startX = e.getPageX();
30291         this.startY = e.getPageY();
30292
30293         this.deltaX = this.startX - el.offsetLeft;
30294         this.deltaY = this.startY - el.offsetTop;
30295
30296         this.dragThreshMet = false;
30297
30298         this.clickTimeout = setTimeout(
30299                 function() {
30300                     var DDM = Ext.dd.DragDropManager;
30301                     DDM.startDrag(DDM.startX, DDM.startY);
30302                 },
30303                 this.clickTimeThresh );
30304     },
30305
30306     
30307     startDrag: function(x, y) {
30308         clearTimeout(this.clickTimeout);
30309         if (this.dragCurrent) {
30310             this.dragCurrent.b4StartDrag(x, y);
30311             this.dragCurrent.startDrag(x, y);
30312         }
30313         this.dragThreshMet = true;
30314     },
30315
30316     
30317     handleMouseUp: function(e) {
30318
30319         if(Ext.tip.QuickTipManager){
30320             Ext.tip.QuickTipManager.ddEnable();
30321         }
30322         if (! this.dragCurrent) {
30323             return;
30324         }
30325
30326         clearTimeout(this.clickTimeout);
30327
30328         if (this.dragThreshMet) {
30329             this.fireEvents(e, true);
30330         } else {
30331         }
30332
30333         this.stopDrag(e);
30334
30335         this.stopEvent(e);
30336     },
30337
30338     
30339     stopEvent: function(e){
30340         if(this.stopPropagation) {
30341             e.stopPropagation();
30342         }
30343
30344         if (this.preventDefault) {
30345             e.preventDefault();
30346         }
30347     },
30348
30349     
30350     stopDrag: function(e) {
30351         
30352         if (this.dragCurrent) {
30353             if (this.dragThreshMet) {
30354                 this.dragCurrent.b4EndDrag(e);
30355                 this.dragCurrent.endDrag(e);
30356             }
30357
30358             this.dragCurrent.onMouseUp(e);
30359         }
30360
30361         this.dragCurrent = null;
30362         this.dragOvers = {};
30363     },
30364
30365     
30366     handleMouseMove: function(e) {
30367         if (! this.dragCurrent) {
30368             return true;
30369         }
30370         
30371
30372         
30373         if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
30374             this.stopEvent(e);
30375             return this.handleMouseUp(e);
30376         }
30377
30378         if (!this.dragThreshMet) {
30379             var diffX = Math.abs(this.startX - e.getPageX());
30380             var diffY = Math.abs(this.startY - e.getPageY());
30381             if (diffX > this.clickPixelThresh ||
30382                         diffY > this.clickPixelThresh) {
30383                 this.startDrag(this.startX, this.startY);
30384             }
30385         }
30386
30387         if (this.dragThreshMet) {
30388             this.dragCurrent.b4Drag(e);
30389             this.dragCurrent.onDrag(e);
30390             if(!this.dragCurrent.moveOnly){
30391                 this.fireEvents(e, false);
30392             }
30393         }
30394
30395         this.stopEvent(e);
30396
30397         return true;
30398     },
30399
30400     
30401     fireEvents: function(e, isDrop) {
30402         var dc = this.dragCurrent;
30403
30404         
30405         
30406         if (!dc || dc.isLocked()) {
30407             return;
30408         }
30409
30410         var pt = e.getPoint();
30411
30412         
30413         var oldOvers = [];
30414
30415         var outEvts   = [];
30416         var overEvts  = [];
30417         var dropEvts  = [];
30418         var enterEvts = [];
30419
30420         
30421         
30422         for (var i in this.dragOvers) {
30423
30424             var ddo = this.dragOvers[i];
30425
30426             if (! this.isTypeOfDD(ddo)) {
30427                 continue;
30428             }
30429
30430             if (! this.isOverTarget(pt, ddo, this.mode)) {
30431                 outEvts.push( ddo );
30432             }
30433
30434             oldOvers[i] = true;
30435             delete this.dragOvers[i];
30436         }
30437
30438         for (var sGroup in dc.groups) {
30439
30440             if ("string" != typeof sGroup) {
30441                 continue;
30442             }
30443
30444             for (i in this.ids[sGroup]) {
30445                 var oDD = this.ids[sGroup][i];
30446                 if (! this.isTypeOfDD(oDD)) {
30447                     continue;
30448                 }
30449
30450                 if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
30451                     if (this.isOverTarget(pt, oDD, this.mode)) {
30452                         
30453                         if (isDrop) {
30454                             dropEvts.push( oDD );
30455                         
30456                         } else {
30457
30458                             
30459                             if (!oldOvers[oDD.id]) {
30460                                 enterEvts.push( oDD );
30461                             
30462                             } else {
30463                                 overEvts.push( oDD );
30464                             }
30465
30466                             this.dragOvers[oDD.id] = oDD;
30467                         }
30468                     }
30469                 }
30470             }
30471         }
30472
30473         if (this.mode) {
30474             if (outEvts.length) {
30475                 dc.b4DragOut(e, outEvts);
30476                 dc.onDragOut(e, outEvts);
30477             }
30478
30479             if (enterEvts.length) {
30480                 dc.onDragEnter(e, enterEvts);
30481             }
30482
30483             if (overEvts.length) {
30484                 dc.b4DragOver(e, overEvts);
30485                 dc.onDragOver(e, overEvts);
30486             }
30487
30488             if (dropEvts.length) {
30489                 dc.b4DragDrop(e, dropEvts);
30490                 dc.onDragDrop(e, dropEvts);
30491             }
30492
30493         } else {
30494             
30495             var len = 0;
30496             for (i=0, len=outEvts.length; i<len; ++i) {
30497                 dc.b4DragOut(e, outEvts[i].id);
30498                 dc.onDragOut(e, outEvts[i].id);
30499             }
30500
30501             
30502             for (i=0,len=enterEvts.length; i<len; ++i) {
30503                 
30504                 dc.onDragEnter(e, enterEvts[i].id);
30505             }
30506
30507             
30508             for (i=0,len=overEvts.length; i<len; ++i) {
30509                 dc.b4DragOver(e, overEvts[i].id);
30510                 dc.onDragOver(e, overEvts[i].id);
30511             }
30512
30513             
30514             for (i=0, len=dropEvts.length; i<len; ++i) {
30515                 dc.b4DragDrop(e, dropEvts[i].id);
30516                 dc.onDragDrop(e, dropEvts[i].id);
30517             }
30518
30519         }
30520
30521         
30522         if (isDrop && !dropEvts.length) {
30523             dc.onInvalidDrop(e);
30524         }
30525
30526     },
30527
30528     
30529     getBestMatch: function(dds) {
30530         var winner = null;
30531         
30532         
30533            
30534         
30535         
30536
30537         var len = dds.length;
30538
30539         if (len == 1) {
30540             winner = dds[0];
30541         } else {
30542             
30543             for (var i=0; i<len; ++i) {
30544                 var dd = dds[i];
30545                 
30546                 
30547                 
30548                 if (dd.cursorIsOver) {
30549                     winner = dd;
30550                     break;
30551                 
30552                 } else {
30553                     if (!winner ||
30554                         winner.overlap.getArea() < dd.overlap.getArea()) {
30555                         winner = dd;
30556                     }
30557                 }
30558             }
30559         }
30560
30561         return winner;
30562     },
30563
30564     
30565     refreshCache: function(groups) {
30566         for (var sGroup in groups) {
30567             if ("string" != typeof sGroup) {
30568                 continue;
30569             }
30570             for (var i in this.ids[sGroup]) {
30571                 var oDD = this.ids[sGroup][i];
30572
30573                 if (this.isTypeOfDD(oDD)) {
30574                 
30575                     var loc = this.getLocation(oDD);
30576                     if (loc) {
30577                         this.locationCache[oDD.id] = loc;
30578                     } else {
30579                         delete this.locationCache[oDD.id];
30580                         
30581                         
30582                         
30583                     }
30584                 }
30585             }
30586         }
30587     },
30588
30589     
30590     verifyEl: function(el) {
30591         if (el) {
30592             var parent;
30593             if(Ext.isIE){
30594                 try{
30595                     parent = el.offsetParent;
30596                 }catch(e){}
30597             }else{
30598                 parent = el.offsetParent;
30599             }
30600             if (parent) {
30601                 return true;
30602             }
30603         }
30604
30605         return false;
30606     },
30607
30608     
30609     getLocation: function(oDD) {
30610         if (! this.isTypeOfDD(oDD)) {
30611             return null;
30612         }
30613
30614         
30615         
30616         if (oDD.getRegion) {
30617             return oDD.getRegion();
30618         }
30619
30620         var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
30621
30622         try {
30623             pos= Ext.core.Element.getXY(el);
30624         } catch (e) { }
30625
30626         if (!pos) {
30627             return null;
30628         }
30629
30630         x1 = pos[0];
30631         x2 = x1 + el.offsetWidth;
30632         y1 = pos[1];
30633         y2 = y1 + el.offsetHeight;
30634
30635         t = y1 - oDD.padding[0];
30636         r = x2 + oDD.padding[1];
30637         b = y2 + oDD.padding[2];
30638         l = x1 - oDD.padding[3];
30639
30640         return Ext.create('Ext.util.Region', t, r, b, l);
30641     },
30642
30643     
30644     isOverTarget: function(pt, oTarget, intersect) {
30645         
30646         var loc = this.locationCache[oTarget.id];
30647         if (!loc || !this.useCache) {
30648             loc = this.getLocation(oTarget);
30649             this.locationCache[oTarget.id] = loc;
30650
30651         }
30652
30653         if (!loc) {
30654             return false;
30655         }
30656
30657         oTarget.cursorIsOver = loc.contains( pt );
30658
30659         
30660         
30661         
30662         
30663         
30664         var dc = this.dragCurrent;
30665         if (!dc || !dc.getTargetCoord ||
30666                 (!intersect && !dc.constrainX && !dc.constrainY)) {
30667             return oTarget.cursorIsOver;
30668         }
30669
30670         oTarget.overlap = null;
30671
30672         
30673         
30674         
30675         
30676         var pos = dc.getTargetCoord(pt.x, pt.y);
30677
30678         var el = dc.getDragEl();
30679         var curRegion = Ext.create('Ext.util.Region', pos.y,
30680                                                pos.x + el.offsetWidth,
30681                                                pos.y + el.offsetHeight,
30682                                                pos.x );
30683
30684         var overlap = curRegion.intersect(loc);
30685
30686         if (overlap) {
30687             oTarget.overlap = overlap;
30688             return (intersect) ? true : oTarget.cursorIsOver;
30689         } else {
30690             return false;
30691         }
30692     },
30693
30694     
30695     _onUnload: function(e, me) {
30696         Ext.dd.DragDropManager.unregAll();
30697     },
30698
30699     
30700     unregAll: function() {
30701
30702         if (this.dragCurrent) {
30703             this.stopDrag();
30704             this.dragCurrent = null;
30705         }
30706
30707         this._execOnAll("unreg", []);
30708
30709         for (var i in this.elementCache) {
30710             delete this.elementCache[i];
30711         }
30712
30713         this.elementCache = {};
30714         this.ids = {};
30715     },
30716
30717     
30718     elementCache: {},
30719
30720     
30721     getElWrapper: function(id) {
30722         var oWrapper = this.elementCache[id];
30723         if (!oWrapper || !oWrapper.el) {
30724             oWrapper = this.elementCache[id] =
30725                 new this.ElementWrapper(Ext.getDom(id));
30726         }
30727         return oWrapper;
30728     },
30729
30730     
30731     getElement: function(id) {
30732         return Ext.getDom(id);
30733     },
30734
30735     
30736     getCss: function(id) {
30737         var el = Ext.getDom(id);
30738         return (el) ? el.style : null;
30739     },
30740
30741     
30742     ElementWrapper: function(el) {
30743             
30744             this.el = el || null;
30745             
30746             this.id = this.el && el.id;
30747             
30748             this.css = this.el && el.style;
30749         },
30750
30751     
30752     getPosX: function(el) {
30753         return Ext.core.Element.getX(el);
30754     },
30755
30756     
30757     getPosY: function(el) {
30758         return Ext.core.Element.getY(el);
30759     },
30760
30761     
30762     swapNode: function(n1, n2) {
30763         if (n1.swapNode) {
30764             n1.swapNode(n2);
30765         } else {
30766             var p = n2.parentNode;
30767             var s = n2.nextSibling;
30768
30769             if (s == n1) {
30770                 p.insertBefore(n1, n2);
30771             } else if (n2 == n1.nextSibling) {
30772                 p.insertBefore(n2, n1);
30773             } else {
30774                 n1.parentNode.replaceChild(n2, n1);
30775                 p.insertBefore(n1, s);
30776             }
30777         }
30778     },
30779
30780     
30781     getScroll: function () {
30782         var doc   = window.document,
30783             docEl = doc.documentElement,
30784             body  = doc.body,
30785             top   = 0,
30786             left  = 0;
30787             
30788         if (Ext.isGecko4) {
30789             top  = window.scrollYOffset;
30790             left = window.scrollXOffset;
30791         } else {
30792             if (docEl && (docEl.scrollTop || docEl.scrollLeft)) {
30793                 top  = docEl.scrollTop;
30794                 left = docEl.scrollLeft;
30795             } else if (body) {
30796                 top  = body.scrollTop;
30797                 left = body.scrollLeft;
30798             } 
30799         }
30800         return {
30801             top: top,
30802             left: left
30803         };
30804     },
30805
30806     
30807     getStyle: function(el, styleProp) {
30808         return Ext.fly(el).getStyle(styleProp);
30809     },
30810
30811     
30812     getScrollTop: function () {
30813         return this.getScroll().top;
30814     },
30815
30816     
30817     getScrollLeft: function () {
30818         return this.getScroll().left;
30819     },
30820
30821     
30822     moveToEl: function (moveEl, targetEl) {
30823         var aCoord = Ext.core.Element.getXY(targetEl);
30824         Ext.core.Element.setXY(moveEl, aCoord);
30825     },
30826
30827     
30828     numericSort: function(a, b) {
30829         return (a - b);
30830     },
30831
30832     
30833     _timeoutCount: 0,
30834
30835     
30836     _addListeners: function() {
30837         if ( document ) {
30838             this._onLoad();
30839         } else {
30840             if (this._timeoutCount > 2000) {
30841             } else {
30842                 setTimeout(this._addListeners, 10);
30843                 if (document && document.body) {
30844                     this._timeoutCount += 1;
30845                 }
30846             }
30847         }
30848     },
30849
30850     
30851     handleWasClicked: function(node, id) {
30852         if (this.isHandle(id, node.id)) {
30853             return true;
30854         } else {
30855             
30856             var p = node.parentNode;
30857
30858             while (p) {
30859                 if (this.isHandle(id, p.id)) {
30860                     return true;
30861                 } else {
30862                     p = p.parentNode;
30863                 }
30864             }
30865         }
30866
30867         return false;
30868     }
30869 }, function() {
30870     this._addListeners();
30871 });
30872
30873
30874
30875 Ext.define('Ext.layout.container.Box', {
30876
30877     
30878
30879     alias: ['layout.box'],
30880     extend: 'Ext.layout.container.Container',
30881     alternateClassName: 'Ext.layout.BoxLayout',
30882     
30883     requires: [
30884         'Ext.layout.container.boxOverflow.None',
30885         'Ext.layout.container.boxOverflow.Menu',
30886         'Ext.layout.container.boxOverflow.Scroller',
30887         'Ext.util.Format',
30888         'Ext.dd.DragDropManager'
30889     ],
30890
30891     
30892
30893     
30894
30895     
30896     defaultMargins: {
30897         top: 0,
30898         right: 0,
30899         bottom: 0,
30900         left: 0
30901     },
30902
30903     
30904     padding: '0',
30905     
30906     pack: 'start',
30907
30908     
30909     
30910
30911     type: 'box',
30912     scrollOffset: 0,
30913     itemCls: Ext.baseCSSPrefix + 'box-item',
30914     targetCls: Ext.baseCSSPrefix + 'box-layout-ct',
30915     innerCls: Ext.baseCSSPrefix + 'box-inner',
30916
30917     bindToOwnerCtContainer: true,
30918
30919     fixedLayout: false,
30920     
30921     
30922     
30923     availableSpaceOffset: 0,
30924     
30925     
30926     reserveOffset: true,
30927     
30928     
30929     clearInnerCtOnLayout: false,
30930
30931     flexSortFn: function (a, b) {
30932         var maxParallelPrefix = 'max' + this.parallelPrefixCap,
30933             infiniteValue = Infinity;
30934         a = a.component[maxParallelPrefix] || infiniteValue;
30935         b = b.component[maxParallelPrefix] || infiniteValue;
30936         
30937         if (!isFinite(a) && !isFinite(b)) {
30938             return false;
30939         }
30940         return a - b;
30941     },
30942
30943     
30944     minSizeSortFn: function(a, b) {
30945         return b.available - a.available;
30946     },
30947
30948     constructor: function(config) {
30949         var me = this;
30950
30951         me.callParent(arguments);
30952
30953         
30954         me.flexSortFn = Ext.Function.bind(me.flexSortFn, me);
30955
30956         me.initOverflowHandler();
30957     },
30958
30959     
30960     getChildBox: function(child) {
30961         child = child.el || this.owner.getComponent(child).el;
30962         return {
30963             left: child.getLeft(true),
30964             top: child.getTop(true),
30965             width: child.getWidth(),
30966             height: child.getHeight()
30967         };
30968     },
30969
30970     
30971     calculateChildBox: function(child) {
30972         var me = this,
30973             boxes = me.calculateChildBoxes(me.getVisibleItems(), me.getLayoutTargetSize()).boxes,
30974             ln = boxes.length,
30975             i = 0;
30976
30977         child = me.owner.getComponent(child);
30978         for (; i < ln; i++) {
30979             if (boxes[i].component === child) {
30980                 return boxes[i];
30981             }
30982         }
30983     },
30984
30985     
30986     calculateChildBoxes: function(visibleItems, targetSize) {
30987         var me = this,
30988             math = Math,
30989             mmax = math.max,
30990             infiniteValue = Infinity,
30991             undefinedValue,
30992
30993             parallelPrefix = me.parallelPrefix,
30994             parallelPrefixCap = me.parallelPrefixCap,
30995             perpendicularPrefix = me.perpendicularPrefix,
30996             perpendicularPrefixCap = me.perpendicularPrefixCap,
30997             parallelMinString = 'min' + parallelPrefixCap,
30998             perpendicularMinString = 'min' + perpendicularPrefixCap,
30999             perpendicularMaxString = 'max' + perpendicularPrefixCap,
31000
31001             parallelSize = targetSize[parallelPrefix] - me.scrollOffset,
31002             perpendicularSize = targetSize[perpendicularPrefix],
31003             padding = me.padding,
31004             parallelOffset = padding[me.parallelBefore],
31005             paddingParallel = parallelOffset + padding[me.parallelAfter],
31006             perpendicularOffset = padding[me.perpendicularLeftTop],
31007             paddingPerpendicular =  perpendicularOffset + padding[me.perpendicularRightBottom],
31008             availPerpendicularSize = mmax(0, perpendicularSize - paddingPerpendicular),
31009
31010             isStart = me.pack == 'start',
31011             isCenter = me.pack == 'center',
31012             isEnd = me.pack == 'end',
31013
31014             constrain = Ext.Number.constrain,
31015             visibleCount = visibleItems.length,
31016             nonFlexSize = 0,
31017             totalFlex = 0,
31018             desiredSize = 0,
31019             minimumSize = 0,
31020             maxSize = 0,
31021             boxes = [],
31022             minSizes = [],
31023             calculatedWidth,
31024
31025             i, child, childParallel, childPerpendicular, childMargins, childSize, minParallel, tmpObj, shortfall, 
31026             tooNarrow, availableSpace, minSize, item, length, itemIndex, box, oldSize, newSize, reduction, diff, 
31027             flexedBoxes, remainingSpace, remainingFlex, flexedSize, parallelMargins, calcs, offset, 
31028             perpendicularMargins, stretchSize;
31029
31030         
31031         for (i = 0; i < visibleCount; i++) {
31032             child = visibleItems[i];
31033             childPerpendicular = child[perpendicularPrefix];
31034             me.layoutItem(child);
31035             childMargins = child.margins;
31036             parallelMargins = childMargins[me.parallelBefore] + childMargins[me.parallelAfter];
31037
31038             
31039             tmpObj = {
31040                 component: child,
31041                 margins: childMargins
31042             };
31043
31044             
31045             if (child.flex) {
31046                 totalFlex += child.flex;
31047                 childParallel = undefinedValue;
31048             }
31049             
31050             else {
31051                 if (!(child[parallelPrefix] && childPerpendicular)) {
31052                     childSize = child.getSize();
31053                 }
31054                 childParallel = child[parallelPrefix] || childSize[parallelPrefix];
31055                 childPerpendicular = childPerpendicular || childSize[perpendicularPrefix];
31056             }
31057
31058             nonFlexSize += parallelMargins + (childParallel || 0);
31059             desiredSize += parallelMargins + (child.flex ? child[parallelMinString] || 0 : childParallel);
31060             minimumSize += parallelMargins + (child[parallelMinString] || childParallel || 0);
31061
31062             
31063             if (typeof childPerpendicular != 'number') {
31064                 
31065                 
31066                 childPerpendicular = child['get' + perpendicularPrefixCap]();
31067             }
31068
31069             
31070             maxSize = mmax(maxSize, childPerpendicular + childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom]);
31071
31072             tmpObj[parallelPrefix] = childParallel || undefinedValue;
31073             tmpObj[perpendicularPrefix] = childPerpendicular || undefinedValue;
31074             boxes.push(tmpObj);
31075         }
31076         shortfall = desiredSize - parallelSize;
31077         tooNarrow = minimumSize > parallelSize;
31078
31079         
31080         availableSpace = mmax(0, parallelSize - nonFlexSize - paddingParallel - (me.reserveOffset ? me.availableSpaceOffset : 0));
31081
31082         if (tooNarrow) {
31083             for (i = 0; i < visibleCount; i++) {
31084                 box = boxes[i];
31085                 minSize = visibleItems[i][parallelMinString] || visibleItems[i][parallelPrefix] || box[parallelPrefix];
31086                 box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
31087                 box[parallelPrefix] = minSize;
31088             }
31089         }
31090         else {
31091             
31092             
31093             if (shortfall > 0) {
31094                 
31095                 for (i = 0; i < visibleCount; i++) {
31096                     item = visibleItems[i];
31097                     minSize = item[parallelMinString] || 0;
31098
31099                     
31100                     
31101                     if (item.flex) {
31102                         box = boxes[i];
31103                         box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
31104                         box[parallelPrefix] = minSize;
31105                     }
31106                     else {
31107                         minSizes.push({
31108                             minSize: minSize,
31109                             available: boxes[i][parallelPrefix] - minSize,
31110                             index: i
31111                         });
31112                     }
31113                 }
31114
31115                 
31116                 Ext.Array.sort(minSizes, me.minSizeSortFn);
31117
31118                 
31119                 for (i = 0, length = minSizes.length; i < length; i++) {
31120                     itemIndex = minSizes[i].index;
31121
31122                     if (itemIndex == undefinedValue) {
31123                         continue;
31124                     }
31125                     item = visibleItems[itemIndex];
31126                     minSize = minSizes[i].minSize;
31127
31128                     box = boxes[itemIndex];
31129                     oldSize = box[parallelPrefix];
31130                     newSize = mmax(minSize, oldSize - math.ceil(shortfall / (length - i)));
31131                     reduction = oldSize - newSize;
31132
31133                     box.dirtySize = box.dirtySize || box[parallelPrefix] != newSize;
31134                     box[parallelPrefix] = newSize;
31135                     shortfall -= reduction;
31136                 }
31137             }
31138             else {
31139                 remainingSpace = availableSpace;
31140                 remainingFlex = totalFlex;
31141                 flexedBoxes = [];
31142
31143                 
31144                 for (i = 0; i < visibleCount; i++) {
31145                     child = visibleItems[i];
31146                     if (isStart && child.flex) {
31147                         flexedBoxes.push(boxes[Ext.Array.indexOf(visibleItems, child)]);
31148                     }
31149                 }
31150                 
31151                 
31152                 
31153                 Ext.Array.sort(flexedBoxes, me.flexSortFn);
31154
31155                 
31156                 for (i = 0; i < flexedBoxes.length; i++) {
31157                     calcs = flexedBoxes[i];
31158                     child = calcs.component;
31159                     childMargins = calcs.margins;
31160
31161                     flexedSize = math.ceil((child.flex / remainingFlex) * remainingSpace);
31162
31163                     
31164                     flexedSize = Math.max(child['min' + parallelPrefixCap] || 0, math.min(child['max' + parallelPrefixCap] || infiniteValue, flexedSize));
31165
31166                     
31167                     remainingSpace -= flexedSize;
31168                     remainingFlex -= child.flex;
31169
31170                     calcs.dirtySize = calcs.dirtySize || calcs[parallelPrefix] != flexedSize;
31171                     calcs[parallelPrefix] = flexedSize;
31172                 }
31173             }
31174         }
31175
31176         if (isCenter) {
31177             parallelOffset += availableSpace / 2;
31178         }
31179         else if (isEnd) {
31180             parallelOffset += availableSpace;
31181         }
31182
31183         
31184         
31185         
31186         
31187         if (me.owner.dock && (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) && !me.owner.width && me.direction == 'vertical') {
31188
31189             calculatedWidth = maxSize + me.owner.el.getPadding('lr') + me.owner.el.getBorderWidth('lr');
31190             if (me.owner.frameSize) {
31191                 calculatedWidth += me.owner.frameSize.left + me.owner.frameSize.right;
31192             }
31193             
31194             availPerpendicularSize = Math.min(availPerpendicularSize, targetSize.width = maxSize + padding.left + padding.right);
31195         }
31196
31197         
31198         for (i = 0; i < visibleCount; i++) {
31199             child = visibleItems[i];
31200             calcs = boxes[i];
31201
31202             childMargins = calcs.margins;
31203
31204             perpendicularMargins = childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom];
31205
31206             
31207             parallelOffset += childMargins[me.parallelBefore];
31208
31209             calcs[me.parallelBefore] = parallelOffset;
31210             calcs[me.perpendicularLeftTop] = perpendicularOffset + childMargins[me.perpendicularLeftTop];
31211
31212             if (me.align == 'stretch') {
31213                 stretchSize = constrain(availPerpendicularSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
31214                 calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
31215                 calcs[perpendicularPrefix] = stretchSize;
31216             }
31217             else if (me.align == 'stretchmax') {
31218                 stretchSize = constrain(maxSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
31219                 calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
31220                 calcs[perpendicularPrefix] = stretchSize;
31221             }
31222             else if (me.align == me.alignCenteringString) {
31223                 
31224                 
31225                 
31226                 diff = mmax(availPerpendicularSize, maxSize) - me.innerCt.getBorderWidth(me.perpendicularLT + me.perpendicularRB) - calcs[perpendicularPrefix];
31227                 if (diff > 0) {
31228                     calcs[me.perpendicularLeftTop] = perpendicularOffset + Math.round(diff / 2);
31229                 }
31230             }
31231
31232             
31233             parallelOffset += (calcs[parallelPrefix] || 0) + childMargins[me.parallelAfter];
31234         }
31235
31236         return {
31237             boxes: boxes,
31238             meta : {
31239                 calculatedWidth: calculatedWidth,
31240                 maxSize: maxSize,
31241                 nonFlexSize: nonFlexSize,
31242                 desiredSize: desiredSize,
31243                 minimumSize: minimumSize,
31244                 shortfall: shortfall,
31245                 tooNarrow: tooNarrow
31246             }
31247         };
31248     },
31249     
31250     onRemove: function(comp){
31251         this.callParent(arguments);
31252         if (this.overflowHandler) {
31253             this.overflowHandler.onRemove(comp);
31254         }
31255     },
31256
31257     
31258     initOverflowHandler: function() {
31259         var handler = this.overflowHandler;
31260
31261         if (typeof handler == 'string') {
31262             handler = {
31263                 type: handler
31264             };
31265         }
31266
31267         var handlerType = 'None';
31268         if (handler && handler.type !== undefined) {
31269             handlerType = handler.type;
31270         }
31271
31272         var constructor = Ext.layout.container.boxOverflow[handlerType];
31273         if (constructor[this.type]) {
31274             constructor = constructor[this.type];
31275         }
31276
31277         this.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.' + handlerType, this, handler);
31278     },
31279
31280     
31281     onLayout: function() {
31282         this.callParent();
31283         
31284         if (this.clearInnerCtOnLayout === true && this.adjustmentPass !== true) {
31285             this.innerCt.setSize(null, null);
31286         }
31287
31288         var me = this,
31289             targetSize = me.getLayoutTargetSize(),
31290             items = me.getVisibleItems(),
31291             calcs = me.calculateChildBoxes(items, targetSize),
31292             boxes = calcs.boxes,
31293             meta = calcs.meta,
31294             handler, method, results;
31295
31296         if (me.autoSize && calcs.meta.desiredSize) {
31297             targetSize[me.parallelPrefix] = calcs.meta.desiredSize;
31298         }
31299
31300         
31301         if (meta.shortfall > 0) {
31302             handler = me.overflowHandler;
31303             method = meta.tooNarrow ? 'handleOverflow': 'clearOverflow';
31304
31305             results = handler[method](calcs, targetSize);
31306
31307             if (results) {
31308                 if (results.targetSize) {
31309                     targetSize = results.targetSize;
31310                 }
31311
31312                 if (results.recalculate) {
31313                     items = me.getVisibleItems(owner);
31314                     calcs = me.calculateChildBoxes(items, targetSize);
31315                     boxes = calcs.boxes;
31316                 }
31317             }
31318         } else {
31319             me.overflowHandler.clearOverflow();
31320         }
31321
31322         
31323         me.layoutTargetLastSize = targetSize;
31324
31325         
31326         me.childBoxCache = calcs;
31327
31328         me.updateInnerCtSize(targetSize, calcs);
31329         me.updateChildBoxes(boxes);
31330         me.handleTargetOverflow(targetSize);
31331     },
31332
31333     
31334     updateChildBoxes: function(boxes) {
31335         var me = this,
31336             i = 0,
31337             length = boxes.length,
31338             animQueue = [],
31339             dd = Ext.dd.DDM.getDDById(me.innerCt.id), 
31340             oldBox, newBox, changed, comp, boxAnim, animCallback;
31341
31342         for (; i < length; i++) {
31343             newBox = boxes[i];
31344             comp = newBox.component;
31345
31346             
31347             
31348             if (dd && (dd.getDragEl() === comp.el.dom)) {
31349                 continue;
31350             }
31351
31352             changed = false;
31353
31354             oldBox = me.getChildBox(comp);
31355
31356             
31357             
31358             
31359             if (me.animate) {
31360                 
31361                 animCallback = me.animate.callback || me.animate;
31362                 boxAnim = {
31363                     layoutAnimation: true,  
31364                     target: comp,
31365                     from: {},
31366                     to: {},
31367                     listeners: {}
31368                 };
31369                 
31370                 
31371                 
31372                 
31373                 if (!isNaN(newBox.width) && (newBox.width != oldBox.width)) {
31374                     changed = true;
31375                     
31376                     boxAnim.to.width = newBox.width;
31377                 }
31378                 if (!isNaN(newBox.height) && (newBox.height != oldBox.height)) {
31379                     changed = true;
31380                     
31381                     boxAnim.to.height = newBox.height;
31382                 }
31383                 if (!isNaN(newBox.left) && (newBox.left != oldBox.left)) {
31384                     changed = true;
31385                     
31386                     boxAnim.to.left = newBox.left;
31387                 }
31388                 if (!isNaN(newBox.top) && (newBox.top != oldBox.top)) {
31389                     changed = true;
31390                     
31391                     boxAnim.to.top = newBox.top;
31392                 }
31393                 if (changed) {
31394                     animQueue.push(boxAnim);
31395                 }
31396             } else {
31397                 if (newBox.dirtySize) {
31398                     if (newBox.width !== oldBox.width || newBox.height !== oldBox.height) {
31399                         me.setItemSize(comp, newBox.width, newBox.height);
31400                     }
31401                 }
31402                 
31403                 if (isNaN(newBox.left) || isNaN(newBox.top)) {
31404                     continue;
31405                 }
31406                 comp.setPosition(newBox.left, newBox.top);
31407             }
31408         }
31409
31410         
31411         length = animQueue.length;
31412         if (length) {
31413
31414             
31415             
31416             var afterAnimate = function(anim) {
31417                 
31418                 length -= 1;
31419                 if (!length) {
31420                     me.layoutBusy = false;
31421                     if (Ext.isFunction(animCallback)) {
31422                         animCallback();
31423                     }
31424                 }
31425             };
31426
31427             var beforeAnimate = function() {
31428                 me.layoutBusy = true;
31429             };
31430
31431             
31432             for (i = 0, length = animQueue.length; i < length; i++) {
31433                 boxAnim = animQueue[i];
31434
31435                 
31436                 boxAnim.listeners.afteranimate = afterAnimate;
31437
31438                 
31439                 if (!i) {
31440                     boxAnim.listeners.beforeanimate = beforeAnimate;
31441                 }
31442                 if (me.animate.duration) {
31443                     boxAnim.duration = me.animate.duration;
31444                 }
31445                 comp = boxAnim.target;
31446                 delete boxAnim.target;
31447                 
31448                 comp.stopAnimation();
31449                 comp.animate(boxAnim);
31450             }
31451         }
31452     },
31453
31454     
31455     updateInnerCtSize: function(tSize, calcs) {
31456         var me = this,
31457             mmax = Math.max,
31458             align = me.align,
31459             padding = me.padding,
31460             width = tSize.width,
31461             height = tSize.height,
31462             meta = calcs.meta,
31463             innerCtWidth,
31464             innerCtHeight;
31465
31466         if (me.direction == 'horizontal') {
31467             innerCtWidth = width;
31468             innerCtHeight = meta.maxSize + padding.top + padding.bottom + me.innerCt.getBorderWidth('tb');
31469
31470             if (align == 'stretch') {
31471                 innerCtHeight = height;
31472             }
31473             else if (align == 'middle') {
31474                 innerCtHeight = mmax(height, innerCtHeight);
31475             }
31476         } else {
31477             innerCtHeight = height;
31478             innerCtWidth = meta.maxSize + padding.left + padding.right + me.innerCt.getBorderWidth('lr');
31479
31480             if (align == 'stretch') {
31481                 innerCtWidth = width;
31482             }
31483             else if (align == 'center') {
31484                 innerCtWidth = mmax(width, innerCtWidth);
31485             }
31486         }
31487         me.getRenderTarget().setSize(innerCtWidth || undefined, innerCtHeight || undefined);
31488
31489         
31490         
31491         if (meta.calculatedWidth && me.owner.el.getWidth() > meta.calculatedWidth) {
31492             me.owner.el.setWidth(meta.calculatedWidth);
31493         }
31494
31495         if (me.innerCt.dom.scrollTop) {
31496             me.innerCt.dom.scrollTop = 0;
31497         }
31498     },
31499
31500     
31501     handleTargetOverflow: function(previousTargetSize) {
31502         var target = this.getTarget(),
31503             overflow = target.getStyle('overflow'),
31504             newTargetSize;
31505
31506         if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
31507             newTargetSize = this.getLayoutTargetSize();
31508             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height) {
31509                 this.adjustmentPass = true;
31510                 this.onLayout();
31511                 return true;
31512             }
31513         }
31514
31515         delete this.adjustmentPass;
31516     },
31517
31518     
31519     isValidParent : function(item, target, position) {
31520         
31521         
31522         var itemEl = item.el ? item.el.dom : Ext.getDom(item);
31523         return (itemEl && this.innerCt && itemEl.parentNode === this.innerCt.dom) || false;
31524     },
31525
31526     
31527     
31528     getRenderTarget: function() {
31529         if (!this.innerCt) {
31530             
31531             this.innerCt = this.getTarget().createChild({
31532                 cls: this.innerCls,
31533                 role: 'presentation'
31534             });
31535             this.padding = Ext.util.Format.parseBox(this.padding);
31536         }
31537         return this.innerCt;
31538     },
31539
31540     
31541     renderItem: function(item, target) {
31542         this.callParent(arguments);
31543         var me = this,
31544             itemEl = item.getEl(),
31545             style = itemEl.dom.style,
31546             margins = item.margins || item.margin;
31547
31548         
31549         if (margins) {
31550             if (Ext.isString(margins) || Ext.isNumber(margins)) {
31551                 margins = Ext.util.Format.parseBox(margins);
31552             } else {
31553                 Ext.applyIf(margins, {top: 0, right: 0, bottom: 0, left: 0});
31554             }
31555         } else {
31556             margins = Ext.apply({}, me.defaultMargins);
31557         }
31558
31559         
31560         margins.top    += itemEl.getMargin('t');
31561         margins.right  += itemEl.getMargin('r');
31562         margins.bottom += itemEl.getMargin('b');
31563         margins.left   += itemEl.getMargin('l');
31564         style.marginTop = style.marginRight = style.marginBottom = style.marginLeft = '0';
31565
31566         
31567         item.margins = margins;
31568     },
31569
31570     
31571     destroy: function() {
31572         Ext.destroy(this.overflowHandler);
31573         this.callParent(arguments);
31574     }
31575 });
31576
31577 Ext.define('Ext.layout.container.HBox', {
31578
31579     
31580
31581     alias: ['layout.hbox'],
31582     extend: 'Ext.layout.container.Box',
31583     alternateClassName: 'Ext.layout.HBoxLayout',
31584     
31585     
31586
31587     
31588     align: 'top', 
31589
31590     //@private
31591
31592     alignCenteringString: 'middle',
31593
31594     type : 'hbox',
31595
31596     direction: 'horizontal',
31597
31598     
31599     parallelSizeIndex: 0,
31600     perpendicularSizeIndex: 1,
31601
31602     parallelPrefix: 'width',
31603     parallelPrefixCap: 'Width',
31604     parallelLT: 'l',
31605     parallelRB: 'r',
31606     parallelBefore: 'left',
31607     parallelBeforeCap: 'Left',
31608     parallelAfter: 'right',
31609     parallelPosition: 'x',
31610
31611     perpendicularPrefix: 'height',
31612     perpendicularPrefixCap: 'Height',
31613     perpendicularLT: 't',
31614     perpendicularRB: 'b',
31615     perpendicularLeftTop: 'top',
31616     perpendicularRightBottom: 'bottom',
31617     perpendicularPosition: 'y'
31618 });
31619
31620 Ext.define('Ext.layout.container.VBox', {
31621
31622     
31623
31624     alias: ['layout.vbox'],
31625     extend: 'Ext.layout.container.Box',
31626     alternateClassName: 'Ext.layout.VBoxLayout',
31627     
31628     
31629
31630     
31631     align : 'left', 
31632
31633     //@private
31634
31635     alignCenteringString: 'center',
31636
31637     type: 'vbox',
31638
31639     direction: 'vertical',
31640
31641     
31642     parallelSizeIndex: 1,
31643     perpendicularSizeIndex: 0,
31644
31645     parallelPrefix: 'height',
31646     parallelPrefixCap: 'Height',
31647     parallelLT: 't',
31648     parallelRB: 'b',
31649     parallelBefore: 'top',
31650     parallelBeforeCap: 'Top',
31651     parallelAfter: 'bottom',
31652     parallelPosition: 'y',
31653
31654     perpendicularPrefix: 'width',
31655     perpendicularPrefixCap: 'Width',
31656     perpendicularLT: 'l',
31657     perpendicularRB: 'r',
31658     perpendicularLeftTop: 'left',
31659     perpendicularRightBottom: 'right',
31660     perpendicularPosition: 'x'
31661 });
31662
31663 Ext.define('Ext.FocusManager', {
31664     singleton: true,
31665     alternateClassName: 'Ext.FocusMgr',
31666
31667     mixins: {
31668         observable: 'Ext.util.Observable'
31669     },
31670
31671     requires: [
31672         'Ext.ComponentManager',
31673         'Ext.ComponentQuery',
31674         'Ext.util.HashMap',
31675         'Ext.util.KeyNav'
31676     ],
31677
31678     
31679     enabled: false,
31680
31681     
31682
31683     focusElementCls: Ext.baseCSSPrefix + 'focus-element',
31684
31685     focusFrameCls: Ext.baseCSSPrefix + 'focus-frame',
31686
31687     
31688     whitelist: [
31689         'textfield'
31690     ],
31691
31692     tabIndexWhitelist: [
31693         'a',
31694         'button',
31695         'embed',
31696         'frame',
31697         'iframe',
31698         'img',
31699         'input',
31700         'object',
31701         'select',
31702         'textarea'
31703     ],
31704
31705     constructor: function() {
31706         var me = this,
31707             CQ = Ext.ComponentQuery;
31708
31709         me.addEvents(
31710             
31711             'beforecomponentfocus',
31712
31713             
31714             'componentfocus',
31715
31716             
31717             'disable',
31718
31719             
31720             'enable'
31721         );
31722
31723         
31724         
31725         me.keyNav = Ext.create('Ext.util.KeyNav', Ext.getDoc(), {
31726             disabled: true,
31727             scope: me,
31728
31729             backspace: me.focusLast,
31730             enter: me.navigateIn,
31731             esc: me.navigateOut,
31732             tab: me.navigateSiblings
31733
31734             
31735             
31736             
31737             
31738             
31739             
31740         });
31741
31742         me.focusData = {};
31743         me.subscribers = Ext.create('Ext.util.HashMap');
31744         me.focusChain = {};
31745
31746         
31747         Ext.apply(CQ.pseudos, {
31748             focusable: function(cmps) {
31749                 var len = cmps.length,
31750                     results = [],
31751                     i = 0,
31752                     c,
31753
31754                     isFocusable = function(x) {
31755                         return x && x.focusable !== false && CQ.is(x, '[rendered]:not([destroying]):not([isDestroyed]):not([disabled]){isVisible(true)}{el && c.el.dom && c.el.isVisible()}');
31756                     };
31757
31758                 for (; i < len; i++) {
31759                     c = cmps[i];
31760                     if (isFocusable(c)) {
31761                         results.push(c);
31762                     }
31763                 }
31764
31765                 return results;
31766             },
31767
31768             nextFocus: function(cmps, idx, step) {
31769                 step = step || 1;
31770                 idx = parseInt(idx, 10);
31771
31772                 var len = cmps.length,
31773                     i = idx + step,
31774                     c;
31775
31776                 for (; i != idx; i += step) {
31777                     if (i >= len) {
31778                         i = 0;
31779                     } else if (i < 0) {
31780                         i = len - 1;
31781                     }
31782
31783                     c = cmps[i];
31784                     if (CQ.is(c, ':focusable')) {
31785                         return [c];
31786                     } else if (c.placeholder && CQ.is(c.placeholder, ':focusable')) {
31787                         return [c.placeholder];
31788                     }
31789                 }
31790
31791                 return [];
31792             },
31793
31794             prevFocus: function(cmps, idx) {
31795                 return this.nextFocus(cmps, idx, -1);
31796             },
31797
31798             root: function(cmps) {
31799                 var len = cmps.length,
31800                     results = [],
31801                     i = 0,
31802                     c;
31803
31804                 for (; i < len; i++) {
31805                     c = cmps[i];
31806                     if (!c.ownerCt) {
31807                         results.push(c);
31808                     }
31809                 }
31810
31811                 return results;
31812             }
31813         });
31814     },
31815
31816     
31817     addXTypeToWhitelist: function(xtype) {
31818         var me = this;
31819
31820         if (Ext.isArray(xtype)) {
31821             Ext.Array.forEach(xtype, me.addXTypeToWhitelist, me);
31822             return;
31823         }
31824
31825         if (!Ext.Array.contains(me.whitelist, xtype)) {
31826             me.whitelist.push(xtype);
31827         }
31828     },
31829
31830     clearComponent: function(cmp) {
31831         clearTimeout(this.cmpFocusDelay);
31832         if (!cmp.isDestroyed) {
31833             cmp.blur();
31834         }
31835     },
31836
31837     
31838     disable: function() {
31839         var me = this;
31840
31841         if (!me.enabled) {
31842             return;
31843         }
31844
31845         delete me.options;
31846         me.enabled = false;
31847
31848         Ext.ComponentManager.all.un('add', me.onComponentCreated, me);
31849
31850         me.removeDOM();
31851
31852         
31853         me.keyNav.disable();
31854
31855         
31856         me.setFocusAll(false);
31857
31858         me.fireEvent('disable', me);
31859     },
31860
31861     
31862     enable: function(options) {
31863         var me = this;
31864
31865         if (options === true) {
31866             options = { focusFrame: true };
31867         }
31868         me.options = options = options || {};
31869
31870         if (me.enabled) {
31871             return;
31872         }
31873
31874         
31875         Ext.ComponentManager.all.on('add', me.onComponentCreated, me);
31876
31877         me.initDOM(options);
31878
31879         
31880         me.keyNav.enable();
31881
31882         
31883         me.setFocusAll(true, options);
31884
31885         
31886         me.focusEl.focus();
31887         delete me.focusedCmp;
31888
31889         me.enabled = true;
31890         me.fireEvent('enable', me);
31891     },
31892
31893     focusLast: function(e) {
31894         var me = this;
31895
31896         if (me.isWhitelisted(me.focusedCmp)) {
31897             return true;
31898         }
31899
31900         
31901         if (me.previousFocusedCmp) {
31902             me.previousFocusedCmp.focus();
31903         }
31904     },
31905
31906     getRootComponents: function() {
31907         var me = this,
31908             CQ = Ext.ComponentQuery,
31909             inline = CQ.query(':focusable:root:not([floating])'),
31910             floating = CQ.query(':focusable:root[floating]');
31911
31912         
31913         
31914         floating.sort(function(a, b) {
31915             return a.el.getZIndex() > b.el.getZIndex();
31916         });
31917
31918         return floating.concat(inline);
31919     },
31920
31921     initDOM: function(options) {
31922         var me = this,
31923             sp = '&#160',
31924             cls = me.focusFrameCls;
31925
31926         if (!Ext.isReady) {
31927             Ext.onReady(me.initDOM, me);
31928             return;
31929         }
31930
31931         
31932         if (!me.focusEl) {
31933             me.focusEl = Ext.getBody().createChild({
31934                 tabIndex: '-1',
31935                 cls: me.focusElementCls,
31936                 html: sp
31937             });
31938         }
31939
31940         
31941         if (!me.focusFrame && options.focusFrame) {
31942             me.focusFrame = Ext.getBody().createChild({
31943                 cls: cls,
31944                 children: [
31945                     { cls: cls + '-top' },
31946                     { cls: cls + '-bottom' },
31947                     { cls: cls + '-left' },
31948                     { cls: cls + '-right' }
31949                 ],
31950                 style: 'top: -100px; left: -100px;'
31951             });
31952             me.focusFrame.setVisibilityMode(Ext.core.Element.DISPLAY);
31953             me.focusFrameWidth = me.focusFrame.child('.' + cls + '-top').getHeight();
31954             me.focusFrame.hide().setLeftTop(0, 0);
31955         }
31956     },
31957
31958     isWhitelisted: function(cmp) {
31959         return cmp && Ext.Array.some(this.whitelist, function(x) {
31960             return cmp.isXType(x);
31961         });
31962     },
31963
31964     navigateIn: function(e) {
31965         var me = this,
31966             focusedCmp = me.focusedCmp,
31967             rootCmps,
31968             firstChild;
31969
31970         if (!focusedCmp) {
31971             
31972             rootCmps = me.getRootComponents();
31973             if (rootCmps.length) {
31974                 rootCmps[0].focus();
31975             }
31976         } else {
31977             
31978             
31979             firstChild = Ext.ComponentQuery.query('>:focusable', focusedCmp)[0];
31980             if (firstChild) {
31981                 firstChild.focus();
31982             } else {
31983                 
31984                 if (Ext.isFunction(focusedCmp.onClick)) {
31985                     e.button = 0;
31986                     focusedCmp.onClick(e);
31987                     focusedCmp.focus();
31988                 }
31989             }
31990         }
31991     },
31992
31993     navigateOut: function(e) {
31994         var me = this,
31995             parent;
31996
31997         if (!me.focusedCmp || !(parent = me.focusedCmp.up(':focusable'))) {
31998             me.focusEl.focus();
31999             return;
32000         }
32001
32002         parent.focus();
32003     },
32004
32005     navigateSiblings: function(e, source, parent) {
32006         var me = this,
32007             src = source || me,
32008             key = e.getKey(),
32009             EO = Ext.EventObject,
32010             goBack = e.shiftKey || key == EO.LEFT || key == EO.UP,
32011             checkWhitelist = key == EO.LEFT || key == EO.RIGHT || key == EO.UP || key == EO.DOWN,
32012             nextSelector = goBack ? 'prev' : 'next',
32013             idx, next, focusedCmp;
32014
32015         focusedCmp = (src.focusedCmp && src.focusedCmp.comp) || src.focusedCmp;
32016         if (!focusedCmp && !parent) {
32017             return;
32018         }
32019
32020         if (checkWhitelist && me.isWhitelisted(focusedCmp)) {
32021             return true;
32022         }
32023
32024         parent = parent || focusedCmp.up();
32025         if (parent) {
32026             idx = focusedCmp ? Ext.Array.indexOf(parent.getRefItems(), focusedCmp) : -1;
32027             next = Ext.ComponentQuery.query('>:' + nextSelector + 'Focus(' + idx + ')', parent)[0];
32028             if (next && focusedCmp !== next) {
32029                 next.focus();
32030                 return next;
32031             }
32032         }
32033     },
32034
32035     onComponentBlur: function(cmp, e) {
32036         var me = this;
32037
32038         if (me.focusedCmp === cmp) {
32039             me.previousFocusedCmp = cmp;
32040             delete me.focusedCmp;
32041         }
32042
32043         if (me.focusFrame) {
32044             me.focusFrame.hide();
32045         }
32046     },
32047
32048     onComponentCreated: function(hash, id, cmp) {
32049         this.setFocus(cmp, true, this.options);
32050     },
32051
32052     onComponentDestroy: function(cmp) {
32053         this.setFocus(cmp, false);
32054     },
32055
32056     onComponentFocus: function(cmp, e) {
32057         var me = this,
32058             chain = me.focusChain;
32059
32060         if (!Ext.ComponentQuery.is(cmp, ':focusable')) {
32061             me.clearComponent(cmp);
32062
32063             
32064             
32065             
32066             
32067             if (chain[cmp.id]) {
32068                 return;
32069             }
32070
32071             
32072             var parent = cmp.up();
32073             if (parent) {
32074                 
32075                 
32076                 
32077                 chain[cmp.id] = true;
32078                 parent.focus();
32079             }
32080
32081             return;
32082         }
32083
32084         
32085         me.focusChain = {};
32086
32087         
32088         
32089         clearTimeout(me.cmpFocusDelay);
32090         if (arguments.length !== 2) {
32091             me.cmpFocusDelay = Ext.defer(me.onComponentFocus, 90, me, [cmp, e]);
32092             return;
32093         }
32094
32095         if (me.fireEvent('beforecomponentfocus', me, cmp, me.previousFocusedCmp) === false) {
32096             me.clearComponent(cmp);
32097             return;
32098         }
32099
32100         me.focusedCmp = cmp;
32101
32102         
32103         if (me.shouldShowFocusFrame(cmp)) {
32104             var cls = '.' + me.focusFrameCls + '-',
32105                 ff = me.focusFrame,
32106                 fw = me.focusFrameWidth,
32107                 box = cmp.el.getPageBox(),
32108
32109             
32110             
32111             
32112                 bt = box.top,
32113                 bl = box.left,
32114                 bw = box.width,
32115                 bh = box.height,
32116                 ft = ff.child(cls + 'top'),
32117                 fb = ff.child(cls + 'bottom'),
32118                 fl = ff.child(cls + 'left'),
32119                 fr = ff.child(cls + 'right');
32120
32121             ft.setWidth(bw - 2).setLeftTop(bl + 1, bt);
32122             fb.setWidth(bw - 2).setLeftTop(bl + 1, bt + bh - fw);
32123             fl.setHeight(bh - 2).setLeftTop(bl, bt + 1);
32124             fr.setHeight(bh - 2).setLeftTop(bl + bw - fw, bt + 1);
32125
32126             ff.show();
32127         }
32128
32129         me.fireEvent('componentfocus', me, cmp, me.previousFocusedCmp);
32130     },
32131
32132     onComponentHide: function(cmp) {
32133         var me = this,
32134             CQ = Ext.ComponentQuery,
32135             cmpHadFocus = false,
32136             focusedCmp,
32137             parent;
32138
32139         if (me.focusedCmp) {
32140             focusedCmp = CQ.query('[id=' + me.focusedCmp.id + ']', cmp)[0];
32141             cmpHadFocus = me.focusedCmp.id === cmp.id || focusedCmp;
32142
32143             if (focusedCmp) {
32144                 me.clearComponent(focusedCmp);
32145             }
32146         }
32147
32148         me.clearComponent(cmp);
32149
32150         if (cmpHadFocus) {
32151             parent = CQ.query('^:focusable', cmp)[0];
32152             if (parent) {
32153                 parent.focus();
32154             }
32155         }
32156     },
32157
32158     removeDOM: function() {
32159         var me = this;
32160
32161         
32162         
32163         if (me.enabled || me.subscribers.length) {
32164             return;
32165         }
32166
32167         Ext.destroy(
32168             me.focusEl,
32169             me.focusFrame
32170         );
32171         delete me.focusEl;
32172         delete me.focusFrame;
32173         delete me.focusFrameWidth;
32174     },
32175
32176     
32177     removeXTypeFromWhitelist: function(xtype) {
32178         var me = this;
32179
32180         if (Ext.isArray(xtype)) {
32181             Ext.Array.forEach(xtype, me.removeXTypeFromWhitelist, me);
32182             return;
32183         }
32184
32185         Ext.Array.remove(me.whitelist, xtype);
32186     },
32187
32188     setFocus: function(cmp, focusable, options) {
32189         var me = this,
32190             el, dom, data,
32191
32192             needsTabIndex = function(n) {
32193                 return !Ext.Array.contains(me.tabIndexWhitelist, n.tagName.toLowerCase())
32194                     && n.tabIndex <= 0;
32195             };
32196
32197         options = options || {};
32198
32199         
32200         if (!cmp.rendered) {
32201             cmp.on('afterrender', Ext.pass(me.setFocus, arguments, me), me, { single: true });
32202             return;
32203         }
32204
32205         el = cmp.getFocusEl();
32206         dom = el.dom;
32207
32208         
32209         if ((focusable && !me.focusData[cmp.id]) || (!focusable && me.focusData[cmp.id])) {
32210             if (focusable) {
32211                 data = {
32212                     focusFrame: options.focusFrame
32213                 };
32214
32215                 
32216                 
32217                 
32218                 
32219                 if (needsTabIndex(dom)) {
32220                     data.tabIndex = dom.tabIndex;
32221                     dom.tabIndex = -1;
32222                 }
32223
32224                 el.on({
32225                     focus: data.focusFn = Ext.bind(me.onComponentFocus, me, [cmp], 0),
32226                     blur: data.blurFn = Ext.bind(me.onComponentBlur, me, [cmp], 0),
32227                     scope: me
32228                 });
32229                 cmp.on({
32230                     hide: me.onComponentHide,
32231                     close: me.onComponentHide,
32232                     beforedestroy: me.onComponentDestroy,
32233                     scope: me
32234                 });
32235
32236                 me.focusData[cmp.id] = data;
32237             } else {
32238                 data = me.focusData[cmp.id];
32239                 if ('tabIndex' in data) {
32240                     dom.tabIndex = data.tabIndex;
32241                 }
32242                 el.un('focus', data.focusFn, me);
32243                 el.un('blur', data.blurFn, me);
32244                 cmp.un('hide', me.onComponentHide, me);
32245                 cmp.un('close', me.onComponentHide, me);
32246                 cmp.un('beforedestroy', me.onComponentDestroy, me);
32247
32248                 delete me.focusData[cmp.id];
32249             }
32250         }
32251     },
32252
32253     setFocusAll: function(focusable, options) {
32254         var me = this,
32255             cmps = Ext.ComponentManager.all.getArray(),
32256             len = cmps.length,
32257             cmp,
32258             i = 0;
32259
32260         for (; i < len; i++) {
32261             me.setFocus(cmps[i], focusable, options);
32262         }
32263     },
32264
32265     setupSubscriberKeys: function(container, keys) {
32266         var me = this,
32267             el = container.getFocusEl(),
32268             scope = keys.scope,
32269             handlers = {
32270                 backspace: me.focusLast,
32271                 enter: me.navigateIn,
32272                 esc: me.navigateOut,
32273                 scope: me
32274             },
32275
32276             navSiblings = function(e) {
32277                 if (me.focusedCmp === container) {
32278                     
32279                     
32280                     
32281                     return me.navigateSiblings(e, me, container);
32282                 } else {
32283                     return me.navigateSiblings(e);
32284                 }
32285             };
32286
32287         Ext.iterate(keys, function(key, cb) {
32288             handlers[key] = function(e) {
32289                 var ret = navSiblings(e);
32290
32291                 if (Ext.isFunction(cb) && cb.call(scope || container, e, ret) === true) {
32292                     return true;
32293                 }
32294
32295                 return ret;
32296             };
32297         }, me);
32298
32299         return Ext.create('Ext.util.KeyNav', el, handlers);
32300     },
32301
32302     shouldShowFocusFrame: function(cmp) {
32303         var me = this,
32304             opts = me.options || {};
32305
32306         if (!me.focusFrame || !cmp) {
32307             return false;
32308         }
32309
32310         
32311         if (opts.focusFrame) {
32312             return true;
32313         }
32314
32315         if (me.focusData[cmp.id].focusFrame) {
32316             return true;
32317         }
32318
32319         return false;
32320     },
32321
32322     
32323     subscribe: function(container, options) {
32324         var me = this,
32325             EA = Ext.Array,
32326             data = {},
32327             subs = me.subscribers,
32328
32329             
32330             
32331             
32332             safeSetFocus = function(cmp) {
32333                 if (cmp.isContainer && !subs.containsKey(cmp.id)) {
32334                     EA.forEach(cmp.query('>'), safeSetFocus);
32335                     me.setFocus(cmp, true, options);
32336                     cmp.on('add', data.onAdd, me);
32337                 } else if (!cmp.isContainer) {
32338                     me.setFocus(cmp, true, options);
32339                 }
32340             };
32341
32342         
32343         if (!container || !container.isContainer) {
32344             return;
32345         }
32346
32347         if (!container.rendered) {
32348             container.on('afterrender', Ext.pass(me.subscribe, arguments, me), me, { single: true });
32349             return;
32350         }
32351
32352         
32353         me.initDOM(options);
32354
32355         
32356         data.keyNav = me.setupSubscriberKeys(container, options.keys);
32357
32358         
32359         
32360         
32361         
32362         data.onAdd = function(ct, cmp, idx) {
32363             safeSetFocus(cmp);
32364         };
32365         container.on('beforedestroy', me.unsubscribe, me);
32366
32367         
32368         safeSetFocus(container);
32369
32370         
32371         subs.add(container.id, data);
32372     },
32373
32374     
32375     unsubscribe: function(container) {
32376         var me = this,
32377             EA = Ext.Array,
32378             subs = me.subscribers,
32379             data,
32380
32381             
32382             
32383             
32384             safeSetFocus = function(cmp) {
32385                 if (cmp.isContainer && !subs.containsKey(cmp.id)) {
32386                     EA.forEach(cmp.query('>'), safeSetFocus);
32387                     me.setFocus(cmp, false);
32388                     cmp.un('add', data.onAdd, me);
32389                 } else if (!cmp.isContainer) {
32390                     me.setFocus(cmp, false);
32391                 }
32392             };
32393
32394         if (!container || !subs.containsKey(container.id)) {
32395             return;
32396         }
32397
32398         data = subs.get(container.id);
32399         data.keyNav.destroy();
32400         container.un('beforedestroy', me.unsubscribe, me);
32401         subs.removeAtKey(container.id);
32402         safeSetFocus(container);
32403         me.removeDOM();
32404     }
32405 });
32406
32407 Ext.define('Ext.toolbar.Toolbar', {
32408     extend: 'Ext.container.Container',
32409     requires: [
32410         'Ext.toolbar.Fill',
32411         'Ext.layout.container.HBox',
32412         'Ext.layout.container.VBox',
32413         'Ext.FocusManager'
32414     ],
32415     uses: [
32416         'Ext.toolbar.Separator'
32417     ],
32418     alias: 'widget.toolbar',
32419     alternateClassName: 'Ext.Toolbar',
32420     
32421     isToolbar: true,
32422     baseCls  : Ext.baseCSSPrefix + 'toolbar',
32423     ariaRole : 'toolbar',
32424     
32425     defaultType: 'button',
32426     
32427     
32428     vertical: false,
32429
32430     
32431
32432     
32433     enableOverflow: false,
32434     
32435     
32436     trackMenus: true,
32437     
32438     itemCls: Ext.baseCSSPrefix + 'toolbar-item',
32439     
32440     initComponent: function() {
32441         var me = this,
32442             keys;
32443
32444         
32445         if (!me.layout && me.enableOverflow) {
32446             me.layout = { overflowHandler: 'Menu' };
32447         }
32448         
32449         if (me.dock === 'right' || me.dock === 'left') {
32450             me.vertical = true;
32451         }
32452
32453         me.layout = Ext.applyIf(Ext.isString(me.layout) ? {
32454             type: me.layout
32455         } : me.layout || {}, {
32456             type: me.vertical ? 'vbox' : 'hbox',
32457             align: me.vertical ? 'stretchmax' : 'middle'
32458         });
32459         
32460         if (me.vertical) {
32461             me.addClsWithUI('vertical');
32462         }
32463         
32464         
32465         if (me.ui === 'footer') {
32466             me.ignoreBorderManagement = true;
32467         }
32468         
32469         me.callParent();
32470
32471         
32472         me.addEvents('overflowchange');
32473         
32474         
32475         keys = me.vertical ? ['up', 'down'] : ['left', 'right'];
32476         Ext.FocusManager.subscribe(me, {
32477             keys: keys
32478         });
32479     },
32480
32481     
32482
32483     
32484     lookupComponent: function(c) {
32485         if (Ext.isString(c)) {
32486             var shortcut = Ext.toolbar.Toolbar.shortcuts[c];
32487             if (shortcut) {
32488                 c = {
32489                     xtype: shortcut
32490                 };
32491             } else {
32492                 c = {
32493                     xtype: 'tbtext',
32494                     text: c
32495                 };
32496             }
32497             this.applyDefaults(c);
32498         }
32499         return this.callParent(arguments);
32500     },
32501
32502     
32503     applyDefaults: function(c) {
32504         if (!Ext.isString(c)) {
32505             c = this.callParent(arguments);
32506             var d = this.internalDefaults;
32507             if (c.events) {
32508                 Ext.applyIf(c.initialConfig, d);
32509                 Ext.apply(c, d);
32510             } else {
32511                 Ext.applyIf(c, d);
32512             }
32513         }
32514         return c;
32515     },
32516
32517     
32518     trackMenu: function(item, remove) {
32519         if (this.trackMenus && item.menu) {
32520             var method = remove ? 'mun' : 'mon',
32521                 me = this;
32522
32523             me[method](item, 'menutriggerover', me.onButtonTriggerOver, me);
32524             me[method](item, 'menushow', me.onButtonMenuShow, me);
32525             me[method](item, 'menuhide', me.onButtonMenuHide, me);
32526         }
32527     },
32528
32529     
32530     constructButton: function(item) {
32531         return item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
32532     },
32533
32534     
32535     onBeforeAdd: function(component) {
32536         if (component.is('field') || (component.is('button') && this.ui != 'footer')) {
32537             component.ui = component.ui + '-toolbar';
32538         }
32539         
32540         
32541         if (component instanceof Ext.toolbar.Separator) {
32542             component.setUI((this.vertical) ? 'vertical' : 'horizontal');
32543         }
32544         
32545         this.callParent(arguments);
32546     },
32547
32548     
32549     onAdd: function(component) {
32550         this.callParent(arguments);
32551
32552         this.trackMenu(component);
32553         if (this.disabled) {
32554             component.disable();
32555         }
32556     },
32557
32558     
32559     onRemove: function(c) {
32560         this.callParent(arguments);
32561         this.trackMenu(c, true);
32562     },
32563
32564     
32565     onButtonTriggerOver: function(btn){
32566         if (this.activeMenuBtn && this.activeMenuBtn != btn) {
32567             this.activeMenuBtn.hideMenu();
32568             btn.showMenu();
32569             this.activeMenuBtn = btn;
32570         }
32571     },
32572
32573     
32574     onButtonMenuShow: function(btn) {
32575         this.activeMenuBtn = btn;
32576     },
32577
32578     
32579     onButtonMenuHide: function(btn) {
32580         delete this.activeMenuBtn;
32581     }
32582 }, function() {
32583     this.shortcuts = {
32584         '-' : 'tbseparator',
32585         ' ' : 'tbspacer',
32586         '->': 'tbfill'
32587     };
32588 });
32589
32590 Ext.define('Ext.panel.AbstractPanel', {
32591
32592     
32593
32594     extend: 'Ext.container.Container',
32595
32596     requires: ['Ext.util.MixedCollection', 'Ext.core.Element', 'Ext.toolbar.Toolbar'],
32597
32598     
32599
32600     
32601     baseCls : Ext.baseCSSPrefix + 'panel',
32602
32603     
32604
32605     
32606     
32607     
32608     
32609     
32610
32611     isPanel: true,
32612
32613     componentLayout: 'dock',
32614
32615     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>'],
32616
32617     
32618     
32619      
32620     border: true,
32621
32622     initComponent : function() {
32623         var me = this;
32624         
32625         me.addEvents(
32626             
32627             'bodyresize'
32628             
32629             
32630             
32631             
32632         );
32633
32634         Ext.applyIf(me.renderSelectors, {
32635             body: '.' + me.baseCls + '-body'
32636         });
32637         
32638         
32639         
32640         
32641         if (me.frame && me.border && me.bodyBorder === undefined) {
32642             me.bodyBorder = false;
32643         }
32644         if (me.frame && me.border && (me.bodyBorder === false || me.bodyBorder === 0)) {
32645             me.manageBodyBorders = true;
32646         }
32647         
32648         me.callParent();
32649     },
32650
32651     
32652     initItems : function() {
32653         var me = this,
32654             items = me.dockedItems;
32655             
32656         me.callParent();
32657         me.dockedItems = Ext.create('Ext.util.MixedCollection', false, me.getComponentId);
32658         if (items) {
32659             me.addDocked(items);
32660         }
32661     },
32662
32663     
32664     getDockedComponent: function(comp) {
32665         if (Ext.isObject(comp)) {
32666             comp = comp.getItemId();
32667         }
32668         return this.dockedItems.get(comp);
32669     },
32670
32671     
32672     getComponent: function(comp) {
32673         var component = this.callParent(arguments);
32674         if (component === undefined && !Ext.isNumber(comp)) {
32675             
32676             component = this.getDockedComponent(comp);
32677         }
32678         return component;
32679     },
32680
32681     
32682     initBodyStyles: function() {
32683         var me = this,
32684             bodyStyle = me.bodyStyle,
32685             styles = [],
32686             Element = Ext.core.Element,
32687             prop;
32688
32689         if (Ext.isFunction(bodyStyle)) {
32690             bodyStyle = bodyStyle();
32691         }
32692         if (Ext.isString(bodyStyle)) {
32693             styles = bodyStyle.split(';');
32694         } else {
32695             for (prop in bodyStyle) {
32696                 if (bodyStyle.hasOwnProperty(prop)) {
32697                     styles.push(prop + ':' + bodyStyle[prop]);
32698                 }
32699             }
32700         }
32701
32702         if (me.bodyPadding !== undefined) {
32703             styles.push('padding: ' + Element.unitizeBox((me.bodyPadding === true) ? 5 : me.bodyPadding));
32704         }
32705         if (me.frame && me.bodyBorder) {
32706             if (!Ext.isNumber(me.bodyBorder)) {
32707                 me.bodyBorder = 1;
32708             }
32709             styles.push('border-width: ' + Element.unitizeBox(me.bodyBorder));
32710         }
32711         delete me.bodyStyle;
32712         return styles.length ? styles.join(';') : undefined;
32713     },
32714     
32715     
32716     initBodyCls: function() {
32717         var me = this,
32718             cls = '',
32719             bodyCls = me.bodyCls;
32720         
32721         if (bodyCls) {
32722             Ext.each(bodyCls, function(v) {
32723                 cls += " " + v;
32724             });
32725             delete me.bodyCls;
32726         }
32727         return cls.length > 0 ? cls : undefined;
32728     },
32729     
32730     
32731     initRenderData: function() {
32732         return Ext.applyIf(this.callParent(), {
32733             bodyStyle: this.initBodyStyles(),
32734             bodyCls: this.initBodyCls()
32735         });
32736     },
32737
32738     
32739     addDocked : function(items, pos) {
32740         var me = this,
32741             i = 0,
32742             item, length;
32743
32744         items = me.prepareItems(items);
32745         length = items.length;
32746
32747         for (; i < length; i++) {
32748             item = items[i];
32749             item.dock = item.dock || 'top';
32750
32751             
32752             if (me.border === false) {
32753                 
32754             }
32755
32756             if (pos !== undefined) {
32757                 me.dockedItems.insert(pos + i, item);
32758             }
32759             else {
32760                 me.dockedItems.add(item);
32761             }
32762             item.onAdded(me, i);
32763             me.onDockedAdd(item);
32764         }
32765         if (me.rendered && !me.suspendLayout) {
32766             me.doComponentLayout();
32767         }
32768         return items;
32769     },
32770
32771     
32772     onDockedAdd : Ext.emptyFn,
32773     onDockedRemove : Ext.emptyFn,
32774
32775     
32776     insertDocked : function(pos, items) {
32777         this.addDocked(items, pos);
32778     },
32779
32780     
32781     removeDocked : function(item, autoDestroy) {
32782         var me = this,
32783             layout,
32784             hasLayout;
32785             
32786         if (!me.dockedItems.contains(item)) {
32787             return item;
32788         }
32789
32790         layout = me.componentLayout;
32791         hasLayout = layout && me.rendered;
32792
32793         if (hasLayout) {
32794             layout.onRemove(item);
32795         }
32796
32797         me.dockedItems.remove(item);
32798         item.onRemoved();
32799         me.onDockedRemove(item);
32800
32801         if (autoDestroy === true || (autoDestroy !== false && me.autoDestroy)) {
32802             item.destroy();
32803         }
32804
32805         if (hasLayout && !autoDestroy) {
32806             layout.afterRemove(item);
32807         }
32808         
32809         if (!this.destroying) {
32810             me.doComponentLayout();
32811         }
32812
32813         return item;
32814     },
32815
32816     
32817     getDockedItems : function(cqSelector) {
32818         var me = this,
32819             
32820             
32821             defaultWeight = { top: 1, left: 3, right: 5, bottom: 7 },
32822             dockedItems;
32823
32824         if (me.dockedItems && me.dockedItems.items.length) {
32825             
32826             if (cqSelector) {
32827                 dockedItems = Ext.ComponentQuery.query(cqSelector, me.dockedItems.items);
32828             } else {
32829                 dockedItems = me.dockedItems.items.slice();
32830             }
32831
32832             Ext.Array.sort(dockedItems, function(a, b) {
32833                 
32834                 
32835                 var aw = a.weight || defaultWeight[a.dock],
32836                     bw = b.weight || defaultWeight[b.dock];
32837                 if (Ext.isNumber(aw) && Ext.isNumber(bw)) {
32838                     return aw - bw;
32839                 }
32840                 return 0;
32841             });
32842             
32843             return dockedItems;
32844         }
32845         return [];
32846     },
32847     
32848     
32849     addUIClsToElement: function(cls, force) {
32850         var me = this;
32851         
32852         me.callParent(arguments);
32853         
32854         if (!force && me.rendered) {
32855             me.body.addCls(Ext.baseCSSPrefix + cls);
32856             me.body.addCls(me.baseCls + '-body-' + cls);
32857             me.body.addCls(me.baseCls + '-body-' + me.ui + '-' + cls);
32858         }
32859     },
32860     
32861     
32862     removeUIClsFromElement: function(cls, force) {
32863         var me = this;
32864         
32865         me.callParent(arguments);
32866         
32867         if (!force && me.rendered) {
32868             me.body.removeCls(Ext.baseCSSPrefix + cls);
32869             me.body.removeCls(me.baseCls + '-body-' + cls);
32870             me.body.removeCls(me.baseCls + '-body-' + me.ui + '-' + cls);
32871         }
32872     },
32873     
32874     
32875     addUIToElement: function(force) {
32876         var me = this;
32877         
32878         me.callParent(arguments);
32879         
32880         if (!force && me.rendered) {
32881             me.body.addCls(me.baseCls + '-body-' + me.ui);
32882         }
32883     },
32884     
32885     
32886     removeUIFromElement: function() {
32887         var me = this;
32888         
32889         me.callParent(arguments);
32890         
32891         if (me.rendered) {
32892             me.body.removeCls(me.baseCls + '-body-' + me.ui);
32893         }
32894     },
32895
32896     
32897     getTargetEl : function() {
32898         return this.body;
32899     },
32900
32901     getRefItems: function(deep) {
32902         var items = this.callParent(arguments),
32903             
32904             dockedItems = this.getDockedItems(deep ? '*,* *' : undefined),
32905             ln = dockedItems.length,
32906             i = 0,
32907             item;
32908         
32909         
32910         for (; i < ln; i++) {
32911             item = dockedItems[i];
32912             if (item.dock === 'right' || item.dock === 'bottom') {
32913                 break;
32914             }
32915         }
32916         
32917         
32918         
32919         
32920         return dockedItems.splice(0, i).concat(items).concat(dockedItems);
32921     },
32922
32923     beforeDestroy: function(){
32924         var docked = this.dockedItems,
32925             c;
32926
32927         if (docked) {
32928             while ((c = docked.first())) {
32929                 this.removeDocked(c, true);
32930             }
32931         }
32932         this.callParent();
32933     },
32934     
32935     setBorder: function(border) {
32936         var me = this;
32937         me.border = (border !== undefined) ? border : true;
32938         if (me.rendered) {
32939             me.doComponentLayout();
32940         }
32941     }
32942 });
32943
32944 Ext.define('Ext.panel.Header', {
32945     extend: 'Ext.container.Container',
32946     uses: ['Ext.panel.Tool', 'Ext.draw.Component', 'Ext.util.CSS'],
32947     alias: 'widget.header',
32948
32949     isHeader       : true,
32950     defaultType    : 'tool',
32951     indicateDrag   : false,
32952     weight         : -1,
32953
32954     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>'],
32955
32956     initComponent: function() {
32957         var me = this,
32958             rule,
32959             style,
32960             titleTextEl,
32961             ui;
32962
32963         me.indicateDragCls = me.baseCls + '-draggable';
32964         me.title = me.title || '&#160;';
32965         me.tools = me.tools || [];
32966         me.items = me.items || [];
32967         me.orientation = me.orientation || 'horizontal';
32968         me.dock = (me.dock) ? me.dock : (me.orientation == 'horizontal') ? 'top' : 'left';
32969
32970         
32971         
32972         me.addClsWithUI(me.orientation);
32973         me.addClsWithUI(me.dock);
32974
32975         Ext.applyIf(me.renderSelectors, {
32976             body: '.' + me.baseCls + '-body'
32977         });
32978
32979         
32980         if (!Ext.isEmpty(me.iconCls)) {
32981             me.initIconCmp();
32982             me.items.push(me.iconCmp);
32983         }
32984
32985         
32986         if (me.orientation == 'vertical') {
32987             
32988             if (Ext.isIE6 || Ext.isIE7) {
32989                 me.width = this.width || 24;
32990             } else if (Ext.isIEQuirks) {
32991                 me.width = this.width || 25;
32992             }
32993
32994             me.layout = {
32995                 type : 'vbox',
32996                 align: 'center',
32997                 clearInnerCtOnLayout: true,
32998                 bindToOwnerCtContainer: false
32999             };
33000             me.textConfig = {
33001                 cls: me.baseCls + '-text',
33002                 type: 'text',
33003                 text: me.title,
33004                 rotate: {
33005                     degrees: 90
33006                 }
33007             };
33008             ui = me.ui;
33009             if (Ext.isArray(ui)) {
33010                 ui = ui[0];
33011             }
33012             rule = Ext.util.CSS.getRule('.' + me.baseCls + '-text-' + ui);
33013             if (rule) {
33014                 style = rule.style;
33015             }
33016             if (style) {
33017                 Ext.apply(me.textConfig, {
33018                     'font-family': style.fontFamily,
33019                     'font-weight': style.fontWeight,
33020                     'font-size': style.fontSize,
33021                     fill: style.color
33022                 });
33023             }
33024             me.titleCmp = Ext.create('Ext.draw.Component', {
33025                 ariaRole  : 'heading',
33026                 focusable: false,
33027                 viewBox: false,
33028                 autoSize: true,
33029                 margins: '5 0 0 0',
33030                 items: [ me.textConfig ],
33031                 renderSelectors: {
33032                     textEl: '.' + me.baseCls + '-text'
33033                 }
33034             });
33035         } else {
33036             me.layout = {
33037                 type : 'hbox',
33038                 align: 'middle',
33039                 clearInnerCtOnLayout: true,
33040                 bindToOwnerCtContainer: false
33041             };
33042             me.titleCmp = Ext.create('Ext.Component', {
33043                 xtype     : 'component',
33044                 ariaRole  : 'heading',
33045                 focusable: false,
33046                 renderTpl : ['<span class="{cls}-text {cls}-text-{ui}">{title}</span>'],
33047                 renderData: {
33048                     title: me.title,
33049                     cls  : me.baseCls,
33050                     ui   : me.ui
33051                 },
33052                 renderSelectors: {
33053                     textEl: '.' + me.baseCls + '-text'
33054                 }
33055             });
33056         }
33057         me.items.push(me.titleCmp);
33058
33059         
33060         me.items.push({
33061             xtype: 'component',
33062             html : '&nbsp;',
33063             flex : 1,
33064             focusable: false
33065         });
33066
33067         
33068         me.items = me.items.concat(me.tools);
33069         this.callParent();
33070     },
33071
33072     initIconCmp: function() {
33073         this.iconCmp = Ext.create('Ext.Component', {
33074             focusable: false,
33075             renderTpl : ['<img alt="" src="{blank}" class="{cls}-icon {iconCls}"/>'],
33076             renderData: {
33077                 blank  : Ext.BLANK_IMAGE_URL,
33078                 cls    : this.baseCls,
33079                 iconCls: this.iconCls,
33080                 orientation: this.orientation
33081             },
33082             renderSelectors: {
33083                 iconEl: '.' + this.baseCls + '-icon'
33084             },
33085             iconCls: this.iconCls
33086         });
33087     },
33088
33089     afterRender: function() {
33090         var me = this;
33091
33092         me.el.unselectable();
33093         if (me.indicateDrag) {
33094             me.el.addCls(me.indicateDragCls);
33095         }
33096         me.mon(me.el, {
33097             click: me.onClick,
33098             scope: me
33099         });
33100         me.callParent();
33101     },
33102
33103     afterLayout: function() {
33104         var me = this;
33105         me.callParent(arguments);
33106
33107         
33108         if (Ext.isIE7) {
33109             me.el.repaint();
33110         }
33111     },
33112
33113     
33114     addUIClsToElement: function(cls, force) {
33115         var me = this;
33116
33117         me.callParent(arguments);
33118
33119         if (!force && me.rendered) {
33120             me.body.addCls(me.baseCls + '-body-' + cls);
33121             me.body.addCls(me.baseCls + '-body-' + me.ui + '-' + cls);
33122         }
33123     },
33124
33125     
33126     removeUIClsFromElement: function(cls, force) {
33127         var me = this;
33128
33129         me.callParent(arguments);
33130
33131         if (!force && me.rendered) {
33132             me.body.removeCls(me.baseCls + '-body-' + cls);
33133             me.body.removeCls(me.baseCls + '-body-' + me.ui + '-' + cls);
33134         }
33135     },
33136
33137     
33138     addUIToElement: function(force) {
33139         var me = this;
33140
33141         me.callParent(arguments);
33142
33143         if (!force && me.rendered) {
33144             me.body.addCls(me.baseCls + '-body-' + me.ui);
33145         }
33146
33147         if (!force && me.titleCmp && me.titleCmp.rendered && me.titleCmp.textEl) {
33148             me.titleCmp.textEl.addCls(me.baseCls + '-text-' + me.ui);
33149         }
33150     },
33151
33152     
33153     removeUIFromElement: function() {
33154         var me = this;
33155
33156         me.callParent(arguments);
33157
33158         if (me.rendered) {
33159             me.body.removeCls(me.baseCls + '-body-' + me.ui);
33160         }
33161
33162         if (me.titleCmp && me.titleCmp.rendered && me.titleCmp.textEl) {
33163             me.titleCmp.textEl.removeCls(me.baseCls + '-text-' + me.ui);
33164         }
33165     },
33166
33167     onClick: function(e) {
33168         if (!e.getTarget(Ext.baseCSSPrefix + 'tool')) {
33169             this.fireEvent('click', e);
33170         }
33171     },
33172
33173     getTargetEl: function() {
33174         return this.body || this.frameBody || this.el;
33175     },
33176
33177     
33178     setTitle: function(title) {
33179         var me = this;
33180         if (me.rendered) {
33181             if (me.titleCmp.rendered) {
33182                 if (me.titleCmp.surface) {
33183                     me.title = title || '';
33184                     var sprite = me.titleCmp.surface.items.items[0],
33185                         surface = me.titleCmp.surface;
33186
33187                     surface.remove(sprite);
33188                     me.textConfig.type = 'text';
33189                     me.textConfig.text = title;
33190                     sprite = surface.add(me.textConfig);
33191                     sprite.setAttributes({
33192                         rotate: {
33193                             degrees: 90
33194                         }
33195                     }, true);
33196                     me.titleCmp.autoSizeSurface();
33197                 } else {
33198                     me.title = title || '&#160;';
33199                     me.titleCmp.textEl.update(me.title);
33200                 }
33201             } else {
33202                 me.titleCmp.on({
33203                     render: function() {
33204                         me.setTitle(title);
33205                     },
33206                     single: true
33207                 });
33208             }
33209         } else {
33210             me.on({
33211                 render: function() {
33212                     me.layout.layout();
33213                     me.setTitle(title);
33214                 },
33215                 single: true
33216             });
33217         }
33218     },
33219
33220     
33221     setIconCls: function(cls) {
33222         this.iconCls = cls;
33223         if (!this.iconCmp) {
33224             this.initIconCmp();
33225             this.insert(0, this.iconCmp);
33226         }
33227         else {
33228             if (!cls || !cls.length) {
33229                 this.iconCmp.destroy();
33230             }
33231             else {
33232                 var iconCmp = this.iconCmp,
33233                     el      = iconCmp.iconEl;
33234
33235                 el.removeCls(iconCmp.iconCls);
33236                 el.addCls(cls);
33237                 iconCmp.iconCls = cls;
33238             }
33239         }
33240     },
33241
33242     
33243     addTool: function(tool) {
33244         this.tools.push(this.add(tool));
33245     },
33246
33247     
33248     onAdd: function(component, index) {
33249         this.callParent([arguments]);
33250         if (component instanceof Ext.panel.Tool) {
33251             component.bindTo(this.ownerCt);
33252             this.tools[component.type] = component;
33253         }
33254     }
33255 });
33256
33257
33258 Ext.define('Ext.fx.target.Element', {
33259
33260     
33261     
33262     extend: 'Ext.fx.target.Target',
33263     
33264     
33265
33266     type: 'element',
33267
33268     getElVal: function(el, attr, val) {
33269         if (val == undefined) {
33270             if (attr === 'x') {
33271                 val = el.getX();
33272             }
33273             else if (attr === 'y') {
33274                 val = el.getY();
33275             }
33276             else if (attr === 'scrollTop') {
33277                 val = el.getScroll().top;
33278             }
33279             else if (attr === 'scrollLeft') {
33280                 val = el.getScroll().left;
33281             }
33282             else if (attr === 'height') {
33283                 val = el.getHeight();
33284             }
33285             else if (attr === 'width') {
33286                 val = el.getWidth();
33287             }
33288             else {
33289                 val = el.getStyle(attr);
33290             }
33291         }
33292         return val;
33293     },
33294
33295     getAttr: function(attr, val) {
33296         var el = this.target;
33297         return [[ el, this.getElVal(el, attr, val)]];
33298     },
33299
33300     setAttr: function(targetData) {
33301         var target = this.target,
33302             ln = targetData.length,
33303             attrs, attr, o, i, j, ln2, element, value;
33304         for (i = 0; i < ln; i++) {
33305             attrs = targetData[i].attrs;
33306             for (attr in attrs) {
33307                 if (attrs.hasOwnProperty(attr)) {
33308                     ln2 = attrs[attr].length;
33309                     for (j = 0; j < ln2; j++) {
33310                         o = attrs[attr][j];
33311                         element = o[0];
33312                         value = o[1];
33313                         if (attr === 'x') {
33314                             element.setX(value);
33315                         }
33316                         else if (attr === 'y') {
33317                             element.setY(value);
33318                         }
33319                         else if (attr === 'scrollTop') {
33320                             element.scrollTo('top', value);
33321                         }
33322                         else if (attr === 'scrollLeft') {
33323                             element.scrollTo('left',value);
33324                         }
33325                         else {
33326                             element.setStyle(attr, value);
33327                         }
33328                     }
33329                 }
33330             }
33331         }
33332     }
33333 });
33334
33335
33336 Ext.define('Ext.fx.target.CompositeElement', {
33337
33338     
33339
33340     extend: 'Ext.fx.target.Element',
33341
33342     
33343
33344     isComposite: true,
33345     
33346     constructor: function(target) {
33347         target.id = target.id || Ext.id(null, 'ext-composite-');
33348         this.callParent([target]);
33349     },
33350
33351     getAttr: function(attr, val) {
33352         var out = [],
33353             target = this.target;
33354         target.each(function(el) {
33355             out.push([el, this.getElVal(el, attr, val)]);
33356         }, this);
33357         return out;
33358     }
33359 });
33360
33361
33362
33363 Ext.define('Ext.fx.Manager', {
33364
33365     
33366
33367     singleton: true,
33368
33369     requires: ['Ext.util.MixedCollection',
33370                'Ext.fx.target.Element',
33371                'Ext.fx.target.CompositeElement',
33372                'Ext.fx.target.Sprite',
33373                'Ext.fx.target.CompositeSprite',
33374                'Ext.fx.target.Component'],
33375
33376     mixins: {
33377         queue: 'Ext.fx.Queue'
33378     },
33379
33380     
33381
33382     constructor: function() {
33383         this.items = Ext.create('Ext.util.MixedCollection');
33384         this.mixins.queue.constructor.call(this);
33385
33386         
33387         
33388         
33389         
33390         
33391         
33392         
33393         
33394         
33395         
33396         
33397         
33398         
33399         
33400         
33401         
33402         
33403     },
33404
33405     
33406     interval: 16,
33407
33408     
33409     forceJS: true,
33410
33411     
33412     createTarget: function(target) {
33413         var me = this,
33414             useCSS3 = !me.forceJS && Ext.supports.Transitions,
33415             targetObj;
33416
33417         me.useCSS3 = useCSS3;
33418
33419         
33420         if (Ext.isString(target)) {
33421             target = Ext.get(target);
33422         }
33423         
33424         if (target && target.tagName) {
33425             target = Ext.get(target);
33426             targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
33427             me.targets.add(targetObj);
33428             return targetObj;
33429         }
33430         if (Ext.isObject(target)) {
33431             
33432             if (target.dom) {
33433                 targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
33434             }
33435             
33436             else if (target.isComposite) {
33437                 targetObj = Ext.create('Ext.fx.target.' + 'CompositeElement' + (useCSS3 ? 'CSS' : ''), target);
33438             }
33439             
33440             else if (target.isSprite) {
33441                 targetObj = Ext.create('Ext.fx.target.Sprite', target);
33442             }
33443             
33444             else if (target.isCompositeSprite) {
33445                 targetObj = Ext.create('Ext.fx.target.CompositeSprite', target);
33446             }
33447             
33448             else if (target.isComponent) {
33449                 targetObj = Ext.create('Ext.fx.target.Component', target);
33450             }
33451             else if (target.isAnimTarget) {
33452                 return target;
33453             }
33454             else {
33455                 return null;
33456             }
33457             me.targets.add(targetObj);
33458             return targetObj;
33459         }
33460         else {
33461             return null;
33462         }
33463     },
33464
33465     
33466     addAnim: function(anim) {
33467         var items = this.items,
33468             task = this.task;
33469         
33470         
33471         
33472         
33473         
33474         
33475         
33476         
33477         
33478         
33479         
33480         
33481
33482         items.add(anim);
33483
33484         
33485         if (!task && items.length) {
33486             task = this.task = {
33487                 run: this.runner,
33488                 interval: this.interval,
33489                 scope: this
33490             };
33491             Ext.TaskManager.start(task);
33492         }
33493
33494         
33495         
33496         
33497         
33498     },
33499
33500     
33501     removeAnim: function(anim) {
33502         
33503         var items = this.items,
33504             task = this.task;
33505         items.remove(anim);
33506         
33507         if (task && !items.length) {
33508             Ext.TaskManager.stop(task);
33509             delete this.task;
33510         }
33511     },
33512
33513     
33514     startingFilter: function(o) {
33515         return o.paused === false && o.running === false && o.iterations > 0;
33516     },
33517
33518     
33519     runningFilter: function(o) {
33520         return o.paused === false && o.running === true && o.isAnimator !== true;
33521     },
33522
33523     
33524     runner: function() {
33525         var me = this,
33526             items = me.items;
33527
33528         me.targetData = {};
33529         me.targetArr = {};
33530
33531         
33532         me.timestamp = new Date();
33533
33534         
33535         items.filterBy(me.startingFilter).each(me.startAnim, me);
33536
33537         
33538         items.filterBy(me.runningFilter).each(me.runAnim, me);
33539
33540         
33541         me.applyPendingAttrs();
33542     },
33543
33544     
33545     startAnim: function(anim) {
33546         anim.start(this.timestamp);
33547     },
33548
33549     
33550     runAnim: function(anim) {
33551         if (!anim) {
33552             return;
33553         }
33554         var me = this,
33555             targetId = anim.target.getId(),
33556             useCSS3 = me.useCSS3 && anim.target.type == 'element',
33557             elapsedTime = me.timestamp - anim.startTime,
33558             target, o;
33559
33560         this.collectTargetData(anim, elapsedTime, useCSS3);
33561
33562         
33563         
33564         if (useCSS3) {
33565             
33566             anim.target.setAttr(me.targetData[targetId], true);
33567
33568             
33569             me.targetData[targetId] = [];
33570             me.collectTargetData(anim, anim.duration, useCSS3);
33571
33572             
33573             anim.paused = true;
33574
33575             target = anim.target.target;
33576             
33577             if (anim.target.isComposite) {
33578                 target = anim.target.target.last();
33579             }
33580
33581             
33582             o = {};
33583             o[Ext.supports.CSS3TransitionEnd] = anim.lastFrame;
33584             o.scope = anim;
33585             o.single = true;
33586             target.on(o);
33587         }
33588         
33589         else if (elapsedTime >= anim.duration) {
33590             me.applyPendingAttrs(true);
33591             delete me.targetData[targetId];
33592             delete me.targetArr[targetId];
33593             anim.lastFrame();
33594         }
33595     },
33596
33597     
33598     collectTargetData: function(anim, elapsedTime, useCSS3) {
33599         var targetId = anim.target.getId(),
33600             targetData = this.targetData[targetId],
33601             data;
33602         
33603         if (!targetData) {
33604             targetData = this.targetData[targetId] = [];
33605             this.targetArr[targetId] = anim.target;
33606         }
33607
33608         data = {
33609             duration: anim.duration,
33610             easing: (useCSS3 && anim.reverse) ? anim.easingFn.reverse().toCSS3() : anim.easing,
33611             attrs: {}
33612         };
33613         Ext.apply(data.attrs, anim.runAnim(elapsedTime));
33614         targetData.push(data);
33615     },
33616
33617     
33618     applyPendingAttrs: function(isLastFrame) {
33619         var targetData = this.targetData,
33620             targetArr = this.targetArr,
33621             targetId;
33622         for (targetId in targetData) {
33623             if (targetData.hasOwnProperty(targetId)) {
33624                 targetArr[targetId].setAttr(targetData[targetId], false, isLastFrame);
33625             }
33626         }
33627     }
33628 });
33629
33630
33631 Ext.define('Ext.fx.Animator', {
33632
33633     
33634
33635     mixins: {
33636         observable: 'Ext.util.Observable'
33637     },
33638
33639     requires: ['Ext.fx.Manager'],
33640
33641     
33642
33643     isAnimator: true,
33644
33645     
33646     duration: 250,
33647
33648     
33649     delay: 0,
33650
33651     
33652     delayStart: 0,
33653
33654     
33655     dynamic: false,
33656
33657     
33658     easing: 'ease',
33659
33660     
33661     running: false,
33662
33663     
33664     paused: false,
33665
33666     
33667     damper: 1,
33668
33669     
33670     iterations: 1,
33671
33672     
33673     currentIteration: 0,
33674
33675     
33676     keyframeStep: 0,
33677
33678     
33679     animKeyFramesRE: /^(from|to|\d+%?)$/,
33680
33681     
33682
33683      
33684     constructor: function(config) {
33685         var me = this;
33686         config = Ext.apply(me, config || {});
33687         me.config = config;
33688         me.id = Ext.id(null, 'ext-animator-');
33689         me.addEvents(
33690             
33691             'beforeanimate',
33692             
33693             'keyframe',
33694             
33695             'afteranimate'
33696         );
33697         me.mixins.observable.constructor.call(me, config);
33698         me.timeline = [];
33699         me.createTimeline(me.keyframes);
33700         if (me.target) {
33701             me.applyAnimator(me.target);
33702             Ext.fx.Manager.addAnim(me);
33703         }
33704     },
33705
33706     
33707     sorter: function (a, b) {
33708         return a.pct - b.pct;
33709     },
33710
33711     
33712     createTimeline: function(keyframes) {
33713         var me = this,
33714             attrs = [],
33715             to = me.to || {},
33716             duration = me.duration,
33717             prevMs, ms, i, ln, pct, anim, nextAnim, attr;
33718
33719         for (pct in keyframes) {
33720             if (keyframes.hasOwnProperty(pct) && me.animKeyFramesRE.test(pct)) {
33721                 attr = {attrs: Ext.apply(keyframes[pct], to)};
33722                 
33723                 if (pct == "from") {
33724                     pct = 0;
33725                 }
33726                 else if (pct == "to") {
33727                     pct = 100;
33728                 }
33729                 
33730                 attr.pct = parseInt(pct, 10);
33731                 attrs.push(attr);
33732             }
33733         }
33734         
33735         Ext.Array.sort(attrs, me.sorter);
33736         
33737         
33738         
33739         
33740
33741         ln = attrs.length;
33742         for (i = 0; i < ln; i++) {
33743             prevMs = (attrs[i - 1]) ? duration * (attrs[i - 1].pct / 100) : 0;
33744             ms = duration * (attrs[i].pct / 100);
33745             me.timeline.push({
33746                 duration: ms - prevMs,
33747                 attrs: attrs[i].attrs
33748             });
33749         }
33750     },
33751
33752     
33753     applyAnimator: function(target) {
33754         var me = this,
33755             anims = [],
33756             timeline = me.timeline,
33757             reverse = me.reverse,
33758             ln = timeline.length,
33759             anim, easing, damper, initial, attrs, lastAttrs, i;
33760
33761         if (me.fireEvent('beforeanimate', me) !== false) {
33762             for (i = 0; i < ln; i++) {
33763                 anim = timeline[i];
33764                 attrs = anim.attrs;
33765                 easing = attrs.easing || me.easing;
33766                 damper = attrs.damper || me.damper;
33767                 delete attrs.easing;
33768                 delete attrs.damper;
33769                 anim = Ext.create('Ext.fx.Anim', {
33770                     target: target,
33771                     easing: easing,
33772                     damper: damper,
33773                     duration: anim.duration,
33774                     paused: true,
33775                     to: attrs
33776                 });
33777                 anims.push(anim);
33778             }
33779             me.animations = anims;
33780             me.target = anim.target;
33781             for (i = 0; i < ln - 1; i++) {
33782                 anim = anims[i];
33783                 anim.nextAnim = anims[i + 1];
33784                 anim.on('afteranimate', function() {
33785                     this.nextAnim.paused = false;
33786                 });
33787                 anim.on('afteranimate', function() {
33788                     this.fireEvent('keyframe', this, ++this.keyframeStep);
33789                 }, me);
33790             }
33791             anims[ln - 1].on('afteranimate', function() {
33792                 this.lastFrame();
33793             }, me);
33794         }
33795     },
33796
33797     
33798     start: function(startTime) {
33799         var me = this,
33800             delay = me.delay,
33801             delayStart = me.delayStart,
33802             delayDelta;
33803         if (delay) {
33804             if (!delayStart) {
33805                 me.delayStart = startTime;
33806                 return;
33807             }
33808             else {
33809                 delayDelta = startTime - delayStart;
33810                 if (delayDelta < delay) {
33811                     return;
33812                 }
33813                 else {
33814                     
33815                     startTime = new Date(delayStart.getTime() + delay);
33816                 }
33817             }
33818         }
33819         if (me.fireEvent('beforeanimate', me) !== false) {
33820             me.startTime = startTime;
33821             me.running = true;
33822             me.animations[me.keyframeStep].paused = false;
33823         }
33824     },
33825
33826     
33827     lastFrame: function() {
33828         var me = this,
33829             iter = me.iterations,
33830             iterCount = me.currentIteration;
33831
33832         iterCount++;
33833         if (iterCount < iter) {
33834             me.startTime = new Date();
33835             me.currentIteration = iterCount;
33836             me.keyframeStep = 0;
33837             me.applyAnimator(me.target);
33838             me.animations[me.keyframeStep].paused = false;
33839         }
33840         else {
33841             me.currentIteration = 0;
33842             me.end();
33843         }
33844     },
33845
33846     
33847     end: function() {
33848         var me = this;
33849         me.fireEvent('afteranimate', me, me.startTime, new Date() - me.startTime);
33850     }
33851 });
33852
33853 Ext.ns('Ext.fx');
33854
33855 Ext.require('Ext.fx.CubicBezier', function() {
33856     var math = Math,
33857         pi = math.PI,
33858         pow = math.pow,
33859         sin = math.sin,
33860         sqrt = math.sqrt,
33861         abs = math.abs,
33862         backInSeed = 1.70158;
33863     Ext.fx.Easing = {
33864         
33865         
33866         
33867         
33868         
33869         
33870         
33871         
33872     };
33873
33874     Ext.apply(Ext.fx.Easing, {
33875         linear: function(n) {
33876             return n;
33877         },
33878         ease: function(n) {
33879             var q = 0.07813 - n / 2,
33880                 alpha = -0.25,
33881                 Q = sqrt(0.0066 + q * q),
33882                 x = Q - q,
33883                 X = pow(abs(x), 1/3) * (x < 0 ? -1 : 1),
33884                 y = -Q - q,
33885                 Y = pow(abs(y), 1/3) * (y < 0 ? -1 : 1),
33886                 t = X + Y + 0.25;
33887             return pow(1 - t, 2) * 3 * t * 0.1 + (1 - t) * 3 * t * t + t * t * t;
33888         },
33889         easeIn: function (n) {
33890             return pow(n, 1.7);
33891         },
33892         easeOut: function (n) {
33893             return pow(n, 0.48);
33894         },
33895         easeInOut: function(n) {
33896             var q = 0.48 - n / 1.04,
33897                 Q = sqrt(0.1734 + q * q),
33898                 x = Q - q,
33899                 X = pow(abs(x), 1/3) * (x < 0 ? -1 : 1),
33900                 y = -Q - q,
33901                 Y = pow(abs(y), 1/3) * (y < 0 ? -1 : 1),
33902                 t = X + Y + 0.5;
33903             return (1 - t) * 3 * t * t + t * t * t;
33904         },
33905         backIn: function (n) {
33906             return n * n * ((backInSeed + 1) * n - backInSeed);
33907         },
33908         backOut: function (n) {
33909             n = n - 1;
33910             return n * n * ((backInSeed + 1) * n + backInSeed) + 1;
33911         },
33912         elasticIn: function (n) {
33913             if (n === 0 || n === 1) {
33914                 return n;
33915             }
33916             var p = 0.3,
33917                 s = p / 4;
33918             return pow(2, -10 * n) * sin((n - s) * (2 * pi) / p) + 1;
33919         },
33920         elasticOut: function (n) {
33921             return 1 - Ext.fx.Easing.elasticIn(1 - n);
33922         },
33923         bounceIn: function (n) {
33924             return 1 - Ext.fx.Easing.bounceOut(1 - n);
33925         },
33926         bounceOut: function (n) {
33927             var s = 7.5625,
33928                 p = 2.75,
33929                 l;
33930             if (n < (1 / p)) {
33931                 l = s * n * n;
33932             } else {
33933                 if (n < (2 / p)) {
33934                     n -= (1.5 / p);
33935                     l = s * n * n + 0.75;
33936                 } else {
33937                     if (n < (2.5 / p)) {
33938                         n -= (2.25 / p);
33939                         l = s * n * n + 0.9375;
33940                     } else {
33941                         n -= (2.625 / p);
33942                         l = s * n * n + 0.984375;
33943                     }
33944                 }
33945             }
33946             return l;
33947         }
33948     });
33949     Ext.apply(Ext.fx.Easing, {
33950         'back-in': Ext.fx.Easing.backIn,
33951         'back-out': Ext.fx.Easing.backOut,
33952         'ease-in': Ext.fx.Easing.easeIn,
33953         'ease-out': Ext.fx.Easing.easeOut,
33954         'elastic-in': Ext.fx.Easing.elasticIn,
33955         'elastic-out': Ext.fx.Easing.elasticIn,
33956         'bounce-in': Ext.fx.Easing.bounceIn,
33957         'bounce-out': Ext.fx.Easing.bounceOut,
33958         'ease-in-out': Ext.fx.Easing.easeInOut
33959     });
33960 });
33961
33962
33963 Ext.define('Ext.draw.Draw', {
33964     
33965
33966     singleton: true,
33967
33968     requires: ['Ext.draw.Color'],
33969
33970     
33971
33972     pathToStringRE: /,?([achlmqrstvxz]),?/gi,
33973     pathCommandRE: /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,
33974     pathValuesRE: /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,
33975     stopsRE: /^(\d+%?)$/,
33976     radian: Math.PI / 180,
33977
33978     availableAnimAttrs: {
33979         along: "along",
33980         blur: null,
33981         "clip-rect": "csv",
33982         cx: null,
33983         cy: null,
33984         fill: "color",
33985         "fill-opacity": null,
33986         "font-size": null,
33987         height: null,
33988         opacity: null,
33989         path: "path",
33990         r: null,
33991         rotation: "csv",
33992         rx: null,
33993         ry: null,
33994         scale: "csv",
33995         stroke: "color",
33996         "stroke-opacity": null,
33997         "stroke-width": null,
33998         translation: "csv",
33999         width: null,
34000         x: null,
34001         y: null
34002     },
34003
34004     is: function(o, type) {
34005         type = String(type).toLowerCase();
34006         return (type == "object" && o === Object(o)) ||
34007             (type == "undefined" && typeof o == type) ||
34008             (type == "null" && o === null) ||
34009             (type == "array" && Array.isArray && Array.isArray(o)) ||
34010             (Object.prototype.toString.call(o).toLowerCase().slice(8, -1)) == type;
34011     },
34012
34013     ellipsePath: function(sprite) {
34014         var attr = sprite.attr;
34015         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);
34016     },
34017
34018     rectPath: function(sprite) {
34019         var attr = sprite.attr;
34020         if (attr.radius) {
34021             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);
34022         }
34023         else {
34024             return Ext.String.format("M{0},{1}l{2},0,0,{3},{4},0z", attr.x, attr.y, attr.width, attr.height, -attr.width);
34025         }
34026     },
34027
34028     
34029     path2string: function () {
34030         return this.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1");
34031     },
34032
34033     
34034     pathToString: function(arrayPath) {
34035         return arrayPath.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1");
34036     },
34037
34038     parsePathString: function (pathString) {
34039         if (!pathString) {
34040             return null;
34041         }
34042         var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0},
34043             data = [],
34044             me = this;
34045         if (me.is(pathString, "array") && me.is(pathString[0], "array")) { 
34046             data = me.pathClone(pathString);
34047         }
34048         if (!data.length) {
34049             String(pathString).replace(me.pathCommandRE, function (a, b, c) {
34050                 var params = [],
34051                     name = b.toLowerCase();
34052                 c.replace(me.pathValuesRE, function (a, b) {
34053                     b && params.push(+b);
34054                 });
34055                 if (name == "m" && params.length > 2) {
34056                     data.push([b].concat(params.splice(0, 2)));
34057                     name = "l";
34058                     b = (b == "m") ? "l" : "L";
34059                 }
34060                 while (params.length >= paramCounts[name]) {
34061                     data.push([b].concat(params.splice(0, paramCounts[name])));
34062                     if (!paramCounts[name]) {
34063                         break;
34064                     }
34065                 }
34066             });
34067         }
34068         data.toString = me.path2string;
34069         return data;
34070     },
34071
34072     mapPath: function (path, matrix) {
34073         if (!matrix) {
34074             return path;
34075         }
34076         var x, y, i, ii, j, jj, pathi;
34077         path = this.path2curve(path);
34078         for (i = 0, ii = path.length; i < ii; i++) {
34079             pathi = path[i];
34080             for (j = 1, jj = pathi.length; j < jj-1; j += 2) {
34081                 x = matrix.x(pathi[j], pathi[j + 1]);
34082                 y = matrix.y(pathi[j], pathi[j + 1]);
34083                 pathi[j] = x;
34084                 pathi[j + 1] = y;
34085             }
34086         }
34087         return path;
34088     },
34089
34090     pathClone: function(pathArray) {
34091         var res = [],
34092             j, jj, i, ii;
34093         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { 
34094             pathArray = this.parsePathString(pathArray);
34095         }
34096         for (i = 0, ii = pathArray.length; i < ii; i++) {
34097             res[i] = [];
34098             for (j = 0, jj = pathArray[i].length; j < jj; j++) {
34099                 res[i][j] = pathArray[i][j];
34100             }
34101         }
34102         res.toString = this.path2string;
34103         return res;
34104     },
34105
34106     pathToAbsolute: function (pathArray) {
34107         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { 
34108             pathArray = this.parsePathString(pathArray);
34109         }
34110         var res = [],
34111             x = 0,
34112             y = 0,
34113             mx = 0,
34114             my = 0,
34115             i = 0,
34116             ln = pathArray.length,
34117             r, pathSegment, j, ln2;
34118         
34119         if (ln && pathArray[0][0] == "M") {
34120             x = +pathArray[0][1];
34121             y = +pathArray[0][2];
34122             mx = x;
34123             my = y;
34124             i++;
34125             res[0] = ["M", x, y];
34126         }
34127         for (; i < ln; i++) {
34128             r = res[i] = [];
34129             pathSegment = pathArray[i];
34130             if (pathSegment[0] != pathSegment[0].toUpperCase()) {
34131                 r[0] = pathSegment[0].toUpperCase();
34132                 switch (r[0]) {
34133                     
34134                     case "A":
34135                         r[1] = pathSegment[1];
34136                         r[2] = pathSegment[2];
34137                         r[3] = pathSegment[3];
34138                         r[4] = pathSegment[4];
34139                         r[5] = pathSegment[5];
34140                         r[6] = +(pathSegment[6] + x);
34141                         r[7] = +(pathSegment[7] + y);
34142                         break;
34143                     
34144                     case "V":
34145                         r[1] = +pathSegment[1] + y;
34146                         break;
34147                     
34148                     case "H":
34149                         r[1] = +pathSegment[1] + x;
34150                         break;
34151                     case "M":
34152                     
34153                         mx = +pathSegment[1] + x;
34154                         my = +pathSegment[2] + y;
34155                     default:
34156                         j = 1;
34157                         ln2 = pathSegment.length;
34158                         for (; j < ln2; j++) {
34159                             r[j] = +pathSegment[j] + ((j % 2) ? x : y);
34160                         }
34161                 }
34162             }
34163             else {
34164                 j = 0;
34165                 ln2 = pathSegment.length;
34166                 for (; j < ln2; j++) {
34167                     res[i][j] = pathSegment[j];
34168                 }
34169             }
34170             switch (r[0]) {
34171                 
34172                 case "Z":
34173                     x = mx;
34174                     y = my;
34175                     break;
34176                 
34177                 case "H":
34178                     x = r[1];
34179                     break;
34180                 
34181                 case "V":
34182                     y = r[1];
34183                     break;
34184                 
34185                 case "M":
34186                     pathSegment = res[i];
34187                     ln2 = pathSegment.length;
34188                     mx = pathSegment[ln2 - 2];
34189                     my = pathSegment[ln2 - 1];
34190                 default:
34191                     pathSegment = res[i];
34192                     ln2 = pathSegment.length;
34193                     x = pathSegment[ln2 - 2];
34194                     y = pathSegment[ln2 - 1];
34195             }
34196         }
34197         res.toString = this.path2string;
34198         return res;
34199     },
34200
34201     
34202     pathToRelative: function (pathArray) {
34203         if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) {
34204             pathArray = this.parsePathString(pathArray);
34205         }
34206         var res = [],
34207             x = 0,
34208             y = 0,
34209             mx = 0,
34210             my = 0,
34211             start = 0;
34212         if (pathArray[0][0] == "M") {
34213             x = pathArray[0][1];
34214             y = pathArray[0][2];
34215             mx = x;
34216             my = y;
34217             start++;
34218             res.push(["M", x, y]);
34219         }
34220         for (var i = start, ii = pathArray.length; i < ii; i++) {
34221             var r = res[i] = [],
34222                 pa = pathArray[i];
34223             if (pa[0] != pa[0].toLowerCase()) {
34224                 r[0] = pa[0].toLowerCase();
34225                 switch (r[0]) {
34226                     case "a":
34227                         r[1] = pa[1];
34228                         r[2] = pa[2];
34229                         r[3] = pa[3];
34230                         r[4] = pa[4];
34231                         r[5] = pa[5];
34232                         r[6] = +(pa[6] - x).toFixed(3);
34233                         r[7] = +(pa[7] - y).toFixed(3);
34234                         break;
34235                     case "v":
34236                         r[1] = +(pa[1] - y).toFixed(3);
34237                         break;
34238                     case "m":
34239                         mx = pa[1];
34240                         my = pa[2];
34241                     default:
34242                         for (var j = 1, jj = pa.length; j < jj; j++) {
34243                             r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
34244                         }
34245                 }
34246             } else {
34247                 r = res[i] = [];
34248                 if (pa[0] == "m") {
34249                     mx = pa[1] + x;
34250                     my = pa[2] + y;
34251                 }
34252                 for (var k = 0, kk = pa.length; k < kk; k++) {
34253                     res[i][k] = pa[k];
34254                 }
34255             }
34256             var len = res[i].length;
34257             switch (res[i][0]) {
34258                 case "z":
34259                     x = mx;
34260                     y = my;
34261                     break;
34262                 case "h":
34263                     x += +res[i][len - 1];
34264                     break;
34265                 case "v":
34266                     y += +res[i][len - 1];
34267                     break;
34268                 default:
34269                     x += +res[i][len - 2];
34270                     y += +res[i][len - 1];
34271             }
34272         }
34273         res.toString = this.path2string;
34274         return res;
34275     },
34276
34277     
34278     path2curve: function (path) {
34279         var me = this,
34280             points = me.pathToAbsolute(path),
34281             ln = points.length,
34282             attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
34283             i, seg, segLn, point;
34284             
34285         for (i = 0; i < ln; i++) {
34286             points[i] = me.command2curve(points[i], attrs);
34287             if (points[i].length > 7) {
34288                     points[i].shift();
34289                     point = points[i];
34290                     while (point.length) {
34291                         points.splice(i++, 0, ["C"].concat(point.splice(0, 6)));
34292                     }
34293                     points.splice(i, 1);
34294                     ln = points.length;
34295                 }
34296             seg = points[i];
34297             segLn = seg.length;
34298             attrs.x = seg[segLn - 2];
34299             attrs.y = seg[segLn - 1];
34300             attrs.bx = parseFloat(seg[segLn - 4]) || attrs.x;
34301             attrs.by = parseFloat(seg[segLn - 3]) || attrs.y;
34302         }
34303         return points;
34304     },
34305     
34306     interpolatePaths: function (path, path2) {
34307         var me = this,
34308             p = me.pathToAbsolute(path),
34309             p2 = me.pathToAbsolute(path2),
34310             attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
34311             attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
34312             fixArc = function (pp, i) {
34313                 if (pp[i].length > 7) {
34314                     pp[i].shift();
34315                     var pi = pp[i];
34316                     while (pi.length) {
34317                         pp.splice(i++, 0, ["C"].concat(pi.splice(0, 6)));
34318                     }
34319                     pp.splice(i, 1);
34320                     ii = Math.max(p.length, p2.length || 0);
34321                 }
34322             },
34323             fixM = function (path1, path2, a1, a2, i) {
34324                 if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
34325                     path2.splice(i, 0, ["M", a2.x, a2.y]);
34326                     a1.bx = 0;
34327                     a1.by = 0;
34328                     a1.x = path1[i][1];
34329                     a1.y = path1[i][2];
34330                     ii = Math.max(p.length, p2.length || 0);
34331                 }
34332             };
34333         for (var i = 0, ii = Math.max(p.length, p2.length || 0); i < ii; i++) {
34334             p[i] = me.command2curve(p[i], attrs);
34335             fixArc(p, i);
34336             (p2[i] = me.command2curve(p2[i], attrs2));
34337             fixArc(p2, i);
34338             fixM(p, p2, attrs, attrs2, i);
34339             fixM(p2, p, attrs2, attrs, i);
34340             var seg = p[i],
34341                 seg2 = p2[i],
34342                 seglen = seg.length,
34343                 seg2len = seg2.length;
34344             attrs.x = seg[seglen - 2];
34345             attrs.y = seg[seglen - 1];
34346             attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x;
34347             attrs.by = parseFloat(seg[seglen - 3]) || attrs.y;
34348             attrs2.bx = (parseFloat(seg2[seg2len - 4]) || attrs2.x);
34349             attrs2.by = (parseFloat(seg2[seg2len - 3]) || attrs2.y);
34350             attrs2.x = seg2[seg2len - 2];
34351             attrs2.y = seg2[seg2len - 1];
34352         }
34353         return [p, p2];
34354     },
34355     
34356     
34357     command2curve: function (pathCommand, d) {
34358         var me = this;
34359         if (!pathCommand) {
34360             return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
34361         }
34362         if (pathCommand[0] != "T" && pathCommand[0] != "Q") {
34363             d.qx = d.qy = null;
34364         }
34365         switch (pathCommand[0]) {
34366             case "M":
34367                 d.X = pathCommand[1];
34368                 d.Y = pathCommand[2];
34369                 break;
34370             case "A":
34371                 pathCommand = ["C"].concat(me.arc2curve.apply(me, [d.x, d.y].concat(pathCommand.slice(1))));
34372                 break;
34373             case "S":
34374                 pathCommand = ["C", d.x + (d.x - (d.bx || d.x)), d.y + (d.y - (d.by || d.y))].concat(pathCommand.slice(1));
34375                 break;
34376             case "T":
34377                 d.qx = d.x + (d.x - (d.qx || d.x));
34378                 d.qy = d.y + (d.y - (d.qy || d.y));
34379                 pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, d.qx, d.qy, pathCommand[1], pathCommand[2]));
34380                 break;
34381             case "Q":
34382                 d.qx = pathCommand[1];
34383                 d.qy = pathCommand[2];
34384                 pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[3], pathCommand[4]));
34385                 break;
34386             case "L":
34387                 pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[1], pathCommand[2]);
34388                 break;
34389             case "H":
34390                 pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], d.y, pathCommand[1], d.y);
34391                 break;
34392             case "V":
34393                 pathCommand = ["C"].concat(d.x, d.y, d.x, pathCommand[1], d.x, pathCommand[1]);
34394                 break;
34395             case "Z":
34396                 pathCommand = ["C"].concat(d.x, d.y, d.X, d.Y, d.X, d.Y);
34397                 break;
34398         }
34399         return pathCommand;
34400     },
34401
34402     quadratic2curve: function (x1, y1, ax, ay, x2, y2) {
34403         var _13 = 1 / 3,
34404             _23 = 2 / 3;
34405         return [
34406                 _13 * x1 + _23 * ax,
34407                 _13 * y1 + _23 * ay,
34408                 _13 * x2 + _23 * ax,
34409                 _13 * y2 + _23 * ay,
34410                 x2,
34411                 y2
34412             ];
34413     },
34414     
34415     rotate: function (x, y, rad) {
34416         var cos = Math.cos(rad),
34417             sin = Math.sin(rad),
34418             X = x * cos - y * sin,
34419             Y = x * sin + y * cos;
34420         return {x: X, y: Y};
34421     },
34422
34423     arc2curve: function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
34424         
34425         
34426         var me = this,
34427             PI = Math.PI,
34428             radian = me.radian,
34429             _120 = PI * 120 / 180,
34430             rad = radian * (+angle || 0),
34431             res = [],
34432             math = Math,
34433             mcos = math.cos,
34434             msin = math.sin,
34435             msqrt = math.sqrt,
34436             mabs = math.abs,
34437             masin = math.asin,
34438             xy, cos, sin, x, y, h, rx2, ry2, k, cx, cy, f1, f2, df, c1, s1, c2, s2,
34439             t, hx, hy, m1, m2, m3, m4, newres, i, ln, f2old, x2old, y2old;
34440         if (!recursive) {
34441             xy = me.rotate(x1, y1, -rad);
34442             x1 = xy.x;
34443             y1 = xy.y;
34444             xy = me.rotate(x2, y2, -rad);
34445             x2 = xy.x;
34446             y2 = xy.y;
34447             cos = mcos(radian * angle);
34448             sin = msin(radian * angle);
34449             x = (x1 - x2) / 2;
34450             y = (y1 - y2) / 2;
34451             h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
34452             if (h > 1) {
34453                 h = msqrt(h);
34454                 rx = h * rx;
34455                 ry = h * ry;
34456             }
34457             rx2 = rx * rx;
34458             ry2 = ry * ry;
34459             k = (large_arc_flag == sweep_flag ? -1 : 1) *
34460                     msqrt(mabs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x)));
34461             cx = k * rx * y / ry + (x1 + x2) / 2;
34462             cy = k * -ry * x / rx + (y1 + y2) / 2;
34463             f1 = masin(((y1 - cy) / ry).toFixed(7));
34464             f2 = masin(((y2 - cy) / ry).toFixed(7));
34465
34466             f1 = x1 < cx ? PI - f1 : f1;
34467             f2 = x2 < cx ? PI - f2 : f2;
34468             if (f1 < 0) {
34469                 f1 = PI * 2 + f1;
34470             }
34471             if (f2 < 0) {
34472                 f2 = PI * 2 + f2;
34473             }
34474             if (sweep_flag && f1 > f2) {
34475                 f1 = f1 - PI * 2;
34476             }
34477             if (!sweep_flag && f2 > f1) {
34478                 f2 = f2 - PI * 2;
34479             }
34480         }
34481         else {
34482             f1 = recursive[0];
34483             f2 = recursive[1];
34484             cx = recursive[2];
34485             cy = recursive[3];
34486         }
34487         df = f2 - f1;
34488         if (mabs(df) > _120) {
34489             f2old = f2;
34490             x2old = x2;
34491             y2old = y2;
34492             f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
34493             x2 = cx + rx * mcos(f2);
34494             y2 = cy + ry * msin(f2);
34495             res = me.arc2curve(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
34496         }
34497         df = f2 - f1;
34498         c1 = mcos(f1);
34499         s1 = msin(f1);
34500         c2 = mcos(f2);
34501         s2 = msin(f2);
34502         t = math.tan(df / 4);
34503         hx = 4 / 3 * rx * t;
34504         hy = 4 / 3 * ry * t;
34505         m1 = [x1, y1];
34506         m2 = [x1 + hx * s1, y1 - hy * c1];
34507         m3 = [x2 + hx * s2, y2 - hy * c2];
34508         m4 = [x2, y2];
34509         m2[0] = 2 * m1[0] - m2[0];
34510         m2[1] = 2 * m1[1] - m2[1];
34511         if (recursive) {
34512             return [m2, m3, m4].concat(res);
34513         }
34514         else {
34515             res = [m2, m3, m4].concat(res).join().split(",");
34516             newres = [];
34517             ln = res.length;
34518             for (i = 0;  i < ln; i++) {
34519                 newres[i] = i % 2 ? me.rotate(res[i - 1], res[i], rad).y : me.rotate(res[i], res[i + 1], rad).x;
34520             }
34521             return newres;
34522         }
34523     },
34524
34525     
34526     rotateAndTranslatePath: function (sprite) {
34527         var alpha = sprite.rotation.degrees,
34528             cx = sprite.rotation.x,
34529             cy = sprite.rotation.y,
34530             dx = sprite.translation.x,
34531             dy = sprite.translation.y,
34532             path,
34533             i,
34534             p,
34535             xy,
34536             j,
34537             res = [];
34538         if (!alpha && !dx && !dy) {
34539             return this.pathToAbsolute(sprite.attr.path);
34540         }
34541         dx = dx || 0;
34542         dy = dy || 0;
34543         path = this.pathToAbsolute(sprite.attr.path);
34544         for (i = path.length; i--;) {
34545             p = res[i] = path[i].slice();
34546             if (p[0] == "A") {
34547                 xy = this.rotatePoint(p[6], p[7], alpha, cx, cy);
34548                 p[6] = xy.x + dx;
34549                 p[7] = xy.y + dy;
34550             } else {
34551                 j = 1;
34552                 while (p[j + 1] != null) {
34553                     xy = this.rotatePoint(p[j], p[j + 1], alpha, cx, cy);
34554                     p[j] = xy.x + dx;
34555                     p[j + 1] = xy.y + dy;
34556                     j += 2;
34557                 }
34558             }
34559         }
34560         return res;
34561     },
34562
34563     
34564     rotatePoint: function (x, y, alpha, cx, cy) {
34565         if (!alpha) {
34566             return {
34567                 x: x,
34568                 y: y
34569             };
34570         }
34571         cx = cx || 0;
34572         cy = cy || 0;
34573         x = x - cx;
34574         y = y - cy;
34575         alpha = alpha * this.radian;
34576         var cos = Math.cos(alpha),
34577             sin = Math.sin(alpha);
34578         return {
34579             x: x * cos - y * sin + cx,
34580             y: x * sin + y * cos + cy
34581         };
34582     },
34583
34584     pathDimensions: function (path) {
34585         if (!path || !(path + "")) {
34586             return {x: 0, y: 0, width: 0, height: 0};
34587         }
34588         path = this.path2curve(path);
34589         var x = 0, 
34590             y = 0,
34591             X = [],
34592             Y = [],
34593             i = 0,
34594             ln = path.length,
34595             p, xmin, ymin, dim;
34596         for (; i < ln; i++) {
34597             p = path[i];
34598             if (p[0] == "M") {
34599                 x = p[1];
34600                 y = p[2];
34601                 X.push(x);
34602                 Y.push(y);
34603             }
34604             else {
34605                 dim = this.curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
34606                 X = X.concat(dim.min.x, dim.max.x);
34607                 Y = Y.concat(dim.min.y, dim.max.y);
34608                 x = p[5];
34609                 y = p[6];
34610             }
34611         }
34612         xmin = Math.min.apply(0, X);
34613         ymin = Math.min.apply(0, Y);
34614         return {
34615             x: xmin,
34616             y: ymin,
34617             path: path,
34618             width: Math.max.apply(0, X) - xmin,
34619             height: Math.max.apply(0, Y) - ymin
34620         };
34621     },
34622
34623     intersectInside: function(path, cp1, cp2) {
34624         return (cp2[0] - cp1[0]) * (path[1] - cp1[1]) > (cp2[1] - cp1[1]) * (path[0] - cp1[0]);
34625     },
34626
34627     intersectIntersection: function(s, e, cp1, cp2) {
34628         var p = [],
34629             dcx = cp1[0] - cp2[0],
34630             dcy = cp1[1] - cp2[1],
34631             dpx = s[0] - e[0],
34632             dpy = s[1] - e[1],
34633             n1 = cp1[0] * cp2[1] - cp1[1] * cp2[0],
34634             n2 = s[0] * e[1] - s[1] * e[0],
34635             n3 = 1 / (dcx * dpy - dcy * dpx);
34636
34637         p[0] = (n1 * dpx - n2 * dcx) * n3;
34638         p[1] = (n1 * dpy - n2 * dcy) * n3;
34639         return p;
34640     },
34641
34642     intersect: function(subjectPolygon, clipPolygon) {
34643         var me = this,
34644             i = 0,
34645             ln = clipPolygon.length,
34646             cp1 = clipPolygon[ln - 1],
34647             outputList = subjectPolygon,
34648             cp2, s, e, point, ln2, inputList, j;
34649         for (; i < ln; ++i) {
34650             cp2 = clipPolygon[i];
34651             inputList = outputList;
34652             outputList = [];
34653             s = inputList[inputList.length - 1];
34654             j = 0;
34655             ln2 = inputList.length;
34656             for (; j < ln2; j++) {
34657                 e = inputList[j];
34658                 if (me.intersectInside(e, cp1, cp2)) {
34659                     if (!me.intersectInside(s, cp1, cp2)) {
34660                         outputList.push(me.intersectIntersection(s, e, cp1, cp2));
34661                     }
34662                     outputList.push(e);
34663                 }
34664                 else if (me.intersectInside(s, cp1, cp2)) {
34665                     outputList.push(me.intersectIntersection(s, e, cp1, cp2));
34666                 }
34667                 s = e;
34668             }
34669             cp1 = cp2;
34670         }
34671         return outputList;
34672     },
34673
34674     curveDim: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
34675         var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
34676             b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
34677             c = p1x - c1x,
34678             t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a,
34679             t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a,
34680             y = [p1y, p2y],
34681             x = [p1x, p2x],
34682             dot;
34683         if (Math.abs(t1) > 1e12) {
34684             t1 = 0.5;
34685         }
34686         if (Math.abs(t2) > 1e12) {
34687             t2 = 0.5;
34688         }
34689         if (t1 > 0 && t1 < 1) {
34690             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
34691             x.push(dot.x);
34692             y.push(dot.y);
34693         }
34694         if (t2 > 0 && t2 < 1) {
34695             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
34696             x.push(dot.x);
34697             y.push(dot.y);
34698         }
34699         a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
34700         b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
34701         c = p1y - c1y;
34702         t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a;
34703         t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
34704         if (Math.abs(t1) > 1e12) {
34705             t1 = 0.5;
34706         }
34707         if (Math.abs(t2) > 1e12) {
34708             t2 = 0.5;
34709         }
34710         if (t1 > 0 && t1 < 1) {
34711             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
34712             x.push(dot.x);
34713             y.push(dot.y);
34714         }
34715         if (t2 > 0 && t2 < 1) {
34716             dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
34717             x.push(dot.x);
34718             y.push(dot.y);
34719         }
34720         return {
34721             min: {x: Math.min.apply(0, x), y: Math.min.apply(0, y)},
34722             max: {x: Math.max.apply(0, x), y: Math.max.apply(0, y)}
34723         };
34724     },
34725
34726     getAnchors: function (p1x, p1y, p2x, p2y, p3x, p3y, value) {
34727         value = value || 4;
34728         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),
34729             a = Math.atan((p2x - p1x) / Math.abs(p2y - p1y)),
34730             b = Math.atan((p3x - p2x) / Math.abs(p2y - p3y)),
34731             pi = Math.PI;
34732         a = p1y < p2y ? pi - a : a;
34733         b = p3y < p2y ? pi - b : b;
34734         var alpha = pi / 2 - ((a + b) % (pi * 2)) / 2;
34735         alpha > pi / 2 && (alpha -= pi);
34736         var dx1 = l * Math.sin(alpha + a),
34737             dy1 = l * Math.cos(alpha + a),
34738             dx2 = l * Math.sin(alpha + b),
34739             dy2 = l * Math.cos(alpha + b),
34740             out = {
34741                 x1: p2x - dx1,
34742                 y1: p2y + dy1,
34743                 x2: p2x + dx2,
34744                 y2: p2y + dy2
34745             };
34746         return out;
34747     },
34748
34749     
34750     smooth: function (originalPath, value) {
34751         var path = this.path2curve(originalPath),
34752             newp = [path[0]],
34753             x = path[0][1],
34754             y = path[0][2],
34755             j,
34756             points,
34757             i = 1,
34758             ii = path.length,
34759             beg = 1,
34760             mx = x,
34761             my = y,
34762             cx = 0,
34763             cy = 0;
34764         for (; i < ii; i++) {
34765             var pathi = path[i],
34766                 pathil = pathi.length,
34767                 pathim = path[i - 1],
34768                 pathiml = pathim.length,
34769                 pathip = path[i + 1],
34770                 pathipl = pathip && pathip.length;
34771             if (pathi[0] == "M") {
34772                 mx = pathi[1];
34773                 my = pathi[2];
34774                 j = i + 1;
34775                 while (path[j][0] != "C") {
34776                     j++;
34777                 }
34778                 cx = path[j][5];
34779                 cy = path[j][6];
34780                 newp.push(["M", mx, my]);
34781                 beg = newp.length;
34782                 x = mx;
34783                 y = my;
34784                 continue;
34785             }
34786             if (pathi[pathil - 2] == mx && pathi[pathil - 1] == my && (!pathip || pathip[0] == "M")) {
34787                 var begl = newp[beg].length;
34788                 points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], mx, my, newp[beg][begl - 2], newp[beg][begl - 1], value);
34789                 newp[beg][1] = points.x2;
34790                 newp[beg][2] = points.y2;
34791             }
34792             else if (!pathip || pathip[0] == "M") {
34793                 points = {
34794                     x1: pathi[pathil - 2],
34795                     y1: pathi[pathil - 1]
34796                 };
34797             } else {
34798                 points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], pathi[pathil - 2], pathi[pathil - 1], pathip[pathipl - 2], pathip[pathipl - 1], value);
34799             }
34800             newp.push(["C", x, y, points.x1, points.y1, pathi[pathil - 2], pathi[pathil - 1]]);
34801             x = points.x2;
34802             y = points.y2;
34803         }
34804         return newp;
34805     },
34806
34807     findDotAtSegment: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
34808         var t1 = 1 - t;
34809         return {
34810             x: Math.pow(t1, 3) * p1x + Math.pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + Math.pow(t, 3) * p2x,
34811             y: Math.pow(t1, 3) * p1y + Math.pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + Math.pow(t, 3) * p2y
34812         };
34813     },
34814
34815     snapEnds: function (from, to, stepsMax) {
34816         var step = (to - from) / stepsMax,
34817             level = Math.floor(Math.log(step) / Math.LN10) + 1,
34818             m = Math.pow(10, level),
34819             cur,
34820             modulo = Math.round((step % m) * Math.pow(10, 2 - level)),
34821             interval = [[0, 15], [20, 4], [30, 2], [40, 4], [50, 9], [60, 4], [70, 2], [80, 4], [100, 15]],
34822             stepCount = 0,
34823             value,
34824             weight,
34825             i,
34826             topValue,
34827             topWeight = 1e9,
34828             ln = interval.length;
34829         cur = from = Math.floor(from / m) * m;
34830         for (i = 0; i < ln; i++) {
34831             value = interval[i][0];
34832             weight = (value - modulo) < 0 ? 1e6 : (value - modulo) / interval[i][1];
34833             if (weight < topWeight) {
34834                 topValue = value;
34835                 topWeight = weight;
34836             }
34837         }
34838         step = Math.floor(step * Math.pow(10, -level)) * Math.pow(10, level) + topValue * Math.pow(10, level - 2);
34839         while (cur < to) {
34840             cur += step;
34841             stepCount++;
34842         }
34843         to = +cur.toFixed(10);
34844         return {
34845             from: from,
34846             to: to,
34847             power: level,
34848             step: step,
34849             steps: stepCount
34850         };
34851     },
34852
34853     sorter: function (a, b) {
34854         return a.offset - b.offset;
34855     },
34856
34857     rad: function(degrees) {
34858         return degrees % 360 * Math.PI / 180;
34859     },
34860
34861     degrees: function(radian) {
34862         return radian * 180 / Math.PI % 360;
34863     },
34864
34865     withinBox: function(x, y, bbox) {
34866         bbox = bbox || {};
34867         return (x >= bbox.x && x <= (bbox.x + bbox.width) && y >= bbox.y && y <= (bbox.y + bbox.height));
34868     },
34869
34870     parseGradient: function(gradient) {
34871         var me = this,
34872             type = gradient.type || 'linear',
34873             angle = gradient.angle || 0,
34874             radian = me.radian,
34875             stops = gradient.stops,
34876             stopsArr = [],
34877             stop,
34878             vector,
34879             max,
34880             stopObj;
34881
34882         if (type == 'linear') {
34883             vector = [0, 0, Math.cos(angle * radian), Math.sin(angle * radian)];
34884             max = 1 / (Math.max(Math.abs(vector[2]), Math.abs(vector[3])) || 1);
34885             vector[2] *= max;
34886             vector[3] *= max;
34887             if (vector[2] < 0) {
34888                 vector[0] = -vector[2];
34889                 vector[2] = 0;
34890             }
34891             if (vector[3] < 0) {
34892                 vector[1] = -vector[3];
34893                 vector[3] = 0;
34894             }
34895         }
34896
34897         for (stop in stops) {
34898             if (stops.hasOwnProperty(stop) && me.stopsRE.test(stop)) {
34899                 stopObj = {
34900                     offset: parseInt(stop, 10),
34901                     color: Ext.draw.Color.toHex(stops[stop].color) || '#ffffff',
34902                     opacity: stops[stop].opacity || 1
34903                 };
34904                 stopsArr.push(stopObj);
34905             }
34906         }
34907         
34908         Ext.Array.sort(stopsArr, me.sorter);
34909         if (type == 'linear') {
34910             return {
34911                 id: gradient.id,
34912                 type: type,
34913                 vector: vector,
34914                 stops: stopsArr
34915             };
34916         }
34917         else {
34918             return {
34919                 id: gradient.id,
34920                 type: type,
34921                 centerX: gradient.centerX,
34922                 centerY: gradient.centerY,
34923                 focalX: gradient.focalX,
34924                 focalY: gradient.focalY,
34925                 radius: gradient.radius,
34926                 vector: vector,
34927                 stops: stopsArr
34928             };
34929         }
34930     }
34931 });
34932
34933
34934 Ext.define('Ext.fx.PropertyHandler', {
34935
34936     
34937
34938     requires: ['Ext.draw.Draw'],
34939
34940     statics: {
34941         defaultHandler: {
34942             pixelDefaults: ['width', 'height', 'top', 'left'],
34943             unitRE: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/,
34944
34945             computeDelta: function(from, end, damper, initial, attr) {
34946                 damper = (typeof damper == 'number') ? damper : 1;
34947                 var match = this.unitRE.exec(from),
34948                     start, units;
34949                 if (match) {
34950                     from = match[1];
34951                     units = match[2];
34952                     if (!units && Ext.Array.contains(this.pixelDefaults, attr)) {
34953                         units = 'px';
34954                     }
34955                 }
34956                 from = +from || 0;
34957
34958                 match = this.unitRE.exec(end);
34959                 if (match) {
34960                     end = match[1];
34961                     units = match[2] || units;
34962                 }
34963                 end = +end || 0;
34964                 start = (initial != null) ? initial : from;
34965                 return {
34966                     from: from,
34967                     delta: (end - start) * damper,
34968                     units: units
34969                 };
34970             },
34971
34972             get: function(from, end, damper, initialFrom, attr) {
34973                 var ln = from.length,
34974                     out = [],
34975                     i, initial, res, j, len;
34976                 for (i = 0; i < ln; i++) {
34977                     if (initialFrom) {
34978                         initial = initialFrom[i][1].from;
34979                     }
34980                     if (Ext.isArray(from[i][1]) && Ext.isArray(end)) {
34981                         res = [];
34982                         j = 0;
34983                         len = from[i][1].length;
34984                         for (; j < len; j++) {
34985                             res.push(this.computeDelta(from[i][1][j], end[j], damper, initial, attr));
34986                         }
34987                         out.push([from[i][0], res]);
34988                     }
34989                     else {
34990                         out.push([from[i][0], this.computeDelta(from[i][1], end, damper, initial, attr)]);
34991                     }
34992                 }
34993                 return out;
34994             },
34995
34996             set: function(values, easing) {
34997                 var ln = values.length,
34998                     out = [],
34999                     i, val, res, len, j;
35000                 for (i = 0; i < ln; i++) {
35001                     val  = values[i][1];
35002                     if (Ext.isArray(val)) {
35003                         res = [];
35004                         j = 0;
35005                         len = val.length;
35006                         for (; j < len; j++) {
35007                             res.push(val[j].from + (val[j].delta * easing) + (val[j].units || 0));
35008                         }
35009                         out.push([values[i][0], res]);
35010                     } else {
35011                         out.push([values[i][0], val.from + (val.delta * easing) + (val.units || 0)]);
35012                     }
35013                 }
35014                 return out;
35015             }
35016         },
35017         color: {
35018             rgbRE: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i,
35019             hexRE: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i,
35020             hex3RE: /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i,
35021
35022             parseColor : function(color, damper) {
35023                 damper = (typeof damper == 'number') ? damper : 1;
35024                 var base,
35025                     out = false,
35026                     match;
35027
35028                 Ext.each([this.hexRE, this.rgbRE, this.hex3RE], function(re, idx) {
35029                     base = (idx % 2 == 0) ? 16 : 10;
35030                     match = re.exec(color);
35031                     if (match && match.length == 4) {
35032                         if (idx == 2) {
35033                             match[1] += match[1];
35034                             match[2] += match[2];
35035                             match[3] += match[3];
35036                         }
35037                         out = {
35038                             red: parseInt(match[1], base),
35039                             green: parseInt(match[2], base),
35040                             blue: parseInt(match[3], base)
35041                         };
35042                         return false;
35043                     }
35044                 });
35045                 return out || color;
35046             },
35047
35048             computeDelta: function(from, end, damper, initial) {
35049                 from = this.parseColor(from);
35050                 end = this.parseColor(end, damper);
35051                 var start = initial ? initial : from,
35052                     tfrom = typeof start,
35053                     tend = typeof end;
35054                 
35055                 if (tfrom == 'string' ||  tfrom == 'undefined' 
35056                   || tend == 'string' || tend == 'undefined') {
35057                     return end || start;
35058                 }
35059                 return {
35060                     from:  from,
35061                     delta: {
35062                         red: Math.round((end.red - start.red) * damper),
35063                         green: Math.round((end.green - start.green) * damper),
35064                         blue: Math.round((end.blue - start.blue) * damper)
35065                     }
35066                 };
35067             },
35068
35069             get: function(start, end, damper, initialFrom) {
35070                 var ln = start.length,
35071                     out = [],
35072                     i, initial;
35073                 for (i = 0; i < ln; i++) {
35074                     if (initialFrom) {
35075                         initial = initialFrom[i][1].from;
35076                     }
35077                     out.push([start[i][0], this.computeDelta(start[i][1], end, damper, initial)]);
35078                 }
35079                 return out;
35080             },
35081
35082             set: function(values, easing) {
35083                 var ln = values.length,
35084                     out = [],
35085                     i, val, parsedString, from, delta;
35086                 for (i = 0; i < ln; i++) {
35087                     val = values[i][1];
35088                     if (val) {
35089                         from = val.from;
35090                         delta = val.delta;
35091                         
35092                         val = (typeof val == 'object' && 'red' in val)? 
35093                                 'rgb(' + val.red + ', ' + val.green + ', ' + val.blue + ')' : val;
35094                         val = (typeof val == 'object' && val.length)? val[0] : val;
35095                         if (typeof val == 'undefined') {
35096                             return [];
35097                         }
35098                         parsedString = typeof val == 'string'? val :
35099                             'rgb(' + [
35100                                   (from.red + Math.round(delta.red * easing)) % 256,
35101                                   (from.green + Math.round(delta.green * easing)) % 256,
35102                                   (from.blue + Math.round(delta.blue * easing)) % 256
35103                               ].join(',') + ')';
35104                         out.push([
35105                             values[i][0],
35106                             parsedString
35107                         ]);
35108                     }
35109                 }
35110                 return out;
35111             }
35112         },
35113         object: {
35114             interpolate: function(prop, damper) {
35115                 damper = (typeof damper == 'number') ? damper : 1;
35116                 var out = {},
35117                     p;
35118                 for(p in prop) {
35119                     out[p] = parseInt(prop[p], 10) * damper;
35120                 }
35121                 return out;
35122             },
35123
35124             computeDelta: function(from, end, damper, initial) {
35125                 from = this.interpolate(from);
35126                 end = this.interpolate(end, damper);
35127                 var start = initial ? initial : from,
35128                     delta = {},
35129                     p;
35130
35131                 for(p in end) {
35132                     delta[p] = end[p] - start[p];
35133                 }
35134                 return {
35135                     from:  from,
35136                     delta: delta
35137                 };
35138             },
35139
35140             get: function(start, end, damper, initialFrom) {
35141                 var ln = start.length,
35142                     out = [],
35143                     i, initial;
35144                 for (i = 0; i < ln; i++) {
35145                     if (initialFrom) {
35146                         initial = initialFrom[i][1].from;
35147                     }
35148                     out.push([start[i][0], this.computeDelta(start[i][1], end, damper, initial)]);
35149                 }
35150                 return out;
35151             },
35152
35153             set: function(values, easing) {
35154                 var ln = values.length,
35155                     out = [],
35156                     outObject = {},
35157                     i, from, delta, val, p;
35158                 for (i = 0; i < ln; i++) {
35159                     val  = values[i][1];
35160                     from = val.from;
35161                     delta = val.delta;
35162                     for (p in from) {
35163                         outObject[p] = Math.round(from[p] + delta[p] * easing);
35164                     }
35165                     out.push([
35166                         values[i][0],
35167                         outObject
35168                     ]);
35169                 }
35170                 return out;
35171             }
35172         },
35173
35174         path: {
35175             computeDelta: function(from, end, damper, initial) {
35176                 damper = (typeof damper == 'number') ? damper : 1;
35177                 var start;
35178                 from = +from || 0;
35179                 end = +end || 0;
35180                 start = (initial != null) ? initial : from;
35181                 return {
35182                     from: from,
35183                     delta: (end - start) * damper
35184                 };
35185             },
35186
35187             forcePath: function(path) {
35188                 if (!Ext.isArray(path) && !Ext.isArray(path[0])) {
35189                     path = Ext.draw.Draw.parsePathString(path);
35190                 }
35191                 return path;
35192             },
35193
35194             get: function(start, end, damper, initialFrom) {
35195                 var endPath = this.forcePath(end),
35196                     out = [],
35197                     startLn = start.length,
35198                     startPathLn, pointsLn, i, deltaPath, initial, j, k, path, startPath;
35199                 for (i = 0; i < startLn; i++) {
35200                     startPath = this.forcePath(start[i][1]);
35201
35202                     deltaPath = Ext.draw.Draw.interpolatePaths(startPath, endPath);
35203                     startPath = deltaPath[0];
35204                     endPath = deltaPath[1];
35205
35206                     startPathLn = startPath.length;
35207                     path = [];
35208                     for (j = 0; j < startPathLn; j++) {
35209                         deltaPath = [startPath[j][0]];
35210                         pointsLn = startPath[j].length;
35211                         for (k = 1; k < pointsLn; k++) {
35212                             initial = initialFrom && initialFrom[0][1][j][k].from;
35213                             deltaPath.push(this.computeDelta(startPath[j][k], endPath[j][k], damper, initial));
35214                         }
35215                         path.push(deltaPath);
35216                     }
35217                     out.push([start[i][0], path]);
35218                 }
35219                 return out;
35220             },
35221
35222             set: function(values, easing) {
35223                 var ln = values.length,
35224                     out = [],
35225                     i, j, k, newPath, calcPath, deltaPath, deltaPathLn, pointsLn;
35226                 for (i = 0; i < ln; i++) {
35227                     deltaPath = values[i][1];
35228                     newPath = [];
35229                     deltaPathLn = deltaPath.length;
35230                     for (j = 0; j < deltaPathLn; j++) {
35231                         calcPath = [deltaPath[j][0]];
35232                         pointsLn = deltaPath[j].length;
35233                         for (k = 1; k < pointsLn; k++) {
35234                             calcPath.push(deltaPath[j][k].from + deltaPath[j][k].delta * easing);
35235                         }
35236                         newPath.push(calcPath.join(','));
35237                     }
35238                     out.push([values[i][0], newPath.join(',')]);
35239                 }
35240                 return out;
35241             }
35242         }
35243         
35244     }
35245 }, function() {
35246     Ext.each([
35247         'outlineColor',
35248         'backgroundColor',
35249         'borderColor',
35250         'borderTopColor',
35251         'borderRightColor', 
35252         'borderBottomColor', 
35253         'borderLeftColor',
35254         'fill',
35255         'stroke'
35256     ], function(prop) {
35257         this[prop] = this.color;
35258     }, this);
35259 });
35260
35261 Ext.define('Ext.fx.Anim', {
35262
35263     
35264
35265     mixins: {
35266         observable: 'Ext.util.Observable'
35267     },
35268
35269     requires: ['Ext.fx.Manager', 'Ext.fx.Animator', 'Ext.fx.Easing', 'Ext.fx.CubicBezier', 'Ext.fx.PropertyHandler'],
35270
35271     
35272
35273     isAnimation: true,
35274     
35275     duration: 250,
35276
35277     
35278     delay: 0,
35279
35280     
35281     delayStart: 0,
35282
35283     
35284     dynamic: false,
35285
35286     
35287     easing: 'ease',
35288
35289      
35290
35291     
35292     damper: 1,
35293
35294     
35295     bezierRE: /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
35296
35297     
35298     reverse: false,
35299
35300     
35301     running: false,
35302
35303     
35304     paused: false,
35305
35306     
35307     iterations: 1,
35308
35309     
35310     alternate: false,
35311
35312     
35313     currentIteration: 0,
35314
35315     
35316     startTime: 0,
35317
35318     
35319
35320     
35321
35322     
35323
35324     
35325
35326     
35327     constructor: function(config) {
35328         var me = this;
35329         config = config || {};
35330         
35331         if (config.keyframes) {
35332             return Ext.create('Ext.fx.Animator', config);
35333         }
35334         config = Ext.apply(me, config);
35335         if (me.from === undefined) {
35336             me.from = {};
35337         }
35338         me.propHandlers = {};
35339         me.config = config;
35340         me.target = Ext.fx.Manager.createTarget(me.target);
35341         me.easingFn = Ext.fx.Easing[me.easing];
35342         me.target.dynamic = me.dynamic;
35343
35344         
35345         if (!me.easingFn) {
35346             me.easingFn = String(me.easing).match(me.bezierRE);
35347             if (me.easingFn && me.easingFn.length == 5) {
35348                 var curve = me.easingFn;
35349                 me.easingFn = Ext.fx.cubicBezier(+curve[1], +curve[2], +curve[3], +curve[4]);
35350             }
35351         }
35352         me.id = Ext.id(null, 'ext-anim-');
35353         Ext.fx.Manager.addAnim(me);
35354         me.addEvents(
35355             
35356             'beforeanimate',
35357              
35358             'afteranimate',
35359              
35360             'lastframe'
35361         );
35362         me.mixins.observable.constructor.call(me, config);
35363         if (config.callback) {
35364             me.on('afteranimate', config.callback, config.scope);
35365         }
35366         return me;
35367     },
35368
35369     
35370     setAttr: function(attr, value) {
35371         return Ext.fx.Manager.items.get(this.id).setAttr(this.target, attr, value);
35372     },
35373
35374     
35375     initAttrs: function() {
35376         var me = this,
35377             from = me.from,
35378             to = me.to,
35379             initialFrom = me.initialFrom || {},
35380             out = {},
35381             start, end, propHandler, attr;
35382
35383         for (attr in to) {
35384             if (to.hasOwnProperty(attr)) {
35385                 start = me.target.getAttr(attr, from[attr]);
35386                 end = to[attr];
35387                 
35388                 if (!Ext.fx.PropertyHandler[attr]) {
35389                     if (Ext.isObject(end)) {
35390                         propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.object;
35391                     } else {
35392                         propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.defaultHandler;
35393                     }
35394                 }
35395                 
35396                 else {
35397                     propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler[attr];
35398                 }
35399                 out[attr] = propHandler.get(start, end, me.damper, initialFrom[attr], attr);
35400             }
35401         }
35402         me.currentAttrs = out;
35403     },
35404
35405     
35406     start: function(startTime) {
35407         var me = this,
35408             delay = me.delay,
35409             delayStart = me.delayStart,
35410             delayDelta;
35411         if (delay) {
35412             if (!delayStart) {
35413                 me.delayStart = startTime;
35414                 return;
35415             }
35416             else {
35417                 delayDelta = startTime - delayStart;
35418                 if (delayDelta < delay) {
35419                     return;
35420                 }
35421                 else {
35422                     
35423                     startTime = new Date(delayStart.getTime() + delay);
35424                 }
35425             }
35426         }
35427         if (me.fireEvent('beforeanimate', me) !== false) {
35428             me.startTime = startTime;
35429             if (!me.paused && !me.currentAttrs) {
35430                 me.initAttrs();
35431             }
35432             me.running = true;
35433         }
35434     },
35435
35436     
35437     runAnim: function(elapsedTime) {
35438         var me = this,
35439             attrs = me.currentAttrs,
35440             duration = me.duration,
35441             easingFn = me.easingFn,
35442             propHandlers = me.propHandlers,
35443             ret = {},
35444             easing, values, attr, lastFrame;
35445
35446         if (elapsedTime >= duration) {
35447             elapsedTime = duration;
35448             lastFrame = true;
35449         }
35450         if (me.reverse) {
35451             elapsedTime = duration - elapsedTime;
35452         }
35453
35454         for (attr in attrs) {
35455             if (attrs.hasOwnProperty(attr)) {
35456                 values = attrs[attr];
35457                 easing = lastFrame ? 1 : easingFn(elapsedTime / duration);
35458                 ret[attr] = propHandlers[attr].set(values, easing);
35459             }
35460         }
35461         return ret;
35462     },
35463
35464     
35465     lastFrame: function() {
35466         var me = this,
35467             iter = me.iterations,
35468             iterCount = me.currentIteration;
35469
35470         iterCount++;
35471         if (iterCount < iter) {
35472             if (me.alternate) {
35473                 me.reverse = !me.reverse;
35474             }
35475             me.startTime = new Date();
35476             me.currentIteration = iterCount;
35477             
35478             me.paused = false;
35479         }
35480         else {
35481             me.currentIteration = 0;
35482             me.end();
35483             me.fireEvent('lastframe', me, me.startTime);
35484         }
35485     },
35486
35487     
35488     end: function() {
35489         var me = this;
35490         me.startTime = 0;
35491         me.paused = false;
35492         me.running = false;
35493         Ext.fx.Manager.removeAnim(me);
35494         me.fireEvent('afteranimate', me, me.startTime);
35495     }
35496 });
35497
35498 Ext.enableFx = true;
35499
35500
35501
35502
35503
35504
35505 Ext.define('Ext.dd.DragDrop', {
35506     requires: ['Ext.dd.DragDropManager'],
35507     constructor: function(id, sGroup, config) {
35508         if(id) {
35509             this.init(id, sGroup, config);
35510         }
35511     },
35512     
35513     
35514
35515     
35516     id: null,
35517
35518     
35519     config: null,
35520
35521     
35522     dragElId: null,
35523
35524     
35525     handleElId: null,
35526
35527     
35528     invalidHandleTypes: null,
35529
35530     
35531     invalidHandleIds: null,
35532
35533     
35534     invalidHandleClasses: null,
35535
35536     
35537     startPageX: 0,
35538
35539     
35540     startPageY: 0,
35541
35542     
35543     groups: null,
35544
35545     
35546     locked: false,
35547
35548     
35549     lock: function() {
35550         this.locked = true;
35551     },
35552
35553     
35554     moveOnly: false,
35555
35556     
35557     unlock: function() {
35558         this.locked = false;
35559     },
35560
35561     
35562     isTarget: true,
35563
35564     
35565     padding: null,
35566
35567     
35568     _domRef: null,
35569
35570     
35571     __ygDragDrop: true,
35572
35573     
35574     constrainX: false,
35575
35576     
35577     constrainY: false,
35578
35579     
35580     minX: 0,
35581
35582     
35583     maxX: 0,
35584
35585     
35586     minY: 0,
35587
35588     
35589     maxY: 0,
35590
35591     
35592     maintainOffset: false,
35593
35594     
35595     xTicks: null,
35596
35597     
35598     yTicks: null,
35599
35600     
35601     primaryButtonOnly: true,
35602
35603     
35604     available: false,
35605
35606     
35607     hasOuterHandles: false,
35608
35609     
35610     b4StartDrag: function(x, y) { },
35611
35612     
35613     startDrag: function(x, y) {  },
35614
35615     
35616     b4Drag: function(e) { },
35617
35618     
35619     onDrag: function(e) {  },
35620
35621     
35622     onDragEnter: function(e, id) {  },
35623
35624     
35625     b4DragOver: function(e) { },
35626
35627     
35628     onDragOver: function(e, id) {  },
35629
35630     
35631     b4DragOut: function(e) { },
35632
35633     
35634     onDragOut: function(e, id) {  },
35635
35636     
35637     b4DragDrop: function(e) { },
35638
35639     
35640     onDragDrop: function(e, id) {  },
35641
35642     
35643     onInvalidDrop: function(e) {  },
35644
35645     
35646     b4EndDrag: function(e) { },
35647
35648     
35649     endDrag: function(e) {  },
35650
35651     
35652     b4MouseDown: function(e) {  },
35653
35654     
35655     onMouseDown: function(e) {  },
35656
35657     
35658     onMouseUp: function(e) {  },
35659
35660     
35661     onAvailable: function () {
35662     },
35663
35664     
35665     defaultPadding: {
35666         left: 0,
35667         right: 0,
35668         top: 0,
35669         bottom: 0
35670     },
35671
35672     
35673     constrainTo : function(constrainTo, pad, inContent){
35674         if(Ext.isNumber(pad)){
35675             pad = {left: pad, right:pad, top:pad, bottom:pad};
35676         }
35677         pad = pad || this.defaultPadding;
35678         var b = Ext.get(this.getEl()).getBox(),
35679             ce = Ext.get(constrainTo),
35680             s = ce.getScroll(),
35681             c, 
35682             cd = ce.dom;
35683         if(cd == document.body){
35684             c = { x: s.left, y: s.top, width: Ext.core.Element.getViewWidth(), height: Ext.core.Element.getViewHeight()};
35685         }else{
35686             var xy = ce.getXY();
35687             c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
35688         }
35689
35690
35691         var topSpace = b.y - c.y,
35692             leftSpace = b.x - c.x;
35693
35694         this.resetConstraints();
35695         this.setXConstraint(leftSpace - (pad.left||0), 
35696                 c.width - leftSpace - b.width - (pad.right||0), 
35697                                 this.xTickSize
35698         );
35699         this.setYConstraint(topSpace - (pad.top||0), 
35700                 c.height - topSpace - b.height - (pad.bottom||0), 
35701                                 this.yTickSize
35702         );
35703     },
35704
35705     
35706     getEl: function() {
35707         if (!this._domRef) {
35708             this._domRef = Ext.getDom(this.id);
35709         }
35710
35711         return this._domRef;
35712     },
35713
35714     
35715     getDragEl: function() {
35716         return Ext.getDom(this.dragElId);
35717     },
35718
35719     
35720     init: function(id, sGroup, config) {
35721         this.initTarget(id, sGroup, config);
35722         Ext.EventManager.on(this.id, "mousedown", this.handleMouseDown, this);
35723         
35724     },
35725
35726     
35727     initTarget: function(id, sGroup, config) {
35728
35729         
35730         this.config = config || {};
35731
35732         
35733         this.DDMInstance = Ext.dd.DragDropManager;
35734         
35735         this.groups = {};
35736
35737         
35738         
35739         if (typeof id !== "string") {
35740             id = Ext.id(id);
35741         }
35742
35743         
35744         this.id = id;
35745
35746         
35747         this.addToGroup((sGroup) ? sGroup : "default");
35748
35749         
35750         
35751         this.handleElId = id;
35752
35753         
35754         this.setDragElId(id);
35755
35756         
35757         this.invalidHandleTypes = { A: "A" };
35758         this.invalidHandleIds = {};
35759         this.invalidHandleClasses = [];
35760
35761         this.applyConfig();
35762
35763         this.handleOnAvailable();
35764     },
35765
35766     
35767     applyConfig: function() {
35768
35769         
35770         
35771         this.padding           = this.config.padding || [0, 0, 0, 0];
35772         this.isTarget          = (this.config.isTarget !== false);
35773         this.maintainOffset    = (this.config.maintainOffset);
35774         this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
35775
35776     },
35777
35778     
35779     handleOnAvailable: function() {
35780         this.available = true;
35781         this.resetConstraints();
35782         this.onAvailable();
35783     },
35784
35785      
35786     setPadding: function(iTop, iRight, iBot, iLeft) {
35787         
35788         if (!iRight && 0 !== iRight) {
35789             this.padding = [iTop, iTop, iTop, iTop];
35790         } else if (!iBot && 0 !== iBot) {
35791             this.padding = [iTop, iRight, iTop, iRight];
35792         } else {
35793             this.padding = [iTop, iRight, iBot, iLeft];
35794         }
35795     },
35796
35797     
35798     setInitPosition: function(diffX, diffY) {
35799         var el = this.getEl();
35800
35801         if (!this.DDMInstance.verifyEl(el)) {
35802             return;
35803         }
35804
35805         var dx = diffX || 0;
35806         var dy = diffY || 0;
35807
35808         var p = Ext.core.Element.getXY( el );
35809
35810         this.initPageX = p[0] - dx;
35811         this.initPageY = p[1] - dy;
35812
35813         this.lastPageX = p[0];
35814         this.lastPageY = p[1];
35815
35816         this.setStartPosition(p);
35817     },
35818
35819     
35820     setStartPosition: function(pos) {
35821         var p = pos || Ext.core.Element.getXY( this.getEl() );
35822         this.deltaSetXY = null;
35823
35824         this.startPageX = p[0];
35825         this.startPageY = p[1];
35826     },
35827
35828     
35829     addToGroup: function(sGroup) {
35830         this.groups[sGroup] = true;
35831         this.DDMInstance.regDragDrop(this, sGroup);
35832     },
35833
35834     
35835     removeFromGroup: function(sGroup) {
35836         if (this.groups[sGroup]) {
35837             delete this.groups[sGroup];
35838         }
35839
35840         this.DDMInstance.removeDDFromGroup(this, sGroup);
35841     },
35842
35843     
35844     setDragElId: function(id) {
35845         this.dragElId = id;
35846     },
35847
35848     
35849     setHandleElId: function(id) {
35850         if (typeof id !== "string") {
35851             id = Ext.id(id);
35852         }
35853         this.handleElId = id;
35854         this.DDMInstance.regHandle(this.id, id);
35855     },
35856
35857     
35858     setOuterHandleElId: function(id) {
35859         if (typeof id !== "string") {
35860             id = Ext.id(id);
35861         }
35862         Ext.EventManager.on(id, "mousedown", this.handleMouseDown, this);
35863         this.setHandleElId(id);
35864
35865         this.hasOuterHandles = true;
35866     },
35867
35868     
35869     unreg: function() {
35870         Ext.EventManager.un(this.id, "mousedown", this.handleMouseDown, this);
35871         this._domRef = null;
35872         this.DDMInstance._remove(this);
35873     },
35874
35875     destroy : function(){
35876         this.unreg();
35877     },
35878
35879     
35880     isLocked: function() {
35881         return (this.DDMInstance.isLocked() || this.locked);
35882     },
35883
35884     
35885     handleMouseDown: function(e, oDD){
35886         if (this.primaryButtonOnly && e.button != 0) {
35887             return;
35888         }
35889
35890         if (this.isLocked()) {
35891             return;
35892         }
35893
35894         this.DDMInstance.refreshCache(this.groups);
35895
35896         var pt = e.getPoint();
35897         if (!this.hasOuterHandles && !this.DDMInstance.isOverTarget(pt, this) )  {
35898         } else {
35899             if (this.clickValidator(e)) {
35900                 
35901                 this.setStartPosition();
35902                 this.b4MouseDown(e);
35903                 this.onMouseDown(e);
35904
35905                 this.DDMInstance.handleMouseDown(e, this);
35906
35907                 this.DDMInstance.stopEvent(e);
35908             } else {
35909
35910
35911             }
35912         }
35913     },
35914
35915     clickValidator: function(e) {
35916         var target = e.getTarget();
35917         return ( this.isValidHandleChild(target) &&
35918                     (this.id == this.handleElId ||
35919                         this.DDMInstance.handleWasClicked(target, this.id)) );
35920     },
35921
35922     
35923     addInvalidHandleType: function(tagName) {
35924         var type = tagName.toUpperCase();
35925         this.invalidHandleTypes[type] = type;
35926     },
35927
35928     
35929     addInvalidHandleId: function(id) {
35930         if (typeof id !== "string") {
35931             id = Ext.id(id);
35932         }
35933         this.invalidHandleIds[id] = id;
35934     },
35935
35936     
35937     addInvalidHandleClass: function(cssClass) {
35938         this.invalidHandleClasses.push(cssClass);
35939     },
35940
35941     
35942     removeInvalidHandleType: function(tagName) {
35943         var type = tagName.toUpperCase();
35944         
35945         delete this.invalidHandleTypes[type];
35946     },
35947
35948     
35949     removeInvalidHandleId: function(id) {
35950         if (typeof id !== "string") {
35951             id = Ext.id(id);
35952         }
35953         delete this.invalidHandleIds[id];
35954     },
35955
35956     
35957     removeInvalidHandleClass: function(cssClass) {
35958         for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
35959             if (this.invalidHandleClasses[i] == cssClass) {
35960                 delete this.invalidHandleClasses[i];
35961             }
35962         }
35963     },
35964
35965     
35966     isValidHandleChild: function(node) {
35967
35968         var valid = true;
35969         
35970         var nodeName;
35971         try {
35972             nodeName = node.nodeName.toUpperCase();
35973         } catch(e) {
35974             nodeName = node.nodeName;
35975         }
35976         valid = valid && !this.invalidHandleTypes[nodeName];
35977         valid = valid && !this.invalidHandleIds[node.id];
35978
35979         for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
35980             valid = !Ext.fly(node).hasCls(this.invalidHandleClasses[i]);
35981         }
35982
35983
35984         return valid;
35985
35986     },
35987
35988     
35989     setXTicks: function(iStartX, iTickSize) {
35990         this.xTicks = [];
35991         this.xTickSize = iTickSize;
35992
35993         var tickMap = {};
35994
35995         for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
35996             if (!tickMap[i]) {
35997                 this.xTicks[this.xTicks.length] = i;
35998                 tickMap[i] = true;
35999             }
36000         }
36001
36002         for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
36003             if (!tickMap[i]) {
36004                 this.xTicks[this.xTicks.length] = i;
36005                 tickMap[i] = true;
36006             }
36007         }
36008
36009         Ext.Array.sort(this.xTicks, this.DDMInstance.numericSort);
36010     },
36011
36012     
36013     setYTicks: function(iStartY, iTickSize) {
36014         this.yTicks = [];
36015         this.yTickSize = iTickSize;
36016
36017         var tickMap = {};
36018
36019         for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
36020             if (!tickMap[i]) {
36021                 this.yTicks[this.yTicks.length] = i;
36022                 tickMap[i] = true;
36023             }
36024         }
36025
36026         for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
36027             if (!tickMap[i]) {
36028                 this.yTicks[this.yTicks.length] = i;
36029                 tickMap[i] = true;
36030             }
36031         }
36032
36033         Ext.Array.sort(this.yTicks, this.DDMInstance.numericSort);
36034     },
36035
36036     
36037     setXConstraint: function(iLeft, iRight, iTickSize) {
36038         this.leftConstraint = iLeft;
36039         this.rightConstraint = iRight;
36040
36041         this.minX = this.initPageX - iLeft;
36042         this.maxX = this.initPageX + iRight;
36043         if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
36044
36045         this.constrainX = true;
36046     },
36047
36048     
36049     clearConstraints: function() {
36050         this.constrainX = false;
36051         this.constrainY = false;
36052         this.clearTicks();
36053     },
36054
36055     
36056     clearTicks: function() {
36057         this.xTicks = null;
36058         this.yTicks = null;
36059         this.xTickSize = 0;
36060         this.yTickSize = 0;
36061     },
36062
36063     
36064     setYConstraint: function(iUp, iDown, iTickSize) {
36065         this.topConstraint = iUp;
36066         this.bottomConstraint = iDown;
36067
36068         this.minY = this.initPageY - iUp;
36069         this.maxY = this.initPageY + iDown;
36070         if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
36071
36072         this.constrainY = true;
36073
36074     },
36075
36076     
36077     resetConstraints: function() {
36078         
36079         if (this.initPageX || this.initPageX === 0) {
36080             
36081             var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
36082             var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
36083
36084             this.setInitPosition(dx, dy);
36085
36086         
36087         } else {
36088             this.setInitPosition();
36089         }
36090
36091         if (this.constrainX) {
36092             this.setXConstraint( this.leftConstraint,
36093                                  this.rightConstraint,
36094                                  this.xTickSize        );
36095         }
36096
36097         if (this.constrainY) {
36098             this.setYConstraint( this.topConstraint,
36099                                  this.bottomConstraint,
36100                                  this.yTickSize         );
36101         }
36102     },
36103
36104     
36105     getTick: function(val, tickArray) {
36106         if (!tickArray) {
36107             
36108             
36109             return val;
36110         } else if (tickArray[0] >= val) {
36111             
36112             
36113             return tickArray[0];
36114         } else {
36115             for (var i=0, len=tickArray.length; i<len; ++i) {
36116                 var next = i + 1;
36117                 if (tickArray[next] && tickArray[next] >= val) {
36118                     var diff1 = val - tickArray[i];
36119                     var diff2 = tickArray[next] - val;
36120                     return (diff2 > diff1) ? tickArray[i] : tickArray[next];
36121                 }
36122             }
36123
36124             
36125             
36126             return tickArray[tickArray.length - 1];
36127         }
36128     },
36129
36130     
36131     toString: function() {
36132         return ("DragDrop " + this.id);
36133     }
36134
36135 });
36136
36137
36138
36139
36140
36141 Ext.define('Ext.dd.DD', {
36142     extend: 'Ext.dd.DragDrop',
36143     requires: ['Ext.dd.DragDropManager'],
36144     constructor: function(id, sGroup, config) {
36145         if (id) {
36146             this.init(id, sGroup, config);
36147         }
36148     },
36149
36150     
36151     scroll: true,
36152
36153     
36154     autoOffset: function(iPageX, iPageY) {
36155         var x = iPageX - this.startPageX;
36156         var y = iPageY - this.startPageY;
36157         this.setDelta(x, y);
36158     },
36159
36160     
36161     setDelta: function(iDeltaX, iDeltaY) {
36162         this.deltaX = iDeltaX;
36163         this.deltaY = iDeltaY;
36164     },
36165
36166     
36167     setDragElPos: function(iPageX, iPageY) {
36168         
36169         
36170
36171         var el = this.getDragEl();
36172         this.alignElWithMouse(el, iPageX, iPageY);
36173     },
36174
36175     
36176     alignElWithMouse: function(el, iPageX, iPageY) {
36177         var oCoord = this.getTargetCoord(iPageX, iPageY),
36178             fly = el.dom ? el : Ext.fly(el, '_dd'),
36179             elSize = fly.getSize(),
36180             EL = Ext.core.Element,
36181             vpSize;
36182
36183         if (!this.deltaSetXY) {
36184             vpSize = this.cachedViewportSize = { width: EL.getDocumentWidth(), height: EL.getDocumentHeight() };
36185             var aCoord = [
36186                 Math.max(0, Math.min(oCoord.x, vpSize.width - elSize.width)),
36187                 Math.max(0, Math.min(oCoord.y, vpSize.height - elSize.height))
36188             ];
36189             fly.setXY(aCoord);
36190             var newLeft = fly.getLeft(true);
36191             var newTop  = fly.getTop(true);
36192             this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
36193         } else {
36194             vpSize = this.cachedViewportSize;
36195             fly.setLeftTop(
36196                 Math.max(0, Math.min(oCoord.x + this.deltaSetXY[0], vpSize.width - elSize.width)),
36197                 Math.max(0, Math.min(oCoord.y + this.deltaSetXY[1], vpSize.height - elSize.height))
36198             );
36199         }
36200
36201         this.cachePosition(oCoord.x, oCoord.y);
36202         this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
36203         return oCoord;
36204     },
36205
36206     
36207     cachePosition: function(iPageX, iPageY) {
36208         if (iPageX) {
36209             this.lastPageX = iPageX;
36210             this.lastPageY = iPageY;
36211         } else {
36212             var aCoord = Ext.core.Element.getXY(this.getEl());
36213             this.lastPageX = aCoord[0];
36214             this.lastPageY = aCoord[1];
36215         }
36216     },
36217
36218     
36219     autoScroll: function(x, y, h, w) {
36220
36221         if (this.scroll) {
36222             
36223             var clientH = Ext.core.Element.getViewHeight();
36224
36225             
36226             var clientW = Ext.core.Element.getViewWidth();
36227
36228             
36229             var st = this.DDMInstance.getScrollTop();
36230
36231             
36232             var sl = this.DDMInstance.getScrollLeft();
36233
36234             
36235             var bot = h + y;
36236
36237             
36238             var right = w + x;
36239
36240             
36241             
36242             
36243             var toBot = (clientH + st - y - this.deltaY);
36244
36245             
36246             var toRight = (clientW + sl - x - this.deltaX);
36247
36248
36249             
36250             
36251             var thresh = 40;
36252
36253             
36254             
36255             
36256             var scrAmt = (document.all) ? 80 : 30;
36257
36258             
36259             
36260             if ( bot > clientH && toBot < thresh ) {
36261                 window.scrollTo(sl, st + scrAmt);
36262             }
36263
36264             
36265             
36266             if ( y < st && st > 0 && y - st < thresh ) {
36267                 window.scrollTo(sl, st - scrAmt);
36268             }
36269
36270             
36271             
36272             if ( right > clientW && toRight < thresh ) {
36273                 window.scrollTo(sl + scrAmt, st);
36274             }
36275
36276             
36277             
36278             if ( x < sl && sl > 0 && x - sl < thresh ) {
36279                 window.scrollTo(sl - scrAmt, st);
36280             }
36281         }
36282     },
36283
36284     
36285     getTargetCoord: function(iPageX, iPageY) {
36286         var x = iPageX - this.deltaX;
36287         var y = iPageY - this.deltaY;
36288
36289         if (this.constrainX) {
36290             if (x < this.minX) {
36291                 x = this.minX;
36292             }
36293             if (x > this.maxX) {
36294                 x = this.maxX;
36295             }
36296         }
36297
36298         if (this.constrainY) {
36299             if (y < this.minY) {
36300                 y = this.minY;
36301             }
36302             if (y > this.maxY) {
36303                 y = this.maxY;
36304             }
36305         }
36306
36307         x = this.getTick(x, this.xTicks);
36308         y = this.getTick(y, this.yTicks);
36309
36310
36311         return {x: x, y: y};
36312     },
36313
36314     
36315     applyConfig: function() {
36316         this.callParent();
36317         this.scroll = (this.config.scroll !== false);
36318     },
36319
36320     
36321     b4MouseDown: function(e) {
36322         
36323         this.autoOffset(e.getPageX(), e.getPageY());
36324     },
36325
36326     
36327     b4Drag: function(e) {
36328         this.setDragElPos(e.getPageX(), e.getPageY());
36329     },
36330
36331     toString: function() {
36332         return ("DD " + this.id);
36333     }
36334
36335     
36336     
36337     
36338     
36339
36340 });
36341
36342
36343
36344
36345 Ext.define('Ext.dd.DDProxy', {
36346     extend: 'Ext.dd.DD',
36347
36348     statics: {
36349         
36350         dragElId: "ygddfdiv"
36351     },
36352
36353     constructor: function(id, sGroup, config) {
36354         if (id) {
36355             this.init(id, sGroup, config);
36356             this.initFrame();
36357         }
36358     },
36359
36360     
36361     resizeFrame: true,
36362
36363     
36364     centerFrame: false,
36365
36366     
36367     createFrame: function() {
36368         var self = this;
36369         var body = document.body;
36370
36371         if (!body || !body.firstChild) {
36372             setTimeout( function() { self.createFrame(); }, 50 );
36373             return;
36374         }
36375
36376         var div = this.getDragEl();
36377
36378         if (!div) {
36379             div    = document.createElement("div");
36380             div.id = this.dragElId;
36381             var s  = div.style;
36382
36383             s.position   = "absolute";
36384             s.visibility = "hidden";
36385             s.cursor     = "move";
36386             s.border     = "2px solid #aaa";
36387             s.zIndex     = 999;
36388
36389             
36390             
36391             
36392             body.insertBefore(div, body.firstChild);
36393         }
36394     },
36395
36396     
36397     initFrame: function() {
36398         this.createFrame();
36399     },
36400
36401     applyConfig: function() {
36402         this.callParent();
36403
36404         this.resizeFrame = (this.config.resizeFrame !== false);
36405         this.centerFrame = (this.config.centerFrame);
36406         this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId);
36407     },
36408
36409     
36410     showFrame: function(iPageX, iPageY) {
36411         var el = this.getEl();
36412         var dragEl = this.getDragEl();
36413         var s = dragEl.style;
36414
36415         this._resizeProxy();
36416
36417         if (this.centerFrame) {
36418             this.setDelta( Math.round(parseInt(s.width,  10)/2),
36419                            Math.round(parseInt(s.height, 10)/2) );
36420         }
36421
36422         this.setDragElPos(iPageX, iPageY);
36423
36424         Ext.fly(dragEl).show();
36425     },
36426
36427     
36428     _resizeProxy: function() {
36429         if (this.resizeFrame) {
36430             var el = this.getEl();
36431             Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
36432         }
36433     },
36434
36435     
36436     b4MouseDown: function(e) {
36437         var x = e.getPageX();
36438         var y = e.getPageY();
36439         this.autoOffset(x, y);
36440         this.setDragElPos(x, y);
36441     },
36442
36443     
36444     b4StartDrag: function(x, y) {
36445         
36446         this.showFrame(x, y);
36447     },
36448
36449     
36450     b4EndDrag: function(e) {
36451         Ext.fly(this.getDragEl()).hide();
36452     },
36453
36454     
36455     
36456     
36457     endDrag: function(e) {
36458
36459         var lel = this.getEl();
36460         var del = this.getDragEl();
36461
36462         
36463         del.style.visibility = "";
36464
36465         this.beforeMove();
36466         
36467         
36468         lel.style.visibility = "hidden";
36469         Ext.dd.DDM.moveToEl(lel, del);
36470         del.style.visibility = "hidden";
36471         lel.style.visibility = "";
36472
36473         this.afterDrag();
36474     },
36475
36476     beforeMove : function(){
36477
36478     },
36479
36480     afterDrag : function(){
36481
36482     },
36483
36484     toString: function() {
36485         return ("DDProxy " + this.id);
36486     }
36487
36488 });
36489
36490
36491 Ext.define('Ext.dd.DragSource', {
36492     extend: 'Ext.dd.DDProxy',
36493     requires: [
36494         'Ext.dd.StatusProxy',
36495         'Ext.dd.DragDropManager'
36496     ],
36497
36498     
36499
36500     
36501
36502     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
36503     
36504     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
36505
36506     
36507     animRepair: true,
36508
36509     
36510     repairHighlightColor: 'c3daf9',
36511
36512     constructor: function(el, config) {
36513         this.el = Ext.get(el);
36514         if(!this.dragData){
36515             this.dragData = {};
36516         }
36517
36518         Ext.apply(this, config);
36519
36520         if(!this.proxy){
36521             this.proxy = Ext.create('Ext.dd.StatusProxy', {
36522                 animRepair: this.animRepair
36523             });
36524         }
36525         this.callParent([this.el.dom, this.ddGroup || this.group,
36526               {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true}]);
36527
36528         this.dragging = false;
36529     },
36530
36531     
36532     getDragData : function(e){
36533         return this.dragData;
36534     },
36535
36536     
36537     onDragEnter : function(e, id){
36538         var target = Ext.dd.DragDropManager.getDDById(id);
36539         this.cachedTarget = target;
36540         if (this.beforeDragEnter(target, e, id) !== false) {
36541             if (target.isNotifyTarget) {
36542                 var status = target.notifyEnter(this, e, this.dragData);
36543                 this.proxy.setStatus(status);
36544             } else {
36545                 this.proxy.setStatus(this.dropAllowed);
36546             }
36547
36548             if (this.afterDragEnter) {
36549                 
36550                 this.afterDragEnter(target, e, id);
36551             }
36552         }
36553     },
36554
36555     
36556     beforeDragEnter: function(target, e, id) {
36557         return true;
36558     },
36559
36560     
36561     alignElWithMouse: function() {
36562         this.callParent(arguments);
36563         this.proxy.sync();
36564     },
36565
36566     
36567     onDragOver: function(e, id) {
36568         var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
36569         if (this.beforeDragOver(target, e, id) !== false) {
36570             if(target.isNotifyTarget){
36571                 var status = target.notifyOver(this, e, this.dragData);
36572                 this.proxy.setStatus(status);
36573             }
36574
36575             if (this.afterDragOver) {
36576                 
36577                 this.afterDragOver(target, e, id);
36578             }
36579         }
36580     },
36581
36582     
36583     beforeDragOver: function(target, e, id) {
36584         return true;
36585     },
36586
36587     
36588     onDragOut: function(e, id) {
36589         var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
36590         if (this.beforeDragOut(target, e, id) !== false) {
36591             if (target.isNotifyTarget) {
36592                 target.notifyOut(this, e, this.dragData);
36593             }
36594             this.proxy.reset();
36595             if (this.afterDragOut) {
36596                 
36597                 this.afterDragOut(target, e, id);
36598             }
36599         }
36600         this.cachedTarget = null;
36601     },
36602
36603     
36604     beforeDragOut: function(target, e, id){
36605         return true;
36606     },
36607
36608     
36609     onDragDrop: function(e, id){
36610         var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
36611         if (this.beforeDragDrop(target, e, id) !== false) {
36612             if (target.isNotifyTarget) {
36613                 if (target.notifyDrop(this, e, this.dragData) !== false) { 
36614                     this.onValidDrop(target, e, id);
36615                 } else {
36616                     this.onInvalidDrop(target, e, id);
36617                 }
36618             } else {
36619                 this.onValidDrop(target, e, id);
36620             }
36621
36622             if (this.afterDragDrop) {
36623                 
36624                 this.afterDragDrop(target, e, id);
36625             }
36626         }
36627         delete this.cachedTarget;
36628     },
36629
36630     
36631     beforeDragDrop: function(target, e, id){
36632         return true;
36633     },
36634
36635     
36636     onValidDrop: function(target, e, id){
36637         this.hideProxy();
36638         if(this.afterValidDrop){
36639             
36640             this.afterValidDrop(target, e, id);
36641         }
36642     },
36643
36644     
36645     getRepairXY: function(e, data){
36646         return this.el.getXY();
36647     },
36648
36649     
36650     onInvalidDrop: function(target, e, id) {
36651         this.beforeInvalidDrop(target, e, id);
36652         if (this.cachedTarget) {
36653             if(this.cachedTarget.isNotifyTarget){
36654                 this.cachedTarget.notifyOut(this, e, this.dragData);
36655             }
36656             this.cacheTarget = null;
36657         }
36658         this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
36659
36660         if (this.afterInvalidDrop) {
36661             
36662             this.afterInvalidDrop(e, id);
36663         }
36664     },
36665
36666     
36667     afterRepair: function() {
36668         var me = this;
36669         if (Ext.enableFx) {
36670             me.el.highlight(me.repairHighlightColor);
36671         }
36672         me.dragging = false;
36673     },
36674
36675     
36676     beforeInvalidDrop: function(target, e, id) {
36677         return true;
36678     },
36679
36680     
36681     handleMouseDown: function(e) {
36682         if (this.dragging) {
36683             return;
36684         }
36685         var data = this.getDragData(e);
36686         if (data && this.onBeforeDrag(data, e) !== false) {
36687             this.dragData = data;
36688             this.proxy.stop();
36689             this.callParent(arguments);
36690         }
36691     },
36692
36693     
36694     onBeforeDrag: function(data, e){
36695         return true;
36696     },
36697
36698     
36699     onStartDrag: Ext.emptyFn,
36700
36701     
36702     startDrag: function(x, y) {
36703         this.proxy.reset();
36704         this.dragging = true;
36705         this.proxy.update("");
36706         this.onInitDrag(x, y);
36707         this.proxy.show();
36708     },
36709
36710     
36711     onInitDrag: function(x, y) {
36712         var clone = this.el.dom.cloneNode(true);
36713         clone.id = Ext.id(); 
36714         this.proxy.update(clone);
36715         this.onStartDrag(x, y);
36716         return true;
36717     },
36718
36719     
36720     getProxy: function() {
36721         return this.proxy;
36722     },
36723
36724     
36725     hideProxy: function() {
36726         this.proxy.hide();
36727         this.proxy.reset(true);
36728         this.dragging = false;
36729     },
36730
36731     
36732     triggerCacheRefresh: function() {
36733         Ext.dd.DDM.refreshCache(this.groups);
36734     },
36735
36736     
36737     b4EndDrag: function(e) {
36738     },
36739
36740     
36741     endDrag : function(e){
36742         this.onEndDrag(this.dragData, e);
36743     },
36744
36745     
36746     onEndDrag : function(data, e){
36747     },
36748
36749     
36750     autoOffset : function(x, y) {
36751         this.setDelta(-12, -20);
36752     },
36753
36754     destroy: function(){
36755         this.callParent();
36756         Ext.destroy(this.proxy);
36757     }
36758 });
36759
36760
36761 Ext.define('Ext.panel.DD', {
36762     extend: 'Ext.dd.DragSource',
36763     requires: ['Ext.panel.Proxy'],
36764
36765     constructor : function(panel, cfg){
36766         this.panel = panel;
36767         this.dragData = {panel: panel};
36768         this.proxy = Ext.create('Ext.panel.Proxy', panel, cfg);
36769
36770         this.callParent([panel.el, cfg]);
36771
36772         Ext.defer(function() {
36773             var header = panel.header,
36774                 el = panel.body;
36775
36776             if(header){
36777                 this.setHandleElId(header.id);
36778                 el = header.el;
36779             }
36780             el.setStyle('cursor', 'move');
36781             this.scroll = false;
36782         }, 200, this);
36783     },
36784
36785     showFrame: Ext.emptyFn,
36786     startDrag: Ext.emptyFn,
36787     b4StartDrag: function(x, y) {
36788         this.proxy.show();
36789     },
36790     b4MouseDown: function(e) {
36791         var x = e.getPageX(),
36792             y = e.getPageY();
36793         this.autoOffset(x, y);
36794     },
36795     onInitDrag : function(x, y){
36796         this.onStartDrag(x, y);
36797         return true;
36798     },
36799     createFrame : Ext.emptyFn,
36800     getDragEl : function(e){
36801         return this.proxy.ghost.el.dom;
36802     },
36803     endDrag : function(e){
36804         this.proxy.hide();
36805         this.panel.saveState();
36806     },
36807
36808     autoOffset : function(x, y) {
36809         x -= this.startPageX;
36810         y -= this.startPageY;
36811         this.setDelta(x, y);
36812     }
36813 });
36814
36815
36816 Ext.define('Ext.layout.component.Dock', {
36817
36818     
36819
36820     alias: ['layout.dock'],
36821
36822     extend: 'Ext.layout.component.AbstractDock'
36823
36824     
36825
36826 });
36827
36828 Ext.define('Ext.panel.Panel', {
36829     extend: 'Ext.panel.AbstractPanel',
36830     requires: [
36831         'Ext.panel.Header',
36832         'Ext.fx.Anim',
36833         'Ext.util.KeyMap',
36834         'Ext.panel.DD',
36835         'Ext.XTemplate',
36836         'Ext.layout.component.Dock'
36837     ],
36838     alias: 'widget.panel',
36839     alternateClassName: 'Ext.Panel',
36840
36841     
36842     collapsedCls: 'collapsed',
36843
36844     
36845     animCollapse: Ext.enableFx,
36846
36847     
36848     minButtonWidth: 75,
36849
36850     
36851     collapsed: false,
36852
36853     
36854     collapseFirst: true,
36855
36856     
36857     hideCollapseTool: false,
36858
36859     
36860     titleCollapse: false,
36861
36862     
36863
36864     
36865
36866     
36867     floatable: true,
36868     
36869     
36870     
36871     
36872     collapsible: false,
36873
36874     
36875
36876     
36877     closable: false,
36878
36879     
36880     closeAction: 'destroy',
36881
36882     
36883
36884     
36885     preventHeader: false,
36886
36887      
36888     headerPosition: 'top',
36889
36890      
36891     frame: false,
36892
36893     
36894     frameHeader: true,
36895
36896     
36897
36898
36899     initComponent: function() {
36900         var me = this,
36901             cls;
36902
36903         me.addEvents(
36904         
36905             'titlechange',
36906         
36907             'iconchange'
36908         );
36909
36910         if (me.unstyled) {
36911             me.setUI('plain');
36912         }
36913
36914         if (me.frame) {
36915             me.setUI('default-framed');
36916         }
36917
36918         me.callParent();
36919
36920         me.collapseDirection = me.collapseDirection || me.headerPosition || Ext.Component.DIRECTION_TOP;
36921
36922         
36923         me.bridgeToolbars();
36924     },
36925
36926     setBorder: function(border) {
36927         
36928         
36929         
36930         
36931         
36932         
36933         
36934         
36935         
36936         
36937         
36938         
36939         
36940         
36941         
36942         
36943         this.callParent(arguments);
36944     },
36945
36946     beforeDestroy: function() {
36947         Ext.destroy(
36948             this.ghostPanel,
36949             this.dd
36950         );
36951         this.callParent();
36952     },
36953
36954     initAria: function() {
36955         this.callParent();
36956         this.initHeaderAria();
36957     },
36958
36959     initHeaderAria: function() {
36960         var me = this,
36961             el = me.el,
36962             header = me.header;
36963         if (el && header) {
36964             el.dom.setAttribute('aria-labelledby', header.titleCmp.id);
36965         }
36966     },
36967
36968     getHeader: function() {
36969         return this.header;
36970     },
36971
36972     
36973     setTitle: function(newTitle) {
36974         var me = this,
36975         oldTitle = this.title;
36976
36977         me.title = newTitle;
36978         if (me.header) {
36979             me.header.setTitle(newTitle);
36980         } else {
36981             me.updateHeader();
36982         }
36983
36984         if (me.reExpander) {
36985             me.reExpander.setTitle(newTitle);
36986         }
36987         me.fireEvent('titlechange', me, newTitle, oldTitle);
36988     },
36989
36990     
36991     setIconCls: function(newIconCls) {
36992         var me = this,
36993             oldIconCls = me.iconCls;
36994
36995         me.iconCls = newIconCls;
36996         var header = me.header;
36997         if (header) {
36998             header.setIconCls(newIconCls);
36999         }
37000         me.fireEvent('iconchange', me, newIconCls, oldIconCls);
37001     },
37002
37003     bridgeToolbars: function() {
37004         var me = this,
37005             fbar,
37006             fbarDefaults,
37007             minButtonWidth = me.minButtonWidth;
37008
37009         function initToolbar (toolbar, pos) {
37010             if (Ext.isArray(toolbar)) {
37011                 toolbar = {
37012                     xtype: 'toolbar',
37013                     items: toolbar
37014                 };
37015             }
37016             else if (!toolbar.xtype) {
37017                 toolbar.xtype = 'toolbar';
37018             }
37019             toolbar.dock = pos;
37020             if (pos == 'left' || pos == 'right') {
37021                 toolbar.vertical = true;
37022             }
37023             return toolbar;
37024         }
37025
37026         
37027
37028         
37029         if (me.tbar) {
37030             me.addDocked(initToolbar(me.tbar, 'top'));
37031             me.tbar = null;
37032         }
37033
37034         
37035         if (me.bbar) {
37036             me.addDocked(initToolbar(me.bbar, 'bottom'));
37037             me.bbar = null;
37038         }
37039
37040         
37041         if (me.buttons) {
37042             me.fbar = me.buttons;
37043             me.buttons = null;
37044         }
37045
37046         
37047         if (me.fbar) {
37048             fbar = initToolbar(me.fbar, 'bottom');
37049             fbar.ui = 'footer';
37050
37051             
37052             if (minButtonWidth) {
37053                 fbarDefaults = fbar.defaults;
37054                 fbar.defaults = function(config) {
37055                     var defaults = fbarDefaults || {};
37056                     if ((!config.xtype || config.xtype === 'button' || (config.isComponent && config.isXType('button'))) &&
37057                             !('minWidth' in defaults)) {
37058                         defaults = Ext.apply({minWidth: minButtonWidth}, defaults);
37059                     }
37060                     return defaults;
37061                 };
37062             }
37063
37064             fbar = me.addDocked(fbar)[0];
37065             fbar.insert(0, {
37066                 flex: 1,
37067                 xtype: 'component',
37068                 focusable: false
37069             });
37070             me.fbar = null;
37071         }
37072
37073         
37074         if (me.lbar) {
37075             me.addDocked(initToolbar(me.lbar, 'left'));
37076             me.lbar = null;
37077         }
37078
37079         
37080         if (me.rbar) {
37081             me.addDocked(initToolbar(me.rbar, 'right'));
37082             me.rbar = null;
37083         }
37084     },
37085
37086     
37087     initTools: function() {
37088         var me = this;
37089
37090         me.tools = me.tools || [];
37091
37092         
37093         
37094         if (me.collapsible && !(me.hideCollapseTool || me.header === false)) {
37095             me.collapseDirection = me.collapseDirection || me.headerPosition || 'top';
37096             me.collapseTool = me.expandTool = me.createComponent({
37097                 xtype: 'tool',
37098                 type: 'collapse-' + me.collapseDirection,
37099                 expandType: me.getOppositeDirection(me.collapseDirection),
37100                 handler: me.toggleCollapse,
37101                 scope: me
37102             });
37103
37104             
37105             if (me.collapseFirst) {
37106                 me.tools.unshift(me.collapseTool);
37107             }
37108         }
37109
37110         
37111         me.addTools();
37112
37113         
37114         if (me.closable) {
37115             me.addClsWithUI('closable');
37116             me.addTool({
37117                 type: 'close',
37118                 handler: Ext.Function.bind(me.close, this, [])
37119             });
37120         }
37121
37122         
37123         if (me.collapseTool && !me.collapseFirst) {
37124             me.tools.push(me.collapseTool);
37125         }
37126     },
37127
37128     
37129     addTools: Ext.emptyFn,
37130
37131     
37132     close: function() {
37133         if (this.fireEvent('beforeclose', this) !== false) {
37134             this.doClose();
37135         }
37136     },
37137
37138     
37139     doClose: function() {
37140         this.fireEvent('close', this);
37141         this[this.closeAction]();
37142     },
37143
37144     onRender: function(ct, position) {
37145         var me = this,
37146             topContainer;
37147
37148         
37149         
37150         me.initTools();
37151
37152         
37153         me.updateHeader();
37154
37155         
37156         
37157         if (me.collapsed) {
37158             me.collapsed = false;
37159             topContainer = me.findLayoutController();
37160             if (!me.hidden && topContainer) {
37161                 topContainer.on({
37162                     afterlayout: function() {
37163                         me.collapse(null, false, true);
37164                     },
37165                     single: true
37166                 });
37167             } else {
37168                 me.afterComponentLayout = function() {
37169                     delete me.afterComponentLayout;
37170                     Ext.getClass(me).prototype.afterComponentLayout.apply(me, arguments);
37171                     me.collapse(null, false, true);
37172                 };
37173             }
37174         }
37175
37176         
37177         me.callParent(arguments);
37178     },
37179
37180     
37181     updateHeader: function(force) {
37182         var me = this,
37183             header = me.header,
37184             title = me.title,
37185             tools = me.tools;
37186
37187         if (!me.preventHeader && (force || title || (tools && tools.length))) {
37188             if (!header) {
37189                 header = me.header = Ext.create('Ext.panel.Header', {
37190                     title       : title,
37191                     orientation : (me.headerPosition == 'left' || me.headerPosition == 'right') ? 'vertical' : 'horizontal',
37192                     dock        : me.headerPosition || 'top',
37193                     textCls     : me.headerTextCls,
37194                     iconCls     : me.iconCls,
37195                     baseCls     : me.baseCls + '-header',
37196                     tools       : tools,
37197                     ui          : me.ui,
37198                     indicateDrag: me.draggable,
37199                     border      : me.border,
37200                     frame       : me.frame && me.frameHeader,
37201                     ignoreParentFrame : me.frame || me.overlapHeader,
37202                     ignoreBorderManagement: me.frame || me.ignoreHeaderBorderManagement,
37203                     listeners   : me.collapsible && me.titleCollapse ? {
37204                         click: me.toggleCollapse,
37205                         scope: me
37206                     } : null
37207                 });
37208                 me.addDocked(header, 0);
37209
37210                 
37211                 
37212                 me.tools = header.tools;
37213             }
37214             header.show();
37215             me.initHeaderAria();
37216         } else if (header) {
37217             header.hide();
37218         }
37219     },
37220
37221     
37222     setUI: function(ui) {
37223         var me = this;
37224
37225         me.callParent(arguments);
37226
37227         if (me.header) {
37228             me.header.setUI(ui);
37229         }
37230     },
37231
37232     
37233     getContentTarget: function() {
37234         return this.body;
37235     },
37236
37237     getTargetEl: function() {
37238         return this.body || this.frameBody || this.el;
37239     },
37240
37241     addTool: function(tool) {
37242         this.tools.push(tool);
37243         var header = this.header;
37244         if (header) {
37245             header.addTool(tool);
37246         }
37247         this.updateHeader();
37248     },
37249
37250     getOppositeDirection: function(d) {
37251         var c = Ext.Component;
37252         switch (d) {
37253             case c.DIRECTION_TOP:
37254                 return c.DIRECTION_BOTTOM;
37255             case c.DIRECTION_RIGHT:
37256                 return c.DIRECTION_LEFT;
37257             case c.DIRECTION_BOTTOM:
37258                 return c.DIRECTION_TOP;
37259             case c.DIRECTION_LEFT:
37260                 return c.DIRECTION_RIGHT;
37261         }
37262     },
37263
37264     
37265     collapse: function(direction, animate,  internal) {
37266         var me = this,
37267             c = Ext.Component,
37268             height = me.getHeight(),
37269             width = me.getWidth(),
37270             frameInfo,
37271             newSize = 0,
37272             dockedItems = me.dockedItems.items,
37273             dockedItemCount = dockedItems.length,
37274             i = 0,
37275             comp,
37276             pos,
37277             anim = {
37278                 from: {
37279                     height: height,
37280                     width: width
37281                 },
37282                 to: {
37283                     height: height,
37284                     width: width
37285                 },
37286                 listeners: {
37287                     afteranimate: me.afterCollapse,
37288                     scope: me
37289                 },
37290                 duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration)
37291             },
37292             reExpander,
37293             reExpanderOrientation,
37294             reExpanderDock,
37295             getDimension,
37296             setDimension,
37297             collapseDimension;
37298
37299         if (!direction) {
37300             direction = me.collapseDirection;
37301         }
37302
37303         
37304         if (internal) {
37305             animate = false;
37306         } else if (me.collapsed || me.fireEvent('beforecollapse', me, direction, animate) === false) {
37307             return false;
37308         }
37309
37310         reExpanderDock = direction;
37311         me.expandDirection = me.getOppositeDirection(direction);
37312
37313         
37314         me.hiddenDocked = [];
37315
37316         switch (direction) {
37317             case c.DIRECTION_TOP:
37318             case c.DIRECTION_BOTTOM:
37319                 me.expandedSize = me.getHeight();
37320                 reExpanderOrientation = 'horizontal';
37321                 collapseDimension = 'height';
37322                 getDimension = 'getHeight';
37323                 setDimension = 'setHeight';
37324
37325                 
37326                 
37327                 
37328                 for (; i < dockedItemCount; i++) {
37329                     comp = dockedItems[i];
37330                     if (comp.isVisible()) {
37331                         if (comp.isHeader && (!comp.dock || comp.dock == 'top' || comp.dock == 'bottom')) {
37332                             reExpander = comp;
37333                         } else {
37334                             me.hiddenDocked.push(comp);
37335                         }
37336                     }
37337                 }
37338
37339                 if (direction == Ext.Component.DIRECTION_BOTTOM) {
37340                     pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
37341                     anim.from.top = pos;
37342                 }
37343                 break;
37344
37345             case c.DIRECTION_LEFT:
37346             case c.DIRECTION_RIGHT:
37347                 me.expandedSize = me.getWidth();
37348                 reExpanderOrientation = 'vertical';
37349                 collapseDimension = 'width';
37350                 getDimension = 'getWidth';
37351                 setDimension = 'setWidth';
37352
37353                 
37354                 
37355                 
37356                 for (; i < dockedItemCount; i++) {
37357                     comp = dockedItems[i];
37358                     if (comp.isVisible()) {
37359                         if (comp.isHeader && (comp.dock == 'left' || comp.dock == 'right')) {
37360                             reExpander = comp;
37361                         } else {
37362                             me.hiddenDocked.push(comp);
37363                         }
37364                     }
37365                 }
37366
37367                 if (direction == Ext.Component.DIRECTION_RIGHT) {
37368                     pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
37369                     anim.from.left = pos;
37370                 }
37371                 break;
37372
37373             default:
37374                 throw('Panel collapse must be passed a valid Component collapse direction');
37375         }
37376
37377         
37378         
37379         me.setAutoScroll(false);
37380         me.suspendLayout = true;
37381         me.body.setVisibilityMode(Ext.core.Element.DISPLAY);
37382
37383         
37384         if (animate && me.collapseTool) {
37385             me.collapseTool.disable();
37386         }
37387
37388         
37389         me.addClsWithUI(me.collapsedCls);
37390         
37391         
37392         
37393
37394         
37395         if (reExpander) {
37396             
37397             reExpander.addClsWithUI(me.collapsedCls);
37398             reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
37399             if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
37400                 reExpander.addClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
37401             }
37402
37403             frameInfo = reExpander.getFrameInfo();
37404                         
37405             
37406             newSize = reExpander[getDimension]() + (frameInfo ? frameInfo[direction] : 0);
37407
37408             
37409             reExpander.removeClsWithUI(me.collapsedCls);
37410             reExpander.removeClsWithUI(me.collapsedCls + '-' + reExpander.dock);              
37411             if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
37412                 reExpander.removeClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
37413             }
37414         }
37415         
37416         else {
37417             reExpander = {
37418                 hideMode: 'offsets',
37419                 temporary: true,
37420                 title: me.title,
37421                 orientation: reExpanderOrientation,
37422                 dock: reExpanderDock,
37423                 textCls: me.headerTextCls,
37424                 iconCls: me.iconCls,
37425                 baseCls: me.baseCls + '-header',
37426                 ui: me.ui,
37427                 frame: me.frame && me.frameHeader,
37428                 ignoreParentFrame: me.frame || me.overlapHeader,
37429                 indicateDrag: me.draggable,
37430                 cls: me.baseCls + '-collapsed-placeholder ' + ' ' + Ext.baseCSSPrefix + 'docked ' + me.baseCls + '-' + me.ui + '-collapsed',
37431                 renderTo: me.el
37432             };
37433             if (!me.hideCollapseTool) {
37434                 reExpander[(reExpander.orientation == 'horizontal') ? 'tools' : 'items'] = [{
37435                     xtype: 'tool',
37436                     type: 'expand-' + me.expandDirection,
37437                     handler: me.toggleCollapse,
37438                     scope: me
37439                 }];
37440             }
37441
37442             
37443             
37444             reExpander = me.reExpander = Ext.create('Ext.panel.Header', reExpander);
37445             newSize = reExpander[getDimension]() + ((reExpander.frame) ? reExpander.frameSize[direction] : 0);
37446             reExpander.hide();
37447
37448             
37449             me.insertDocked(0, reExpander);
37450         }
37451
37452         me.reExpander = reExpander;
37453         me.reExpander.addClsWithUI(me.collapsedCls);
37454         me.reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
37455         if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
37456             me.reExpander.addClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
37457         }
37458
37459         
37460         if (direction == Ext.Component.DIRECTION_RIGHT) {
37461             anim.to.left = pos + (width - newSize);
37462         } else if (direction == Ext.Component.DIRECTION_BOTTOM) {
37463             anim.to.top = pos + (height - newSize);
37464         }
37465
37466         
37467         anim.to[collapseDimension] = newSize;
37468
37469         
37470         me.savedFlex = me.flex;
37471         me.savedMinWidth = me.minWidth;
37472         me.savedMinHeight = me.minHeight;
37473         me.minWidth = 0;
37474         me.minHeight = 0;
37475         delete me.flex;
37476
37477         if (animate) {
37478             me.animate(anim);
37479         } else {
37480             
37481             
37482             me.uncollapsedSize = { width: me.width, height: me.height };
37483
37484             me.setSize(anim.to.width, anim.to.height);
37485             if (Ext.isDefined(anim.to.left) || Ext.isDefined(anim.to.top)) {
37486                 me.setPosition(anim.to.left, anim.to.top);
37487             }
37488             me.afterCollapse(false, internal);
37489         }
37490         return me;
37491     },
37492
37493     afterCollapse: function(animated, internal) {
37494         var me = this,
37495             i = 0,
37496             l = me.hiddenDocked.length;
37497
37498         me.minWidth = me.savedMinWidth;
37499         me.minHeight = me.savedMinHeight;
37500
37501         me.body.hide();
37502         for (; i < l; i++) {
37503             me.hiddenDocked[i].hide();
37504         }
37505         if (me.reExpander) {
37506             me.reExpander.updateFrame();
37507             me.reExpander.show();
37508         }
37509         me.collapsed = true;
37510
37511         if (!internal) {
37512             me.doComponentLayout();
37513         }
37514
37515         if (me.resizer) {
37516             me.resizer.disable();
37517         }
37518
37519         
37520         if (me.collapseTool) {
37521             me.collapseTool.setType('expand-' + me.expandDirection);
37522         }
37523         if (!internal) {
37524             me.fireEvent('collapse', me);
37525         }
37526
37527         
37528         if (animated && me.collapseTool) {
37529             me.collapseTool.enable();
37530         }
37531     },
37532
37533     
37534     expand: function(animate) {
37535         if (!this.collapsed || this.fireEvent('beforeexpand', this, animate) === false) {
37536             return false;
37537         }
37538
37539         
37540         if (this.uncollapsedSize) {
37541             Ext.Object.each(this.uncollapsedSize, function (name, value) {
37542                 if (Ext.isDefined(value)) {
37543                     this[name] = value;
37544                 } else {
37545                     delete this[name];
37546                 }
37547             }, this);
37548             delete this.uncollapsedSize;
37549         }
37550
37551         var me = this,
37552             i = 0,
37553             l = me.hiddenDocked.length,
37554             direction = me.expandDirection,
37555             height = me.getHeight(),
37556             width = me.getWidth(),
37557             pos, anim, satisfyJSLint;
37558
37559         
37560         if (animate && me.collapseTool) {
37561             me.collapseTool.disable();
37562         }
37563
37564         
37565         
37566         for (; i < l; i++) {
37567             me.hiddenDocked[i].hidden = false;
37568             me.hiddenDocked[i].el.show();
37569         }
37570         if (me.reExpander) {
37571             if (me.reExpander.temporary) {
37572                 me.reExpander.hide();
37573             } else {
37574                 me.reExpander.removeClsWithUI(me.collapsedCls);
37575                 me.reExpander.removeClsWithUI(me.collapsedCls + '-' + me.reExpander.dock);
37576                 if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
37577                     me.reExpander.removeClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
37578                 }
37579                 me.reExpander.updateFrame();
37580             }
37581         }
37582
37583         
37584         if (me.collapseTool) {
37585             me.collapseTool.setType('collapse-' + me.collapseDirection);
37586         }
37587
37588         
37589         me.collapsed = false;
37590
37591         
37592         me.body.show();
37593
37594         
37595         me.removeClsWithUI(me.collapsedCls);
37596         
37597         
37598         
37599
37600         anim = {
37601             to: {
37602             },
37603             from: {
37604                 height: height,
37605                 width: width
37606             },
37607             listeners: {
37608                 afteranimate: me.afterExpand,
37609                 scope: me
37610             }
37611         };
37612
37613         if ((direction == Ext.Component.DIRECTION_TOP) || (direction == Ext.Component.DIRECTION_BOTTOM)) {
37614
37615             
37616             if (me.autoHeight) {
37617                 me.setCalculatedSize(me.width, null);
37618                 anim.to.height = me.getHeight();
37619
37620                 
37621                 me.setCalculatedSize(me.width, anim.from.height);
37622             }
37623             
37624             
37625             else if (me.savedFlex) {
37626                 me.flex = me.savedFlex;
37627                 anim.to.height = me.ownerCt.layout.calculateChildBox(me).height;
37628                 delete me.flex;
37629             }
37630             
37631             else {
37632                 anim.to.height = me.expandedSize;
37633             }
37634
37635             
37636             if (direction == Ext.Component.DIRECTION_TOP) {
37637                 pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
37638                 anim.from.top = pos;
37639                 anim.to.top = pos - (anim.to.height - height);
37640             }
37641         } else if ((direction == Ext.Component.DIRECTION_LEFT) || (direction == Ext.Component.DIRECTION_RIGHT)) {
37642
37643             
37644             if (me.autoWidth) {
37645                 me.setCalculatedSize(null, me.height);
37646                 anim.to.width = me.getWidth();
37647
37648                 
37649                 me.setCalculatedSize(anim.from.width, me.height);
37650             }
37651             
37652             
37653             else if (me.savedFlex) {
37654                 me.flex = me.savedFlex;
37655                 anim.to.width = me.ownerCt.layout.calculateChildBox(me).width;
37656                 delete me.flex;
37657             }
37658             
37659             else {
37660                 anim.to.width = me.expandedSize;
37661             }
37662
37663             
37664             if (direction == Ext.Component.DIRECTION_LEFT) {
37665                 pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
37666                 anim.from.left = pos;
37667                 anim.to.left = pos - (anim.to.width - width);
37668             }
37669         }
37670
37671         if (animate) {
37672             me.animate(anim);
37673         } else {
37674             me.setSize(anim.to.width, anim.to.height);
37675             if (anim.to.x) {
37676                 me.setLeft(anim.to.x);
37677             }
37678             if (anim.to.y) {
37679                 me.setTop(anim.to.y);
37680             }
37681             me.afterExpand(false);
37682         }
37683
37684         return me;
37685     },
37686
37687     afterExpand: function(animated) {
37688         var me = this;
37689         me.setAutoScroll(me.initialConfig.autoScroll);
37690
37691         
37692         if (me.savedFlex) {
37693             me.flex = me.savedFlex;
37694             delete me.savedFlex;
37695             delete me.width;
37696             delete me.height;
37697         }
37698
37699         
37700         delete me.suspendLayout;
37701         if (animated && me.ownerCt) {
37702             me.ownerCt.doLayout();
37703         }
37704
37705         if (me.resizer) {
37706             me.resizer.enable();
37707         }
37708
37709         me.fireEvent('expand', me);
37710
37711         
37712         if (animated && me.collapseTool) {
37713             me.collapseTool.enable();
37714         }
37715     },
37716
37717     
37718     toggleCollapse: function() {
37719         if (this.collapsed) {
37720             this.expand(this.animCollapse);
37721         } else {
37722             this.collapse(this.collapseDirection, this.animCollapse);
37723         }
37724         return this;
37725     },
37726
37727     
37728     getKeyMap : function(){
37729         if(!this.keyMap){
37730             this.keyMap = Ext.create('Ext.util.KeyMap', this.el, this.keys);
37731         }
37732         return this.keyMap;
37733     },
37734
37735     
37736     initDraggable : function(){
37737         
37738         this.dd = Ext.create('Ext.panel.DD', this, Ext.isBoolean(this.draggable) ? null : this.draggable);
37739     },
37740
37741     
37742     ghostTools : function() {
37743         var tools = [],
37744             origTools = this.initialConfig.tools;
37745
37746         if (origTools) {
37747             Ext.each(origTools, function(tool) {
37748                 
37749                 
37750                 
37751                 
37752                 tools.push({
37753                     type: tool.type
37754                 });
37755             });
37756         }
37757         else {
37758             tools = [{
37759                 type: 'placeholder'
37760             }];
37761         }
37762         return tools;
37763     },
37764
37765     
37766     ghost: function(cls) {
37767         var me = this,
37768             ghostPanel = me.ghostPanel,
37769             box = me.getBox();
37770
37771         if (!ghostPanel) {
37772             ghostPanel = Ext.create('Ext.panel.Panel', {
37773                 renderTo: document.body,
37774                 floating: {
37775                     shadow: false
37776                 },
37777                 frame: Ext.supports.CSS3BorderRadius ? me.frame : false,
37778                 title: me.title,
37779                 overlapHeader: me.overlapHeader,
37780                 headerPosition: me.headerPosition,
37781                 width: me.getWidth(),
37782                 height: me.getHeight(),
37783                 iconCls: me.iconCls,
37784                 baseCls: me.baseCls,
37785                 tools: me.ghostTools(),
37786                 cls: me.baseCls + '-ghost ' + (cls ||'')
37787             });
37788             me.ghostPanel = ghostPanel;
37789         }
37790         ghostPanel.floatParent = me.floatParent;
37791         if (me.floating) {
37792             ghostPanel.setZIndex(Ext.Number.from(me.el.getStyle('zIndex'), 0));
37793         } else {
37794             ghostPanel.toFront();
37795         }
37796         ghostPanel.el.show();
37797         ghostPanel.setPosition(box.x, box.y);
37798         ghostPanel.setSize(box.width, box.height);
37799         me.el.hide();
37800         if (me.floatingItems) {
37801             me.floatingItems.hide();
37802         }
37803         return ghostPanel;
37804     },
37805
37806     
37807     unghost: function(show, matchPosition) {
37808         var me = this;
37809         if (!me.ghostPanel) {
37810             return;
37811         }
37812         if (show !== false) {
37813             me.el.show();
37814             if (matchPosition !== false) {
37815                 me.setPosition(me.ghostPanel.getPosition());
37816             }
37817             if (me.floatingItems) {
37818                 me.floatingItems.show();
37819             }
37820             Ext.defer(me.focus, 10, me);
37821         }
37822         me.ghostPanel.el.hide();
37823     },
37824
37825     initResizable: function(resizable) {
37826         if (this.collapsed) {
37827             resizable.disabled = true;
37828         }
37829         this.callParent([resizable]);
37830     }
37831 });
37832
37833
37834
37835 Ext.define('Ext.layout.component.Tip', {
37836
37837     
37838
37839     alias: ['layout.tip'],
37840
37841     extend: 'Ext.layout.component.Dock',
37842
37843     
37844
37845     type: 'tip',
37846     
37847     onLayout: function(width, height) {
37848         var me = this,
37849             owner = me.owner,
37850             el = owner.el,
37851             minWidth,
37852             maxWidth,
37853             naturalWidth,
37854             constrainedWidth,
37855             xy = el.getXY();
37856
37857         
37858         el.setXY([-9999,-9999]);
37859
37860         
37861         this.callParent(arguments);
37862
37863         
37864         if (!Ext.isNumber(width)) {
37865             minWidth = owner.minWidth;
37866             maxWidth = owner.maxWidth;
37867             
37868             if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
37869                 constrainedWidth = me.doAutoWidth();
37870             } else {
37871                 naturalWidth = el.getWidth();
37872             }
37873             if (naturalWidth < minWidth) {
37874                 constrainedWidth = minWidth;
37875             }
37876             else if (naturalWidth > maxWidth) {
37877                 constrainedWidth = maxWidth;
37878             }
37879             if (constrainedWidth) {
37880                 this.callParent([constrainedWidth, height]);
37881             }
37882         }
37883
37884         
37885         el.setXY(xy);
37886     },
37887     
37888     doAutoWidth: function(){
37889         var me = this,
37890             owner = me.owner,
37891             body = owner.body,
37892             width = body.getTextWidth();
37893             
37894         if (owner.header) {
37895             width = Math.max(width, owner.header.getWidth());
37896         }
37897         if (!Ext.isDefined(me.frameWidth)) {
37898             me.frameWidth = owner.el.getWidth() - body.getWidth();
37899         }
37900         width += me.frameWidth + body.getPadding('lr');
37901         return width;
37902     }
37903 });
37904
37905
37906 Ext.define('Ext.tip.Tip', {
37907     extend: 'Ext.panel.Panel',
37908     requires: [ 'Ext.layout.component.Tip' ],
37909     alternateClassName: 'Ext.Tip',
37910     
37911     
37912     
37913     minWidth : 40,
37914     
37915     maxWidth : 300,
37916     
37917     shadow : "sides",
37918
37919     
37920     defaultAlign : "tl-bl?",
37921     
37922     constrainPosition : true,
37923
37924     
37925     frame: false,
37926
37927     
37928     autoRender: true,
37929     hidden: true,
37930     baseCls: Ext.baseCSSPrefix + 'tip',
37931     floating: {
37932         shadow: true,
37933         shim: true,
37934         constrain: true
37935     },
37936     focusOnToFront: false,
37937     componentLayout: 'tip',
37938
37939     closeAction: 'hide',
37940
37941     ariaRole: 'tooltip',
37942
37943     initComponent: function() {
37944         this.callParent(arguments);
37945
37946         
37947         this.constrain = this.constrain || this.constrainPosition;
37948     },
37949
37950     
37951     showAt : function(xy){
37952         var me = this;
37953         this.callParent();
37954         
37955         if (me.isVisible()) {
37956             me.setPagePosition(xy[0], xy[1]);
37957             if (me.constrainPosition || me.constrain) {
37958                 me.doConstrain();
37959             }
37960             me.toFront(true);
37961         }
37962     },
37963
37964     
37965     showBy : function(el, pos) {
37966         this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
37967     },
37968
37969     
37970     initDraggable : function(){
37971         var me = this;
37972         me.draggable = {
37973             el: me.getDragEl(),
37974             delegate: me.header.el,
37975             constrain: me,
37976             constrainTo: me.el.dom.parentNode
37977         };
37978         
37979         Ext.Component.prototype.initDraggable.call(me);
37980     },
37981
37982     
37983     ghost: undefined,
37984     unghost: undefined
37985 });
37986
37987
37988 Ext.define('Ext.tip.ToolTip', {
37989     extend: 'Ext.tip.Tip',
37990     alias: 'widget.tooltip',
37991     alternateClassName: 'Ext.ToolTip',
37992     
37993     
37994     
37995     
37996     showDelay: 500,
37997     
37998     hideDelay: 200,
37999     
38000     dismissDelay: 5000,
38001     
38002     
38003     trackMouse: false,
38004     
38005     
38006     anchorToTarget: true,
38007     
38008     anchorOffset: 0,
38009     
38010
38011     
38012     targetCounter: 0,
38013     quickShowInterval: 250,
38014
38015     
38016     initComponent: function() {
38017         var me = this;
38018         me.callParent(arguments);
38019         me.lastActive = new Date();
38020         me.setTarget(me.target);
38021         me.origAnchor = me.anchor;
38022     },
38023
38024     
38025     onRender: function(ct, position) {
38026         var me = this;
38027         me.callParent(arguments);
38028         me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition();
38029         me.anchorEl = me.el.createChild({
38030             cls: Ext.baseCSSPrefix + 'tip-anchor ' + me.anchorCls
38031         });
38032     },
38033
38034     
38035     afterRender: function() {
38036         var me = this,
38037             zIndex;
38038
38039         me.callParent(arguments);
38040         zIndex = parseInt(me.el.getZIndex(), 10) || 0;
38041         me.anchorEl.setStyle('z-index', zIndex + 1).setVisibilityMode(Ext.core.Element.DISPLAY);
38042     },
38043
38044     
38045     setTarget: function(target) {
38046         var me = this,
38047             t = Ext.get(target),
38048             tg;
38049
38050         if (me.target) {
38051             tg = Ext.get(me.target);
38052             me.mun(tg, 'mouseover', me.onTargetOver, me);
38053             me.mun(tg, 'mouseout', me.onTargetOut, me);
38054             me.mun(tg, 'mousemove', me.onMouseMove, me);
38055         }
38056         
38057         me.target = t;
38058         if (t) {
38059             
38060             me.mon(t, {
38061                 
38062                 
38063                 freezeEvent: true,
38064
38065                 mouseover: me.onTargetOver,
38066                 mouseout: me.onTargetOut,
38067                 mousemove: me.onMouseMove,
38068                 scope: me
38069             });
38070         }
38071         if (me.anchor) {
38072             me.anchorTarget = me.target;
38073         }
38074     },
38075
38076     
38077     onMouseMove: function(e) {
38078         var me = this,
38079             t = me.delegate ? e.getTarget(me.delegate) : me.triggerElement = true,
38080             xy;
38081         if (t) {
38082             me.targetXY = e.getXY();
38083             if (t === me.triggerElement) {
38084                 if (!me.hidden && me.trackMouse) {
38085                     xy = me.getTargetXY();
38086                     if (me.constrainPosition) {
38087                         xy = me.el.adjustForConstraints(xy, me.el.dom.parentNode);
38088                     }
38089                     me.setPagePosition(xy);
38090                 }
38091             } else {
38092                 me.hide();
38093                 me.lastActive = new Date(0);
38094                 me.onTargetOver(e);
38095             }
38096         } else if ((!me.closable && me.isVisible()) && me.autoHide !== false) {
38097             me.hide();
38098         }
38099     },
38100
38101     
38102     getTargetXY: function() {
38103         var me = this,
38104             mouseOffset;
38105         if (me.delegate) {
38106             me.anchorTarget = me.triggerElement;
38107         }
38108         if (me.anchor) {
38109             me.targetCounter++;
38110                 var offsets = me.getOffsets(),
38111                     xy = (me.anchorToTarget && !me.trackMouse) ? me.el.getAlignToXY(me.anchorTarget, me.getAnchorAlign()) : me.targetXY,
38112                     dw = Ext.core.Element.getViewWidth() - 5,
38113                     dh = Ext.core.Element.getViewHeight() - 5,
38114                     de = document.documentElement,
38115                     bd = document.body,
38116                     scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5,
38117                     scrollY = (de.scrollTop || bd.scrollTop || 0) + 5,
38118                     axy = [xy[0] + offsets[0], xy[1] + offsets[1]],
38119                     sz = me.getSize(),
38120                     constrainPosition = me.constrainPosition;
38121
38122             me.anchorEl.removeCls(me.anchorCls);
38123
38124             if (me.targetCounter < 2 && constrainPosition) {
38125                 if (axy[0] < scrollX) {
38126                     if (me.anchorToTarget) {
38127                         me.defaultAlign = 'l-r';
38128                         if (me.mouseOffset) {
38129                             me.mouseOffset[0] *= -1;
38130                         }
38131                     }
38132                     me.anchor = 'left';
38133                     return me.getTargetXY();
38134                 }
38135                 if (axy[0] + sz.width > dw) {
38136                     if (me.anchorToTarget) {
38137                         me.defaultAlign = 'r-l';
38138                         if (me.mouseOffset) {
38139                             me.mouseOffset[0] *= -1;
38140                         }
38141                     }
38142                     me.anchor = 'right';
38143                     return me.getTargetXY();
38144                 }
38145                 if (axy[1] < scrollY) {
38146                     if (me.anchorToTarget) {
38147                         me.defaultAlign = 't-b';
38148                         if (me.mouseOffset) {
38149                             me.mouseOffset[1] *= -1;
38150                         }
38151                     }
38152                     me.anchor = 'top';
38153                     return me.getTargetXY();
38154                 }
38155                 if (axy[1] + sz.height > dh) {
38156                     if (me.anchorToTarget) {
38157                         me.defaultAlign = 'b-t';
38158                         if (me.mouseOffset) {
38159                             me.mouseOffset[1] *= -1;
38160                         }
38161                     }
38162                     me.anchor = 'bottom';
38163                     return me.getTargetXY();
38164                 }
38165             }
38166
38167             me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition();
38168             me.anchorEl.addCls(me.anchorCls);
38169             me.targetCounter = 0;
38170             return axy;
38171         } else {
38172             mouseOffset = me.getMouseOffset();
38173             return (me.targetXY) ? [me.targetXY[0] + mouseOffset[0], me.targetXY[1] + mouseOffset[1]] : mouseOffset;
38174         }
38175     },
38176
38177     getMouseOffset: function() {
38178         var me = this,
38179         offset = me.anchor ? [0, 0] : [15, 18];
38180         if (me.mouseOffset) {
38181             offset[0] += me.mouseOffset[0];
38182             offset[1] += me.mouseOffset[1];
38183         }
38184         return offset;
38185     },
38186
38187     
38188     getAnchorPosition: function() {
38189         var me = this,
38190             m;
38191         if (me.anchor) {
38192             me.tipAnchor = me.anchor.charAt(0);
38193         } else {
38194             m = me.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/);
38195             if (!m) {
38196                 Ext.Error.raise('The AnchorTip.defaultAlign value "' + me.defaultAlign + '" is invalid.');
38197             }
38198             me.tipAnchor = m[1].charAt(0);
38199         }
38200
38201         switch (me.tipAnchor) {
38202         case 't':
38203             return 'top';
38204         case 'b':
38205             return 'bottom';
38206         case 'r':
38207             return 'right';
38208         }
38209         return 'left';
38210     },
38211
38212     
38213     getAnchorAlign: function() {
38214         switch (this.anchor) {
38215         case 'top':
38216             return 'tl-bl';
38217         case 'left':
38218             return 'tl-tr';
38219         case 'right':
38220             return 'tr-tl';
38221         default:
38222             return 'bl-tl';
38223         }
38224     },
38225
38226     
38227     getOffsets: function() {
38228         var me = this,
38229             mouseOffset,
38230             offsets,
38231             ap = me.getAnchorPosition().charAt(0);
38232         if (me.anchorToTarget && !me.trackMouse) {
38233             switch (ap) {
38234             case 't':
38235                 offsets = [0, 9];
38236                 break;
38237             case 'b':
38238                 offsets = [0, -13];
38239                 break;
38240             case 'r':
38241                 offsets = [ - 13, 0];
38242                 break;
38243             default:
38244                 offsets = [9, 0];
38245                 break;
38246             }
38247         } else {
38248             switch (ap) {
38249             case 't':
38250                 offsets = [ - 15 - me.anchorOffset, 30];
38251                 break;
38252             case 'b':
38253                 offsets = [ - 19 - me.anchorOffset, -13 - me.el.dom.offsetHeight];
38254                 break;
38255             case 'r':
38256                 offsets = [ - 15 - me.el.dom.offsetWidth, -13 - me.anchorOffset];
38257                 break;
38258             default:
38259                 offsets = [25, -13 - me.anchorOffset];
38260                 break;
38261             }
38262         }
38263         mouseOffset = me.getMouseOffset();
38264         offsets[0] += mouseOffset[0];
38265         offsets[1] += mouseOffset[1];
38266
38267         return offsets;
38268     },
38269
38270     
38271     onTargetOver: function(e) {
38272         var me = this,
38273             t;
38274
38275         if (me.disabled || e.within(me.target.dom, true)) {
38276             return;
38277         }
38278         t = e.getTarget(me.delegate);
38279         if (t) {
38280             me.triggerElement = t;
38281             me.clearTimer('hide');
38282             me.targetXY = e.getXY();
38283             me.delayShow();
38284         }
38285     },
38286
38287     
38288     delayShow: function() {
38289         var me = this;
38290         if (me.hidden && !me.showTimer) {
38291             if (Ext.Date.getElapsed(me.lastActive) < me.quickShowInterval) {
38292                 me.show();
38293             } else {
38294                 me.showTimer = Ext.defer(me.show, me.showDelay, me);
38295             }
38296         }
38297         else if (!me.hidden && me.autoHide !== false) {
38298             me.show();
38299         }
38300     },
38301
38302     
38303     onTargetOut: function(e) {
38304         var me = this;
38305         if (me.disabled || e.within(me.target.dom, true)) {
38306             return;
38307         }
38308         me.clearTimer('show');
38309         if (me.autoHide !== false) {
38310             me.delayHide();
38311         }
38312     },
38313
38314     
38315     delayHide: function() {
38316         var me = this;
38317         if (!me.hidden && !me.hideTimer) {
38318             me.hideTimer = Ext.defer(me.hide, me.hideDelay, me);
38319         }
38320     },
38321
38322     
38323     hide: function() {
38324         var me = this;
38325         me.clearTimer('dismiss');
38326         me.lastActive = new Date();
38327         if (me.anchorEl) {
38328             me.anchorEl.hide();
38329         }
38330         me.callParent(arguments);
38331         delete me.triggerElement;
38332     },
38333
38334     
38335     show: function() {
38336         var me = this;
38337
38338         
38339         
38340         this.callParent();
38341         if (this.hidden === false) {
38342             me.setPagePosition(-10000, -10000);
38343
38344             if (me.anchor) {
38345                 me.anchor = me.origAnchor;
38346             }
38347             me.showAt(me.getTargetXY());
38348
38349             if (me.anchor) {
38350                 me.syncAnchor();
38351                 me.anchorEl.show();
38352             } else {
38353                 me.anchorEl.hide();
38354             }
38355         }
38356     },
38357
38358     
38359     showAt: function(xy) {
38360         var me = this;
38361         me.lastActive = new Date();
38362         me.clearTimers();
38363
38364         
38365         if (!me.isVisible()) {
38366             this.callParent(arguments);
38367         }
38368
38369         
38370         if (me.isVisible()) {
38371             me.setPagePosition(xy[0], xy[1]);
38372             if (me.constrainPosition || me.constrain) {
38373                 me.doConstrain();
38374             }
38375             me.toFront(true);
38376         }
38377
38378         if (me.dismissDelay && me.autoHide !== false) {
38379             me.dismissTimer = Ext.defer(me.hide, me.dismissDelay, me);
38380         }
38381         if (me.anchor) {
38382             me.syncAnchor();
38383             if (!me.anchorEl.isVisible()) {
38384                 me.anchorEl.show();
38385             }
38386         } else {
38387             me.anchorEl.hide();
38388         }
38389     },
38390
38391     
38392     syncAnchor: function() {
38393         var me = this,
38394             anchorPos,
38395             targetPos,
38396             offset;
38397         switch (me.tipAnchor.charAt(0)) {
38398         case 't':
38399             anchorPos = 'b';
38400             targetPos = 'tl';
38401             offset = [20 + me.anchorOffset, 1];
38402             break;
38403         case 'r':
38404             anchorPos = 'l';
38405             targetPos = 'tr';
38406             offset = [ - 1, 12 + me.anchorOffset];
38407             break;
38408         case 'b':
38409             anchorPos = 't';
38410             targetPos = 'bl';
38411             offset = [20 + me.anchorOffset, -1];
38412             break;
38413         default:
38414             anchorPos = 'r';
38415             targetPos = 'tl';
38416             offset = [1, 12 + me.anchorOffset];
38417             break;
38418         }
38419         me.anchorEl.alignTo(me.el, anchorPos + '-' + targetPos, offset);
38420     },
38421
38422     
38423     setPagePosition: function(x, y) {
38424         var me = this;
38425         me.callParent(arguments);
38426         if (me.anchor) {
38427             me.syncAnchor();
38428         }
38429     },
38430
38431     
38432     clearTimer: function(name) {
38433         name = name + 'Timer';
38434         clearTimeout(this[name]);
38435         delete this[name];
38436     },
38437
38438     
38439     clearTimers: function() {
38440         var me = this;
38441         me.clearTimer('show');
38442         me.clearTimer('dismiss');
38443         me.clearTimer('hide');
38444     },
38445
38446     
38447     onShow: function() {
38448         var me = this;
38449         me.callParent();
38450         me.mon(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me);
38451     },
38452
38453     
38454     onHide: function() {
38455         var me = this;
38456         me.callParent();
38457         me.mun(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me);
38458     },
38459
38460     
38461     onDocMouseDown: function(e) {
38462         var me = this;
38463         if (me.autoHide !== true && !me.closable && !e.within(me.el.dom)) {
38464             me.disable();
38465             Ext.defer(me.doEnable, 100, me);
38466         }
38467     },
38468
38469     
38470     doEnable: function() {
38471         if (!this.isDestroyed) {
38472             this.enable();
38473         }
38474     },
38475
38476     
38477     onDisable: function() {
38478         this.callParent();
38479         this.clearTimers();
38480         this.hide();
38481     },
38482
38483     beforeDestroy: function() {
38484         var me = this;
38485         me.clearTimers();
38486         Ext.destroy(me.anchorEl);
38487         delete me.anchorEl;
38488         delete me.target;
38489         delete me.anchorTarget;
38490         delete me.triggerElement;
38491         me.callParent();
38492     },
38493
38494     
38495     onDestroy: function() {
38496         Ext.getDoc().un('mousedown', this.onDocMouseDown, this);
38497         this.callParent();
38498     }
38499 });
38500
38501
38502 Ext.define('Ext.tip.QuickTip', {
38503     extend: 'Ext.tip.ToolTip',
38504     alternateClassName: 'Ext.QuickTip',
38505     
38506     
38507     interceptTitles : false,
38508
38509     
38510     title: '&#160;',
38511
38512     
38513     tagConfig : {
38514         namespace : "data-",
38515         attribute : "qtip",
38516         width : "qwidth",
38517         target : "target",
38518         title : "qtitle",
38519         hide : "hide",
38520         cls : "qclass",
38521         align : "qalign",
38522         anchor : "anchor"
38523     },
38524
38525     
38526     initComponent : function(){
38527         var me = this;
38528         
38529         me.target = me.target || Ext.getDoc();
38530         me.targets = me.targets || {};
38531         me.callParent();
38532     },
38533
38534     
38535     register : function(config){
38536         var configs = Ext.isArray(config) ? config : arguments,
38537             i = 0,
38538             len = configs.length,
38539             target, j, targetLen;
38540             
38541         for (; i < len; i++) {
38542             config = configs[i];
38543             target = config.target;
38544             if (target) {
38545                 if (Ext.isArray(target)) {
38546                     for (j = 0, targetLen = target.length; j < targetLen; j++) {
38547                         this.targets[Ext.id(target[j])] = config;
38548                     }
38549                 } else{
38550                     this.targets[Ext.id(target)] = config;
38551                 }
38552             }
38553         }
38554     },
38555
38556     
38557     unregister : function(el){
38558         delete this.targets[Ext.id(el)];
38559     },
38560     
38561     
38562     cancelShow: function(el){
38563         var me = this,
38564             activeTarget = me.activeTarget;
38565             
38566         el = Ext.get(el).dom;
38567         if (me.isVisible()) {
38568             if (activeTarget && activeTarget.el == el) {
38569                 me.hide();
38570             }
38571         } else if (activeTarget && activeTarget.el == el) {
38572             me.clearTimer('show');
38573         }
38574     },
38575     
38576     getTipCfg: function(e) {
38577         var t = e.getTarget(),
38578             ttp, 
38579             cfg;
38580         
38581         if(this.interceptTitles && t.title && Ext.isString(t.title)){
38582             ttp = t.title;
38583             t.qtip = ttp;
38584             t.removeAttribute("title");
38585             e.preventDefault();
38586         } 
38587         else {            
38588             cfg = this.tagConfig;
38589             t = e.getTarget('[' + cfg.namespace + cfg.attribute + ']');
38590             if (t) {
38591                 ttp = t.getAttribute(cfg.namespace + cfg.attribute);
38592             }
38593         }
38594         return ttp;
38595     },
38596
38597     
38598     onTargetOver : function(e){
38599         var me = this,
38600             target = e.getTarget(),
38601             elTarget,
38602             cfg,
38603             ns,
38604             ttp,
38605             autoHide;
38606         
38607         if (me.disabled) {
38608             return;
38609         }
38610
38611         
38612         
38613         
38614         me.targetXY = e.getXY();
38615
38616         if(!target || target.nodeType !== 1 || target == document || target == document.body){
38617             return;
38618         }
38619         
38620         if (me.activeTarget && ((target == me.activeTarget.el) || Ext.fly(me.activeTarget.el).contains(target))) {
38621             me.clearTimer('hide');
38622             me.show();
38623             return;
38624         }
38625         
38626         if (target) {
38627             Ext.Object.each(me.targets, function(key, value) {
38628                 var targetEl = Ext.fly(value.target);
38629                 if (targetEl && (targetEl.dom === target || targetEl.contains(target))) {
38630                     elTarget = targetEl.dom;
38631                     return false;
38632                 }
38633             });
38634             if (elTarget) {
38635                 me.activeTarget = me.targets[elTarget.id];
38636                 me.activeTarget.el = target;
38637                 me.anchor = me.activeTarget.anchor;
38638                 if (me.anchor) {
38639                     me.anchorTarget = target;
38640                 }
38641                 me.delayShow();
38642                 return;
38643             }
38644         }
38645
38646         elTarget = Ext.get(target);
38647         cfg = me.tagConfig;
38648         ns = cfg.namespace; 
38649         ttp = me.getTipCfg(e);
38650         
38651         if (ttp) {
38652             autoHide = elTarget.getAttribute(ns + cfg.hide);
38653                  
38654             me.activeTarget = {
38655                 el: target,
38656                 text: ttp,
38657                 width: +elTarget.getAttribute(ns + cfg.width) || null,
38658                 autoHide: autoHide != "user" && autoHide !== 'false',
38659                 title: elTarget.getAttribute(ns + cfg.title),
38660                 cls: elTarget.getAttribute(ns + cfg.cls),
38661                 align: elTarget.getAttribute(ns + cfg.align)
38662                 
38663             };
38664             me.anchor = elTarget.getAttribute(ns + cfg.anchor);
38665             if (me.anchor) {
38666                 me.anchorTarget = target;
38667             }
38668             me.delayShow();
38669         }
38670     },
38671
38672     
38673     onTargetOut : function(e){
38674         var me = this;
38675         
38676         
38677         if (me.activeTarget && e.within(me.activeTarget.el) && !me.getTipCfg(e)) {
38678             return;
38679         }
38680
38681         me.clearTimer('show');
38682         if (me.autoHide !== false) {
38683             me.delayHide();
38684         }
38685     },
38686
38687     
38688     showAt : function(xy){
38689         var me = this,
38690             target = me.activeTarget;
38691         
38692         if (target) {
38693             if (!me.rendered) {
38694                 me.render(Ext.getBody());
38695                 me.activeTarget = target;
38696             }
38697             if (target.title) {
38698                 me.setTitle(target.title || '');
38699                 me.header.show();
38700             } else {
38701                 me.header.hide();
38702             }
38703             me.body.update(target.text);
38704             me.autoHide = target.autoHide;
38705             me.dismissDelay = target.dismissDelay || me.dismissDelay;
38706             if (me.lastCls) {
38707                 me.el.removeCls(me.lastCls);
38708                 delete me.lastCls;
38709             }
38710             if (target.cls) {
38711                 me.el.addCls(target.cls);
38712                 me.lastCls = target.cls;
38713             }
38714
38715             me.setWidth(target.width);
38716             
38717             if (me.anchor) {
38718                 me.constrainPosition = false;
38719             } else if (target.align) { 
38720                 xy = me.el.getAlignToXY(target.el, target.align);
38721                 me.constrainPosition = false;
38722             }else{
38723                 me.constrainPosition = true;
38724             }
38725         }
38726         me.callParent([xy]);
38727     },
38728
38729     
38730     hide: function(){
38731         delete this.activeTarget;
38732         this.callParent();
38733     }
38734 });
38735
38736
38737 Ext.define('Ext.tip.QuickTipManager', function() {
38738     var tip,
38739         disabled = false;
38740
38741     return {
38742         requires: ['Ext.tip.QuickTip'],
38743         singleton: true,
38744         alternateClassName: 'Ext.QuickTips',
38745
38746         
38747         init : function (autoRender, config) {
38748             if (!tip) {
38749                 if (!Ext.isReady) {
38750                     Ext.onReady(function(){
38751                         Ext.tip.QuickTipManager.init(autoRender);
38752                     });
38753                     return;
38754                 }
38755
38756                 var tipConfig = Ext.apply({ disabled: disabled }, config),
38757                     className = tipConfig.className,
38758                     xtype = tipConfig.xtype;
38759
38760                 if (className) {
38761                     delete tipConfig.className;
38762                 } else if (xtype) {
38763                     className = 'widget.' + xtype;
38764                     delete tipConfig.xtype;
38765                 }
38766
38767                 if (autoRender !== false) {
38768                     tipConfig.renderTo = document.body;
38769
38770                     if (tipConfig.renderTo.tagName != 'BODY') { 
38771                         Ext.Error.raise({
38772                             sourceClass: 'Ext.tip.QuickTipManager',
38773                             sourceMethod: 'init',
38774                             msg: 'Cannot init QuickTipManager: no document body'
38775                         });
38776                     }
38777                 }
38778
38779                 tip = Ext.create(className || 'Ext.tip.QuickTip', tipConfig);
38780             }
38781         },
38782
38783         
38784         destroy: function() {
38785             if (tip) {
38786                 var undef;
38787                 tip.destroy();
38788                 tip = undef;
38789             }
38790         },
38791
38792         
38793         ddDisable : function(){
38794             
38795             if(tip && !disabled){
38796                 tip.disable();
38797             }
38798         },
38799
38800         
38801         ddEnable : function(){
38802             
38803             if(tip && !disabled){
38804                 tip.enable();
38805             }
38806         },
38807
38808         
38809         enable : function(){
38810             if(tip){
38811                 tip.enable();
38812             }
38813             disabled = false;
38814         },
38815
38816         
38817         disable : function(){
38818             if(tip){
38819                 tip.disable();
38820             }
38821             disabled = true;
38822         },
38823
38824         
38825         isEnabled : function(){
38826             return tip !== undefined && !tip.disabled;
38827         },
38828
38829         
38830         getQuickTip : function(){
38831             return tip;
38832         },
38833
38834         
38835         register : function(){
38836             tip.register.apply(tip, arguments);
38837         },
38838
38839         
38840         unregister : function(){
38841             tip.unregister.apply(tip, arguments);
38842         },
38843
38844         
38845         tips : function(){
38846             tip.register.apply(tip, arguments);
38847         }
38848     };
38849 }());
38850
38851 Ext.define('Ext.app.Application', {
38852     extend: 'Ext.app.Controller',
38853
38854     requires: [
38855         'Ext.ModelManager',
38856         'Ext.data.Model',
38857         'Ext.data.StoreManager',
38858         'Ext.tip.QuickTipManager',
38859         'Ext.ComponentManager',
38860         'Ext.app.EventBus'
38861     ],
38862
38863     
38864
38865     
38866     scope: undefined,
38867
38868     
38869     enableQuickTips: true,
38870
38871     
38872
38873     
38874     appFolder: 'app',
38875
38876     
38877     autoCreateViewport: false,
38878
38879     constructor: function(config) {
38880         config = config || {};
38881         Ext.apply(this, config);
38882
38883         var requires = config.requires || [];
38884
38885         Ext.Loader.setPath(this.name, this.appFolder);
38886
38887         if (this.paths) {
38888             Ext.Object.each(this.paths, function(key, value) {
38889                 Ext.Loader.setPath(key, value);
38890             });
38891         }
38892
38893         this.callParent(arguments);
38894
38895         this.eventbus = Ext.create('Ext.app.EventBus');
38896
38897         var controllers = Ext.Array.from(this.controllers),
38898             ln = controllers && controllers.length,
38899             i, controller;
38900
38901         this.controllers = Ext.create('Ext.util.MixedCollection');
38902
38903         if (this.autoCreateViewport) {
38904             requires.push(this.getModuleClassName('Viewport', 'view'));
38905         }
38906
38907         for (i = 0; i < ln; i++) {
38908             requires.push(this.getModuleClassName(controllers[i], 'controller'));
38909         }
38910
38911         Ext.require(requires);
38912
38913         Ext.onReady(function() {
38914             for (i = 0; i < ln; i++) {
38915                 controller = this.getController(controllers[i]);
38916                 controller.init(this);
38917             }
38918
38919             this.onBeforeLaunch.call(this);
38920         }, this);
38921     },
38922
38923     control: function(selectors, listeners, controller) {
38924         this.eventbus.control(selectors, listeners, controller);
38925     },
38926
38927     
38928     launch: Ext.emptyFn,
38929
38930     
38931     onBeforeLaunch: function() {
38932         if (this.enableQuickTips) {
38933             Ext.tip.QuickTipManager.init();
38934         }
38935
38936         if (this.autoCreateViewport) {
38937             this.getView('Viewport').create();
38938         }
38939
38940         this.launch.call(this.scope || this);
38941         this.launched = true;
38942         this.fireEvent('launch', this);
38943
38944         this.controllers.each(function(controller) {
38945             controller.onLaunch(this);
38946         }, this);
38947     },
38948
38949     getModuleClassName: function(name, type) {
38950         var namespace = Ext.Loader.getPrefix(name);
38951
38952         if (namespace.length > 0 && namespace !== name) {
38953             return name;
38954         }
38955
38956         return this.name + '.' + type + '.' + name;
38957     },
38958
38959     getController: function(name) {
38960         var controller = this.controllers.get(name);
38961
38962         if (!controller) {
38963             controller = Ext.create(this.getModuleClassName(name, 'controller'), {
38964                 application: this,
38965                 id: name
38966             });
38967
38968             this.controllers.add(controller);
38969         }
38970
38971         return controller;
38972     },
38973
38974     getStore: function(name) {
38975         var store = Ext.StoreManager.get(name);
38976
38977         if (!store) {
38978             store = Ext.create(this.getModuleClassName(name, 'store'), {
38979                 storeId: name
38980             });
38981         }
38982
38983         return store;
38984     },
38985
38986     getModel: function(model) {
38987         model = this.getModuleClassName(model, 'model');
38988
38989         return Ext.ModelManager.getModel(model);
38990     },
38991
38992     getView: function(view) {
38993         view = this.getModuleClassName(view, 'view');
38994
38995         return Ext.ClassManager.get(view);
38996     }
38997 });
38998
38999
39000 Ext.define('Ext.chart.Callout', {
39001
39002     
39003
39004     
39005
39006     constructor: function(config) {
39007         if (config.callouts) {
39008             config.callouts.styles = Ext.applyIf(config.callouts.styles || {}, {
39009                 color: "#000",
39010                 font: "11px Helvetica, sans-serif"
39011             });
39012             this.callouts = Ext.apply(this.callouts || {}, config.callouts);
39013             this.calloutsArray = [];
39014         }
39015     },
39016
39017     renderCallouts: function() {
39018         if (!this.callouts) {
39019             return;
39020         }
39021
39022         var me = this,
39023             items = me.items,
39024             animate = me.chart.animate,
39025             config = me.callouts,
39026             styles = config.styles,
39027             group = me.calloutsArray,
39028             store = me.chart.store,
39029             len = store.getCount(),
39030             ratio = items.length / len,
39031             previouslyPlacedCallouts = [],
39032             i,
39033             count,
39034             j,
39035             p;
39036             
39037         for (i = 0, count = 0; i < len; i++) {
39038             for (j = 0; j < ratio; j++) {
39039                 var item = items[count],
39040                     label = group[count],
39041                     storeItem = store.getAt(i),
39042                     display;
39043                 
39044                 display = config.filter(storeItem);
39045                 
39046                 if (!display && !label) {
39047                     count++;
39048                     continue;               
39049                 }
39050                 
39051                 if (!label) {
39052                     group[count] = label = me.onCreateCallout(storeItem, item, i, display, j, count);
39053                 }
39054                 for (p in label) {
39055                     if (label[p] && label[p].setAttributes) {
39056                         label[p].setAttributes(styles, true);
39057                     }
39058                 }
39059                 if (!display) {
39060                     for (p in label) {
39061                         if (label[p]) {
39062                             if (label[p].setAttributes) {
39063                                 label[p].setAttributes({
39064                                     hidden: true
39065                                 }, true);
39066                             } else if(label[p].setVisible) {
39067                                 label[p].setVisible(false);
39068                             }
39069                         }
39070                     }
39071                 }
39072                 config.renderer(label, storeItem);
39073                 me.onPlaceCallout(label, storeItem, item, i, display, animate,
39074                                   j, count, previouslyPlacedCallouts);
39075                 previouslyPlacedCallouts.push(label);
39076                 count++;
39077             }
39078         }
39079         this.hideCallouts(count);
39080     },
39081
39082     onCreateCallout: function(storeItem, item, i, display) {
39083         var me = this,
39084             group = me.calloutsGroup,
39085             config = me.callouts,
39086             styles = config.styles,
39087             width = styles.width,
39088             height = styles.height,
39089             chart = me.chart,
39090             surface = chart.surface,
39091             calloutObj = {
39092                 
39093                 
39094                 lines: false
39095             };
39096
39097         calloutObj.lines = surface.add(Ext.apply({},
39098         {
39099             type: 'path',
39100             path: 'M0,0',
39101             stroke: me.getLegendColor() || '#555'
39102         },
39103         styles));
39104
39105         if (config.items) {
39106             calloutObj.panel = Ext.create('widget.panel', {
39107                 style: "position: absolute;",    
39108                 width: width,
39109                 height: height,
39110                 items: config.items,
39111                 renderTo: chart.el
39112             });
39113         }
39114
39115         return calloutObj;
39116     },
39117
39118     hideCallouts: function(index) {
39119         var calloutsArray = this.calloutsArray,
39120             len = calloutsArray.length,
39121             co,
39122             p;
39123         while (len-->index) {
39124             co = calloutsArray[len];
39125             for (p in co) {
39126                 if (co[p]) {
39127                     co[p].hide(true);
39128                 }
39129             }
39130         }
39131     }
39132 });
39133
39134
39135 Ext.define('Ext.draw.CompositeSprite', {
39136
39137     
39138
39139     extend: 'Ext.util.MixedCollection',
39140     mixins: {
39141         animate: 'Ext.util.Animate'
39142     },
39143
39144     
39145     isCompositeSprite: true,
39146     constructor: function(config) {
39147         var me = this;
39148         
39149         config = config || {};
39150         Ext.apply(me, config);
39151
39152         me.addEvents(
39153             'mousedown',
39154             'mouseup',
39155             'mouseover',
39156             'mouseout',
39157             'click'
39158         );
39159         me.id = Ext.id(null, 'ext-sprite-group-');
39160         me.callParent();
39161     },
39162
39163     
39164     onClick: function(e) {
39165         this.fireEvent('click', e);
39166     },
39167
39168     
39169     onMouseUp: function(e) {
39170         this.fireEvent('mouseup', e);
39171     },
39172
39173     
39174     onMouseDown: function(e) {
39175         this.fireEvent('mousedown', e);
39176     },
39177
39178     
39179     onMouseOver: function(e) {
39180         this.fireEvent('mouseover', e);
39181     },
39182
39183     
39184     onMouseOut: function(e) {
39185         this.fireEvent('mouseout', e);
39186     },
39187
39188     attachEvents: function(o) {
39189         var me = this;
39190         
39191         o.on({
39192             scope: me,
39193             mousedown: me.onMouseDown,
39194             mouseup: me.onMouseUp,
39195             mouseover: me.onMouseOver,
39196             mouseout: me.onMouseOut,
39197             click: me.onClick
39198         });
39199     },
39200
39201     
39202     add: function(key, o) {
39203         var result = this.callParent(arguments);
39204         this.attachEvents(result);
39205         return result;
39206     },
39207
39208     insert: function(index, key, o) {
39209         return this.callParent(arguments);
39210     },
39211
39212     
39213     remove: function(o) {
39214         var me = this;
39215         
39216         o.un({
39217             scope: me,
39218             mousedown: me.onMouseDown,
39219             mouseup: me.onMouseUp,
39220             mouseover: me.onMouseOver,
39221             mouseout: me.onMouseOut,
39222             click: me.onClick
39223         });
39224         me.callParent(arguments);
39225     },
39226     
39227     
39228     getBBox: function() {
39229         var i = 0,
39230             sprite,
39231             bb,
39232             items = this.items,
39233             len = this.length,
39234             infinity = Infinity,
39235             minX = infinity,
39236             maxHeight = -infinity,
39237             minY = infinity,
39238             maxWidth = -infinity,
39239             maxWidthBBox, maxHeightBBox;
39240         
39241         for (; i < len; i++) {
39242             sprite = items[i];
39243             if (sprite.el) {
39244                 bb = sprite.getBBox();
39245                 minX = Math.min(minX, bb.x);
39246                 minY = Math.min(minY, bb.y);
39247                 maxHeight = Math.max(maxHeight, bb.height + bb.y);
39248                 maxWidth = Math.max(maxWidth, bb.width + bb.x);
39249             }
39250         }
39251         
39252         return {
39253             x: minX,
39254             y: minY,
39255             height: maxHeight - minY,
39256             width: maxWidth - minX
39257         };
39258     },
39259
39260     
39261     setAttributes: function(attrs, redraw) {
39262         var i = 0,
39263             items = this.items,
39264             len = this.length;
39265             
39266         for (; i < len; i++) {
39267             items[i].setAttributes(attrs, redraw);
39268         }
39269         return this;
39270     },
39271
39272     
39273     hide: function(redraw) {
39274         var i = 0,
39275             items = this.items,
39276             len = this.length;
39277             
39278         for (; i < len; i++) {
39279             items[i].hide(redraw);
39280         }
39281         return this;
39282     },
39283
39284     
39285     show: function(redraw) {
39286         var i = 0,
39287             items = this.items,
39288             len = this.length;
39289             
39290         for (; i < len; i++) {
39291             items[i].show(redraw);
39292         }
39293         return this;
39294     },
39295
39296     redraw: function() {
39297         var me = this,
39298             i = 0,
39299             items = me.items,
39300             surface = me.getSurface(),
39301             len = me.length;
39302         
39303         if (surface) {
39304             for (; i < len; i++) {
39305                 surface.renderItem(items[i]);
39306             }
39307         }
39308         return me;
39309     },
39310
39311     setStyle: function(obj) {
39312         var i = 0,
39313             items = this.items,
39314             len = this.length,
39315             item, el;
39316             
39317         for (; i < len; i++) {
39318             item = items[i];
39319             el = item.el;
39320             if (el) {
39321                 el.setStyle(obj);
39322             }
39323         }
39324     },
39325
39326     addCls: function(obj) {
39327         var i = 0,
39328             items = this.items,
39329             surface = this.getSurface(),
39330             len = this.length;
39331         
39332         if (surface) {
39333             for (; i < len; i++) {
39334                 surface.addCls(items[i], obj);
39335             }
39336         }
39337     },
39338
39339     removeCls: function(obj) {
39340         var i = 0,
39341             items = this.items,
39342             surface = this.getSurface(),
39343             len = this.length;
39344         
39345         if (surface) {
39346             for (; i < len; i++) {
39347                 surface.removeCls(items[i], obj);
39348             }
39349         }
39350     },
39351     
39352     
39353     getSurface: function(){
39354         var first = this.first();
39355         if (first) {
39356             return first.surface;
39357         }
39358         return null;
39359     },
39360     
39361     
39362     destroy: function(){
39363         var me = this,
39364             surface = me.getSurface(),
39365             item;
39366             
39367         if (surface) {
39368             while (me.getCount() > 0) {
39369                 item = me.first();
39370                 me.remove(item);
39371                 surface.remove(item);
39372             }
39373         }
39374         me.clearListeners();
39375     }
39376 });
39377
39378
39379
39380 Ext.define('Ext.layout.component.Draw', {
39381
39382     
39383
39384     alias: 'layout.draw',
39385
39386     extend: 'Ext.layout.component.Auto',
39387
39388     
39389
39390     type: 'draw',
39391
39392     onLayout : function(width, height) {
39393         this.owner.surface.setSize(width, height);
39394         this.callParent(arguments);
39395     }
39396 });
39397
39398 Ext.define('Ext.chart.theme.Theme', {
39399
39400     
39401
39402     requires: ['Ext.draw.Color'],
39403
39404     
39405
39406     theme: 'Base',
39407     themeAttrs: false,
39408     
39409     initTheme: function(theme) {
39410         var me = this,
39411             themes = Ext.chart.theme,
39412             key, gradients;
39413         if (theme) {
39414             theme = theme.split(':');
39415             for (key in themes) {
39416                 if (key == theme[0]) {
39417                     gradients = theme[1] == 'gradients';
39418                     me.themeAttrs = new themes[key]({
39419                         useGradients: gradients
39420                     });
39421                     if (gradients) {
39422                         me.gradients = me.themeAttrs.gradients;
39423                     }
39424                     if (me.themeAttrs.background) {
39425                         me.background = me.themeAttrs.background;
39426                     }
39427                     return;
39428                 }
39429             }
39430             Ext.Error.raise('No theme found named "' + theme + '"');
39431         }
39432     }
39433 }, 
39434
39435 function() {
39436    
39437
39438 (function() {
39439     Ext.chart.theme = function(config, base) {
39440         config = config || {};
39441         var i = 0, l, colors, color,
39442             seriesThemes, markerThemes,
39443             seriesTheme, markerTheme, 
39444             key, gradients = [],
39445             midColor, midL;
39446         
39447         if (config.baseColor) {
39448             midColor = Ext.draw.Color.fromString(config.baseColor);
39449             midL = midColor.getHSL()[2];
39450             if (midL < 0.15) {
39451                 midColor = midColor.getLighter(0.3);
39452             } else if (midL < 0.3) {
39453                 midColor = midColor.getLighter(0.15);
39454             } else if (midL > 0.85) {
39455                 midColor = midColor.getDarker(0.3);
39456             } else if (midL > 0.7) {
39457                 midColor = midColor.getDarker(0.15);
39458             }
39459             config.colors = [ midColor.getDarker(0.3).toString(),
39460                               midColor.getDarker(0.15).toString(),
39461                               midColor.toString(),
39462                               midColor.getLighter(0.15).toString(),
39463                               midColor.getLighter(0.3).toString()];
39464
39465             delete config.baseColor;
39466         }
39467         if (config.colors) {
39468             colors = config.colors.slice();
39469             markerThemes = base.markerThemes;
39470             seriesThemes = base.seriesThemes;
39471             l = colors.length;
39472             base.colors = colors;
39473             for (; i < l; i++) {
39474                 color = colors[i];
39475                 markerTheme = markerThemes[i] || {};
39476                 seriesTheme = seriesThemes[i] || {};
39477                 markerTheme.fill = seriesTheme.fill = markerTheme.stroke = seriesTheme.stroke = color;
39478                 markerThemes[i] = markerTheme;
39479                 seriesThemes[i] = seriesTheme;
39480             }
39481             base.markerThemes = markerThemes.slice(0, l);
39482             base.seriesThemes = seriesThemes.slice(0, l);
39483         
39484         }
39485         for (key in base) {
39486             if (key in config) {
39487                 if (Ext.isObject(config[key]) && Ext.isObject(base[key])) {
39488                     Ext.apply(base[key], config[key]);
39489                 } else {
39490                     base[key] = config[key];
39491                 }
39492             }
39493         }
39494         if (config.useGradients) {
39495             colors = base.colors || (function () {
39496                 var ans = [];
39497                 for (i = 0, seriesThemes = base.seriesThemes, l = seriesThemes.length; i < l; i++) {
39498                     ans.push(seriesThemes[i].fill || seriesThemes[i].stroke);
39499                 }
39500                 return ans;
39501             })();
39502             for (i = 0, l = colors.length; i < l; i++) {
39503                 midColor = Ext.draw.Color.fromString(colors[i]);
39504                 if (midColor) {
39505                     color = midColor.getDarker(0.1).toString();
39506                     midColor = midColor.toString();
39507                     key = 'theme-' + midColor.substr(1) + '-' + color.substr(1);
39508                     gradients.push({
39509                         id: key,
39510                         angle: 45,
39511                         stops: {
39512                             0: {
39513                                 color: midColor.toString()
39514                             },
39515                             100: {
39516                                 color: color.toString()
39517                             }
39518                         }
39519                     });
39520                     colors[i] = 'url(#' + key + ')'; 
39521                 }
39522             }
39523             base.gradients = gradients;
39524             base.colors = colors;
39525         }
39526         
39527         Ext.apply(this, base);
39528     };
39529 })();
39530 });
39531
39532
39533 Ext.define('Ext.chart.Mask', {
39534     constructor: function(config) {
39535         var me = this;
39536
39537         me.addEvents('select');
39538
39539         if (config) {
39540             Ext.apply(me, config);
39541         }
39542         if (me.mask) {
39543             me.on('afterrender', function() {
39544                 
39545                 var comp = Ext.create('Ext.chart.MaskLayer', {
39546                     renderTo: me.el
39547                 });
39548                 comp.el.on({
39549                     'mousemove': function(e) {
39550                         me.onMouseMove(e);
39551                     },
39552                     'mouseup': function(e) {
39553                         me.resized(e);
39554                     }
39555                 });
39556                 
39557                 var resizeHandler = Ext.create('Ext.resizer.Resizer', {
39558                     el: comp.el,
39559                     handles: 'all',
39560                     pinned: true
39561                 });
39562                 resizeHandler.on({
39563                     'resize': function(e) {
39564                         me.resized(e);    
39565                     }    
39566                 });
39567                 comp.initDraggable();
39568                 me.maskType = me.mask;
39569                 me.mask = comp;
39570                 me.maskSprite = me.surface.add({
39571                     type: 'path',
39572                     path: ['M', 0, 0],
39573                     zIndex: 1001,
39574                     opacity: 0.7,
39575                     hidden: true,
39576                     stroke: '#444'
39577                 });
39578             }, me, { single: true });
39579         }
39580     },
39581     
39582     resized: function(e) {
39583         var me = this,
39584             bbox = me.bbox || me.chartBBox,
39585             x = bbox.x,
39586             y = bbox.y,
39587             width = bbox.width,
39588             height = bbox.height,
39589             box = me.mask.getBox(true),
39590             max = Math.max,
39591             min = Math.min,
39592             staticX = box.x - x,
39593             staticY = box.y - y;
39594         
39595         staticX = max(staticX, x);
39596         staticY = max(staticY, y);
39597         staticX = min(staticX, width);
39598         staticY = min(staticY, height);
39599         box.x = staticX;
39600         box.y = staticY;
39601         me.fireEvent('select', me, box);
39602     },
39603
39604     onMouseUp: function(e) {
39605         var me = this,
39606             bbox = me.bbox || me.chartBBox,
39607             sel = me.maskSelection;
39608         me.maskMouseDown = false;
39609         me.mouseDown = false;
39610         if (me.mouseMoved) {
39611             me.onMouseMove(e);
39612             me.mouseMoved = false;
39613             me.fireEvent('select', me, {
39614                 x: sel.x - bbox.x,
39615                 y: sel.y - bbox.y,
39616                 width: sel.width,
39617                 height: sel.height
39618             });
39619         }
39620     },
39621
39622     onMouseDown: function(e) {
39623         var me = this;
39624         me.mouseDown = true;
39625         me.mouseMoved = false;
39626         me.maskMouseDown = {
39627             x: e.getPageX() - me.el.getX(),
39628             y: e.getPageY() - me.el.getY()
39629         };
39630     },
39631
39632     onMouseMove: function(e) {
39633         var me = this,
39634             mask = me.maskType,
39635             bbox = me.bbox || me.chartBBox,
39636             x = bbox.x,
39637             y = bbox.y,
39638             math = Math,
39639             floor = math.floor,
39640             abs = math.abs,
39641             min = math.min,
39642             max = math.max,
39643             height = floor(y + bbox.height),
39644             width = floor(x + bbox.width),
39645             posX = e.getPageX(),
39646             posY = e.getPageY(),
39647             staticX = posX - me.el.getX(),
39648             staticY = posY - me.el.getY(),
39649             maskMouseDown = me.maskMouseDown,
39650             path;
39651         
39652         me.mouseMoved = me.mouseDown;
39653         staticX = max(staticX, x);
39654         staticY = max(staticY, y);
39655         staticX = min(staticX, width);
39656         staticY = min(staticY, height);
39657         if (maskMouseDown && me.mouseDown) {
39658             if (mask == 'horizontal') {
39659                 staticY = y;
39660                 maskMouseDown.y = height;
39661                 posY = me.el.getY() + bbox.height + me.insetPadding;
39662             }
39663             else if (mask == 'vertical') {
39664                 staticX = x;
39665                 maskMouseDown.x = width;
39666             }
39667             width = maskMouseDown.x - staticX;
39668             height = maskMouseDown.y - staticY;
39669             path = ['M', staticX, staticY, 'l', width, 0, 0, height, -width, 0, 'z'];
39670             me.maskSelection = {
39671                 x: width > 0 ? staticX : staticX + width,
39672                 y: height > 0 ? staticY : staticY + height,
39673                 width: abs(width),
39674                 height: abs(height)
39675             };
39676             me.mask.updateBox({
39677                 x: posX - abs(width),
39678                 y: posY - abs(height),
39679                 width: abs(width),
39680                 height: abs(height)
39681             });
39682             me.mask.show();
39683             me.maskSprite.setAttributes({
39684                 hidden: true    
39685             }, true);
39686         }
39687         else {
39688             if (mask == 'horizontal') {
39689                 path = ['M', staticX, y, 'L', staticX, height];
39690             }
39691             else if (mask == 'vertical') {
39692                 path = ['M', x, staticY, 'L', width, staticY];
39693             }
39694             else {
39695                 path = ['M', staticX, y, 'L', staticX, height, 'M', x, staticY, 'L', width, staticY];
39696             }
39697             me.maskSprite.setAttributes({
39698                 path: path,
39699                 fill: me.maskMouseDown ? me.maskSprite.stroke : false,
39700                 'stroke-width': mask === true ? 1 : 3,
39701                 hidden: false
39702             }, true);
39703         }
39704     },
39705
39706     onMouseLeave: function(e) {
39707         var me = this;
39708         me.mouseMoved = false;
39709         me.mouseDown = false;
39710         me.maskMouseDown = false;
39711         me.mask.hide();
39712         me.maskSprite.hide(true);
39713     }
39714 });
39715     
39716
39717 Ext.define('Ext.chart.Navigation', {
39718
39719     constructor: function() {
39720         this.originalStore = this.store;
39721     },
39722     
39723     
39724     setZoom: function(zoomConfig) {
39725         var me = this,
39726             store = me.substore || me.store,
39727             bbox = me.chartBBox,
39728             len = store.getCount(),
39729             from = (zoomConfig.x / bbox.width * len) >> 0,
39730             to = Math.ceil(((zoomConfig.x + zoomConfig.width) / bbox.width * len)),
39731             recFieldsLen, recFields = [], curField, json = [], obj;
39732         
39733         store.each(function(rec, i) {
39734             if (i < from || i > to) {
39735                 return;
39736             }
39737             obj = {};
39738             
39739             if (!recFields.length) {
39740                 rec.fields.each(function(f) {
39741                     recFields.push(f.name);
39742                 });
39743                 recFieldsLen = recFields.length;
39744             }
39745             
39746             for (i = 0; i < recFieldsLen; i++) {
39747                 curField = recFields[i];
39748                 obj[curField] = rec.get(curField);
39749             }
39750             json.push(obj);
39751         });
39752         me.store = me.substore = Ext.create('Ext.data.JsonStore', {
39753             fields: recFields,
39754             data: json
39755         });
39756         me.redraw(true);
39757     },
39758
39759     restoreZoom: function() {
39760         this.store = this.substore = this.originalStore;
39761         this.redraw(true);
39762     }
39763     
39764 });
39765
39766 Ext.define('Ext.chart.Shape', {
39767
39768     
39769
39770     singleton: true,
39771
39772     
39773
39774     circle: function (surface, opts) {
39775         return surface.add(Ext.apply({
39776             type: 'circle',
39777             x: opts.x,
39778             y: opts.y,
39779             stroke: null,
39780             radius: opts.radius
39781         }, opts));
39782     },
39783     line: function (surface, opts) {
39784         return surface.add(Ext.apply({
39785             type: 'rect',
39786             x: opts.x - opts.radius,
39787             y: opts.y - opts.radius,
39788             height: 2 * opts.radius,
39789             width: 2 * opts.radius / 5
39790         }, opts));
39791     },
39792     square: function (surface, opts) {
39793         return surface.add(Ext.applyIf({
39794             type: 'rect',
39795             x: opts.x - opts.radius,
39796             y: opts.y - opts.radius,
39797             height: 2 * opts.radius,
39798             width: 2 * opts.radius,
39799             radius: null
39800         }, opts));
39801     },
39802     triangle: function (surface, opts) {
39803         opts.radius *= 1.75;
39804         return surface.add(Ext.apply({
39805             type: 'path',
39806             stroke: null,
39807             path: "M".concat(opts.x, ",", opts.y, "m0-", opts.radius * 0.58, "l", opts.radius * 0.5, ",", opts.radius * 0.87, "-", opts.radius, ",0z")
39808         }, opts));
39809     },
39810     diamond: function (surface, opts) {
39811         var r = opts.radius;
39812         r *= 1.5;
39813         return surface.add(Ext.apply({
39814             type: 'path',
39815             stroke: null,
39816             path: ["M", opts.x, opts.y - r, "l", r, r, -r, r, -r, -r, r, -r, "z"]
39817         }, opts));
39818     },
39819     cross: function (surface, opts) {
39820         var r = opts.radius;
39821         r = r / 1.7;
39822         return surface.add(Ext.apply({
39823             type: 'path',
39824             stroke: null,
39825             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"])
39826         }, opts));
39827     },
39828     plus: function (surface, opts) {
39829         var r = opts.radius / 1.3;
39830         return surface.add(Ext.apply({
39831             type: 'path',
39832             stroke: null,
39833             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"])
39834         }, opts));
39835     },
39836     arrow: function (surface, opts) {
39837         var r = opts.radius;
39838         return surface.add(Ext.apply({
39839             type: 'path',
39840             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")
39841         }, opts));
39842     },
39843     drop: function (surface, x, y, text, size, angle) {
39844         size = size || 30;
39845         angle = angle || 0;
39846         surface.add({
39847             type: 'path',
39848             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'],
39849             fill: '#000',
39850             stroke: 'none',
39851             rotate: {
39852                 degrees: 22.5 - angle,
39853                 x: x,
39854                 y: y
39855             }
39856         });
39857         angle = (angle + 90) * Math.PI / 180;
39858         surface.add({
39859             type: 'text',
39860             x: x + size * Math.sin(angle) - 10, 
39861             y: y + size * Math.cos(angle) + 5,
39862             text:  text,
39863             'font-size': size * 12 / 40,
39864             stroke: 'none',
39865             fill: '#fff'
39866         });
39867     }
39868 });
39869
39870 Ext.define('Ext.draw.Surface', {
39871
39872     
39873
39874     mixins: {
39875         observable: 'Ext.util.Observable'
39876     },
39877
39878     requires: ['Ext.draw.CompositeSprite'],
39879     uses: ['Ext.draw.engine.Svg', 'Ext.draw.engine.Vml'],
39880
39881     separatorRe: /[, ]+/,
39882
39883     statics: {
39884         
39885         create: function(config, enginePriority) {
39886             enginePriority = enginePriority || ['Svg', 'Vml'];
39887
39888             var i = 0,
39889                 len = enginePriority.length,
39890                 surfaceClass;
39891
39892             for (; i < len; i++) {
39893                 if (Ext.supports[enginePriority[i]]) {
39894                     return Ext.create('Ext.draw.engine.' + enginePriority[i], config);
39895                 }
39896             }
39897             return false;
39898         }
39899     },
39900
39901     
39902
39903     
39904     availableAttrs: {
39905         blur: 0,
39906         "clip-rect": "0 0 1e9 1e9",
39907         cursor: "default",
39908         cx: 0,
39909         cy: 0,
39910         'dominant-baseline': 'auto',
39911         fill: "none",
39912         "fill-opacity": 1,
39913         font: '10px "Arial"',
39914         "font-family": '"Arial"',
39915         "font-size": "10",
39916         "font-style": "normal",
39917         "font-weight": 400,
39918         gradient: "",
39919         height: 0,
39920         hidden: false,
39921         href: "http://sencha.com/",
39922         opacity: 1,
39923         path: "M0,0",
39924         radius: 0,
39925         rx: 0,
39926         ry: 0,
39927         scale: "1 1",
39928         src: "",
39929         stroke: "#000",
39930         "stroke-dasharray": "",
39931         "stroke-linecap": "butt",
39932         "stroke-linejoin": "butt",
39933         "stroke-miterlimit": 0,
39934         "stroke-opacity": 1,
39935         "stroke-width": 1,
39936         target: "_blank",
39937         text: "",
39938         "text-anchor": "middle",
39939         title: "Ext Draw",
39940         width: 0,
39941         x: 0,
39942         y: 0,
39943         zIndex: 0
39944     },
39945
39946  
39947  
39948     container: undefined,
39949     height: 352,
39950     width: 512,
39951     x: 0,
39952     y: 0,
39953
39954     constructor: function(config) {
39955         var me = this;
39956         config = config || {};
39957         Ext.apply(me, config);
39958
39959         me.domRef = Ext.getDoc().dom;
39960         
39961         me.customAttributes = {};
39962
39963         me.addEvents(
39964             'mousedown',
39965             'mouseup',
39966             'mouseover',
39967             'mouseout',
39968             'mousemove',
39969             'mouseenter',
39970             'mouseleave',
39971             'click'
39972         );
39973
39974         me.mixins.observable.constructor.call(me);
39975
39976         me.getId();
39977         me.initGradients();
39978         me.initItems();
39979         if (me.renderTo) {
39980             me.render(me.renderTo);
39981             delete me.renderTo;
39982         }
39983         me.initBackground(config.background);
39984     },
39985
39986     
39987     
39988     initSurface: Ext.emptyFn,
39989
39990     
39991     
39992     renderItem: Ext.emptyFn,
39993
39994     
39995     renderItems: Ext.emptyFn,
39996
39997     
39998     setViewBox: Ext.emptyFn,
39999
40000     
40001     addCls: Ext.emptyFn,
40002
40003     
40004     removeCls: Ext.emptyFn,
40005
40006     
40007     setStyle: Ext.emptyFn,
40008
40009     
40010     initGradients: function() {
40011         var gradients = this.gradients;
40012         if (gradients) {
40013             Ext.each(gradients, this.addGradient, this);
40014         }
40015     },
40016
40017     
40018     initItems: function() {
40019         var items = this.items;
40020         this.items = Ext.create('Ext.draw.CompositeSprite');
40021         this.groups = Ext.create('Ext.draw.CompositeSprite');
40022         if (items) {
40023             this.add(items);
40024         }
40025     },
40026     
40027     
40028     initBackground: function(config) {
40029         var me = this,
40030             width = me.width,
40031             height = me.height,
40032             gradientId, gradient, backgroundSprite;
40033         if (config) {
40034             if (config.gradient) {
40035                 gradient = config.gradient;
40036                 gradientId = gradient.id;
40037                 me.addGradient(gradient);
40038                 me.background = me.add({
40039                     type: 'rect',
40040                     x: 0,
40041                     y: 0,
40042                     width: width,
40043                     height: height,
40044                     fill: 'url(#' + gradientId + ')'
40045                 });
40046             } else if (config.fill) {
40047                 me.background = me.add({
40048                     type: 'rect',
40049                     x: 0,
40050                     y: 0,
40051                     width: width,
40052                     height: height,
40053                     fill: config.fill
40054                 });
40055             } else if (config.image) {
40056                 me.background = me.add({
40057                     type: 'image',
40058                     x: 0,
40059                     y: 0,
40060                     width: width,
40061                     height: height,
40062                     src: config.image
40063                 });
40064             }
40065         }
40066     },
40067     
40068     
40069     setSize: function(w, h) {
40070         if (this.background) {
40071             this.background.setAttributes({
40072                 width: w,
40073                 height: h,
40074                 hidden: false
40075             }, true);
40076         }
40077     },
40078
40079     
40080     scrubAttrs: function(sprite) {
40081         var i,
40082             attrs = {},
40083             exclude = {},
40084             sattr = sprite.attr;
40085         for (i in sattr) {    
40086             
40087             if (this.translateAttrs.hasOwnProperty(i)) {
40088                 
40089                 attrs[this.translateAttrs[i]] = sattr[i];
40090                 exclude[this.translateAttrs[i]] = true;
40091             }
40092             else if (this.availableAttrs.hasOwnProperty(i) && !exclude[i]) {
40093                 
40094                 attrs[i] = sattr[i];
40095             }
40096         }
40097         return attrs;
40098     },
40099
40100     
40101     onClick: function(e) {
40102         this.processEvent('click', e);
40103     },
40104
40105     
40106     onMouseUp: function(e) {
40107         this.processEvent('mouseup', e);
40108     },
40109
40110     
40111     onMouseDown: function(e) {
40112         this.processEvent('mousedown', e);
40113     },
40114
40115     
40116     onMouseOver: function(e) {
40117         this.processEvent('mouseover', e);
40118     },
40119
40120     
40121     onMouseOut: function(e) {
40122         this.processEvent('mouseout', e);
40123     },
40124
40125     
40126     onMouseMove: function(e) {
40127         this.fireEvent('mousemove', e);
40128     },
40129
40130     
40131     onMouseEnter: Ext.emptyFn,
40132
40133     
40134     onMouseLeave: Ext.emptyFn,
40135
40136     
40137     addGradient: Ext.emptyFn,
40138
40139     
40140     add: function() {
40141         var args = Array.prototype.slice.call(arguments),
40142             sprite,
40143             index;
40144
40145         var hasMultipleArgs = args.length > 1;
40146         if (hasMultipleArgs || Ext.isArray(args[0])) {
40147             var items = hasMultipleArgs ? args : args[0],
40148                 results = [],
40149                 i, ln, item;
40150
40151             for (i = 0, ln = items.length; i < ln; i++) {
40152                 item = items[i];
40153                 item = this.add(item);
40154                 results.push(item);
40155             }
40156
40157             return results;
40158         }
40159         sprite = this.prepareItems(args[0], true)[0];
40160         this.normalizeSpriteCollection(sprite);
40161         this.onAdd(sprite);
40162         return sprite;
40163     },
40164
40165     
40166     normalizeSpriteCollection: function(sprite) {
40167         var items = this.items,
40168             zIndex = sprite.attr.zIndex,
40169             idx = items.indexOf(sprite);
40170
40171         if (idx < 0 || (idx > 0 && items.getAt(idx - 1).attr.zIndex > zIndex) ||
40172                 (idx < items.length - 1 && items.getAt(idx + 1).attr.zIndex < zIndex)) {
40173             items.removeAt(idx);
40174             idx = items.findIndexBy(function(otherSprite) {
40175                 return otherSprite.attr.zIndex > zIndex;
40176             });
40177             if (idx < 0) {
40178                 idx = items.length;
40179             }
40180             items.insert(idx, sprite);
40181         }
40182         return idx;
40183     },
40184
40185     onAdd: function(sprite) {
40186         var group = sprite.group,
40187             draggable = sprite.draggable,
40188             groups, ln, i;
40189         if (group) {
40190             groups = [].concat(group);
40191             ln = groups.length;
40192             for (i = 0; i < ln; i++) {
40193                 group = groups[i];
40194                 this.getGroup(group).add(sprite);
40195             }
40196             delete sprite.group;
40197         }
40198         if (draggable) {
40199             sprite.initDraggable();
40200         }
40201     },
40202
40203     
40204     remove: function(sprite, destroySprite) {
40205         if (sprite) {
40206             this.items.remove(sprite);
40207             this.groups.each(function(item) {
40208                 item.remove(sprite);
40209             });
40210             sprite.onRemove();
40211             if (destroySprite === true) {
40212                 sprite.destroy();
40213             }
40214         }
40215     },
40216
40217     
40218     removeAll: function(destroySprites) {
40219         var items = this.items.items,
40220             ln = items.length,
40221             i;
40222         for (i = ln - 1; i > -1; i--) {
40223             this.remove(items[i], destroySprites);
40224         }
40225     },
40226
40227     onRemove: Ext.emptyFn,
40228
40229     onDestroy: Ext.emptyFn,
40230
40231     
40232     applyTransformations: function(sprite) {
40233             sprite.bbox.transform = 0;
40234             this.transform(sprite);
40235
40236         var me = this,
40237             dirty = false,
40238             attr = sprite.attr;
40239
40240         if (attr.translation.x != null || attr.translation.y != null) {
40241             me.translate(sprite);
40242             dirty = true;
40243         }
40244         if (attr.scaling.x != null || attr.scaling.y != null) {
40245             me.scale(sprite);
40246             dirty = true;
40247         }
40248         if (attr.rotation.degrees != null) {
40249             me.rotate(sprite);
40250             dirty = true;
40251         }
40252         if (dirty) {
40253             sprite.bbox.transform = 0;
40254             this.transform(sprite);
40255             sprite.transformations = [];
40256         }
40257     },
40258
40259     
40260     rotate: function (sprite) {
40261         var bbox,
40262             deg = sprite.attr.rotation.degrees,
40263             centerX = sprite.attr.rotation.x,
40264             centerY = sprite.attr.rotation.y;
40265         if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
40266             bbox = this.getBBox(sprite);
40267             centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
40268             centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
40269         }
40270         sprite.transformations.push({
40271             type: "rotate",
40272             degrees: deg,
40273             x: centerX,
40274             y: centerY
40275         });
40276     },
40277
40278     
40279     translate: function(sprite) {
40280         var x = sprite.attr.translation.x || 0,
40281             y = sprite.attr.translation.y || 0;
40282         sprite.transformations.push({
40283             type: "translate",
40284             x: x,
40285             y: y
40286         });
40287     },
40288
40289     
40290     scale: function(sprite) {
40291         var bbox,
40292             x = sprite.attr.scaling.x || 1,
40293             y = sprite.attr.scaling.y || 1,
40294             centerX = sprite.attr.scaling.centerX,
40295             centerY = sprite.attr.scaling.centerY;
40296
40297         if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
40298             bbox = this.getBBox(sprite);
40299             centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
40300             centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
40301         }
40302         sprite.transformations.push({
40303             type: "scale",
40304             x: x,
40305             y: y,
40306             centerX: centerX,
40307             centerY: centerY
40308         });
40309     },
40310
40311     
40312     rectPath: function (x, y, w, h, r) {
40313         if (r) {
40314             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"]];
40315         }
40316         return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]];
40317     },
40318
40319     
40320     ellipsePath: function (x, y, rx, ry) {
40321         if (ry == null) {
40322             ry = rx;
40323         }
40324         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"]];
40325     },
40326
40327     
40328     getPathpath: function (el) {
40329         return el.attr.path;
40330     },
40331
40332     
40333     getPathcircle: function (el) {
40334         var a = el.attr;
40335         return this.ellipsePath(a.x, a.y, a.radius, a.radius);
40336     },
40337
40338     
40339     getPathellipse: function (el) {
40340         var a = el.attr;
40341         return this.ellipsePath(a.x, a.y,
40342                                 a.radiusX || (a.width / 2) || 0,
40343                                 a.radiusY || (a.height / 2) || 0);
40344     },
40345
40346     
40347     getPathrect: function (el) {
40348         var a = el.attr;
40349         return this.rectPath(a.x, a.y, a.width, a.height, a.r);
40350     },
40351
40352     
40353     getPathimage: function (el) {
40354         var a = el.attr;
40355         return this.rectPath(a.x || 0, a.y || 0, a.width, a.height);
40356     },
40357
40358     
40359     getPathtext: function (el) {
40360         var bbox = this.getBBoxText(el);
40361         return this.rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
40362     },
40363
40364     createGroup: function(id) {
40365         var group = this.groups.get(id);
40366         if (!group) {
40367             group = Ext.create('Ext.draw.CompositeSprite', {
40368                 surface: this
40369             });
40370             group.id = id || Ext.id(null, 'ext-surface-group-');
40371             this.groups.add(group);
40372         }
40373         return group;
40374     },
40375
40376     
40377     getGroup: function(id) {
40378         if (typeof id == "string") {
40379             var group = this.groups.get(id);
40380             if (!group) {
40381                 group = this.createGroup(id);
40382             }
40383         } else {
40384             group = id;
40385         }
40386         return group;
40387     },
40388
40389     
40390     prepareItems: function(items, applyDefaults) {
40391         items = [].concat(items);
40392         
40393         var item, i, ln;
40394         for (i = 0, ln = items.length; i < ln; i++) {
40395             item = items[i];
40396             if (!(item instanceof Ext.draw.Sprite)) {
40397                 
40398                 item.surface = this;
40399                 items[i] = this.createItem(item);
40400             } else {
40401                 item.surface = this;
40402             }
40403         }
40404         return items;
40405     },
40406     
40407     
40408     setText: Ext.emptyFn,
40409     
40410     //@private Creates an item and appends it to the surface. Called
40411
40412     
40413     createItem: Ext.emptyFn,
40414
40415     
40416     getId: function() {
40417         return this.id || (this.id = Ext.id(null, 'ext-surface-'));
40418     },
40419
40420     
40421     destroy: function() {
40422         delete this.domRef;
40423         this.removeAll();
40424     }
40425 });
40426
40427 Ext.define('Ext.draw.Component', {
40428
40429     
40430
40431     alias: 'widget.draw',
40432
40433     extend: 'Ext.Component',
40434
40435     requires: [
40436         'Ext.draw.Surface',
40437         'Ext.layout.component.Draw'
40438     ],
40439
40440     
40441
40442     
40443     enginePriority: ['Svg', 'Vml'],
40444
40445     baseCls: Ext.baseCSSPrefix + 'surface',
40446
40447     componentLayout: 'draw',
40448
40449     
40450     viewBox: true,
40451
40452     
40453     autoSize: false,
40454     
40455     
40456
40457     initComponent: function() {
40458         this.callParent(arguments);
40459
40460         this.addEvents(
40461             'mousedown',
40462             'mouseup',
40463             'mousemove',
40464             'mouseenter',
40465             'mouseleave',
40466             'click'
40467         );
40468     },
40469
40470     
40471     onRender: function() {
40472         var me = this,
40473             viewBox = me.viewBox,
40474             autoSize = me.autoSize,
40475             bbox, items, width, height, x, y;
40476         me.callParent(arguments);
40477
40478         me.createSurface();
40479
40480         items = me.surface.items;
40481
40482         if (viewBox || autoSize) {
40483             bbox = items.getBBox();
40484             width = bbox.width;
40485             height = bbox.height;
40486             x = bbox.x;
40487             y = bbox.y;
40488             if (me.viewBox) {
40489                 me.surface.setViewBox(x, y, width, height);
40490             }
40491             else {
40492                 
40493                 me.autoSizeSurface();
40494             }
40495         }
40496     },
40497
40498     //@private
40499
40500     autoSizeSurface: function() {
40501         var me = this,
40502             items = me.surface.items,
40503             bbox = items.getBBox(),
40504             width = bbox.width,
40505             height = bbox.height;
40506         items.setAttributes({
40507             translate: {
40508                 x: -bbox.x,
40509                 
40510                 y: -bbox.y + (+Ext.isOpera)
40511             }
40512         }, true);
40513         if (me.rendered) {
40514             me.setSize(width, height);
40515             me.surface.setSize(width, height);
40516         }
40517         else {
40518             me.surface.setSize(width, height);
40519         }
40520         me.el.setSize(width, height);
40521     },
40522
40523     
40524     createSurface: function() {
40525         var surface = Ext.draw.Surface.create(Ext.apply({}, {
40526                 width: this.width,
40527                 height: this.height,
40528                 renderTo: this.el
40529             }, this.initialConfig));
40530         this.surface = surface;
40531
40532         function refire(eventName) {
40533             return function(e) {
40534                 this.fireEvent(eventName, e);
40535             };
40536         }
40537
40538         surface.on({
40539             scope: this,
40540             mouseup: refire('mouseup'),
40541             mousedown: refire('mousedown'),
40542             mousemove: refire('mousemove'),
40543             mouseenter: refire('mouseenter'),
40544             mouseleave: refire('mouseleave'),
40545             click: refire('click')
40546         });
40547     },
40548
40549
40550     
40551     onDestroy: function() {
40552         var surface = this.surface;
40553         if (surface) {
40554             surface.destroy();
40555         }
40556         this.callParent(arguments);
40557     }
40558
40559 });
40560
40561
40562 Ext.define('Ext.chart.LegendItem', {
40563
40564     
40565
40566     extend: 'Ext.draw.CompositeSprite',
40567
40568     requires: ['Ext.chart.Shape'],
40569
40570     
40571
40572     
40573     x: 0,
40574     y: 0,
40575     zIndex: 500,
40576
40577     constructor: function(config) {
40578         this.callParent(arguments);
40579         this.createLegend(config);
40580     },
40581
40582     
40583     createLegend: function(config) {
40584         var me = this,
40585             index = config.yFieldIndex,
40586             series = me.series,
40587             seriesType = series.type,
40588             idx = me.yFieldIndex,
40589             legend = me.legend,
40590             surface = me.surface,
40591             refX = legend.x + me.x,
40592             refY = legend.y + me.y,
40593             bbox, z = me.zIndex,
40594             markerConfig, label, mask,
40595             radius, toggle = false,
40596             seriesStyle = Ext.apply(series.seriesStyle, series.style);
40597
40598         function getSeriesProp(name) {
40599             var val = series[name];
40600             return (Ext.isArray(val) ? val[idx] : val);
40601         }
40602         
40603         label = me.add('label', surface.add({
40604             type: 'text',
40605             x: 20,
40606             y: 0,
40607             zIndex: z || 0,
40608             font: legend.labelFont,
40609             text: getSeriesProp('title') || getSeriesProp('yField')
40610         }));
40611
40612         
40613         if (seriesType === 'line' || seriesType === 'scatter') {
40614             if(seriesType === 'line') {
40615                 me.add('line', surface.add({
40616                     type: 'path',
40617                     path: 'M0.5,0.5L16.5,0.5',
40618                     zIndex: z,
40619                     "stroke-width": series.lineWidth,
40620                     "stroke-linejoin": "round",
40621                     "stroke-dasharray": series.dash,
40622                     stroke: seriesStyle.stroke || '#000',
40623                     style: {
40624                         cursor: 'pointer'
40625                     }
40626                 }));
40627             }
40628             if (series.showMarkers || seriesType === 'scatter') {
40629                 markerConfig = Ext.apply(series.markerStyle, series.markerConfig || {});
40630                 me.add('marker', Ext.chart.Shape[markerConfig.type](surface, {
40631                     fill: markerConfig.fill,
40632                     x: 8.5,
40633                     y: 0.5,
40634                     zIndex: z,
40635                     radius: markerConfig.radius || markerConfig.size,
40636                     style: {
40637                         cursor: 'pointer'
40638                     }
40639                 }));
40640             }
40641         }
40642         
40643         else {
40644             me.add('box', surface.add({
40645                 type: 'rect',
40646                 zIndex: z,
40647                 x: 0,
40648                 y: 0,
40649                 width: 12,
40650                 height: 12,
40651                 fill: series.getLegendColor(index),
40652                 style: {
40653                     cursor: 'pointer'
40654                 }
40655             }));
40656         }
40657         
40658         me.setAttributes({
40659             hidden: false
40660         }, true);
40661         
40662         bbox = me.getBBox();
40663         
40664         mask = me.add('mask', surface.add({
40665             type: 'rect',
40666             x: bbox.x,
40667             y: bbox.y,
40668             width: bbox.width || 20,
40669             height: bbox.height || 20,
40670             zIndex: (z || 0) + 1000,
40671             fill: '#f00',
40672             opacity: 0,
40673             style: {
40674                 'cursor': 'pointer'
40675             }
40676         }));
40677
40678         
40679         me.on('mouseover', function() {
40680             label.setStyle({
40681                 'font-weight': 'bold'
40682             });
40683             mask.setStyle({
40684                 'cursor': 'pointer'
40685             });
40686             series._index = index;
40687             series.highlightItem();
40688         }, me);
40689
40690         me.on('mouseout', function() {
40691             label.setStyle({
40692                 'font-weight': 'normal'
40693             });
40694             series._index = index;
40695             series.unHighlightItem();
40696         }, me);
40697         
40698         if (!series.visibleInLegend(index)) {
40699             toggle = true;
40700             label.setAttributes({
40701                opacity: 0.5
40702             }, true);
40703         }
40704
40705         me.on('mousedown', function() {
40706             if (!toggle) {
40707                 series.hideAll();
40708                 label.setAttributes({
40709                     opacity: 0.5
40710                 }, true);
40711             } else {
40712                 series.showAll();
40713                 label.setAttributes({
40714                     opacity: 1
40715                 }, true);
40716             }
40717             toggle = !toggle;
40718         }, me);
40719         me.updatePosition({x:0, y:0}); 
40720     },
40721
40722     
40723     updatePosition: function(relativeTo) {
40724         var me = this,
40725             items = me.items,
40726             ln = items.length,
40727             i = 0,
40728             item;
40729         if (!relativeTo) {
40730             relativeTo = me.legend;
40731         }
40732         for (; i < ln; i++) {
40733             item = items[i];
40734             switch (item.type) {
40735                 case 'text':
40736                     item.setAttributes({
40737                         x: 20 + relativeTo.x + me.x,
40738                         y: relativeTo.y + me.y
40739                     }, true);
40740                     break;
40741                 case 'rect':
40742                     item.setAttributes({
40743                         translate: {
40744                             x: relativeTo.x + me.x,
40745                             y: relativeTo.y + me.y - 6
40746                         }
40747                     }, true);
40748                     break;
40749                 default:
40750                     item.setAttributes({
40751                         translate: {
40752                             x: relativeTo.x + me.x,
40753                             y: relativeTo.y + me.y
40754                         }
40755                     }, true);
40756             }
40757         }
40758     }
40759 });
40760
40761 Ext.define('Ext.chart.Legend', {
40762
40763     
40764
40765     requires: ['Ext.chart.LegendItem'],
40766
40767     
40768
40769     
40770     visible: true,
40771
40772     
40773     position: 'bottom',
40774
40775     
40776     x: 0,
40777
40778     
40779     y: 0,
40780
40781     
40782     labelFont: '12px Helvetica, sans-serif',
40783
40784     
40785     boxStroke: '#000',
40786
40787     
40788     boxStrokeWidth: 1,
40789
40790     
40791     boxFill: '#FFF',
40792
40793     
40794     itemSpacing: 10,
40795
40796     
40797     padding: 5,
40798
40799     
40800     width: 0,
40801     
40802     height: 0,
40803
40804     
40805     boxZIndex: 100,
40806
40807     constructor: function(config) {
40808         var me = this;
40809         if (config) {
40810             Ext.apply(me, config);
40811         }
40812         me.items = [];
40813         
40814         me.isVertical = ("left|right|float".indexOf(me.position) !== -1);
40815         
40816         
40817         me.origX = me.x;
40818         me.origY = me.y;
40819     },
40820
40821     
40822     create: function() {
40823         var me = this;
40824         me.createItems();
40825         if (!me.created && me.isDisplayed()) {
40826             me.createBox();
40827             me.created = true;
40828
40829             
40830             me.chart.series.each(function(series) {
40831                 series.on('titlechange', function() {
40832                     me.create();
40833                     me.updatePosition();
40834                 });
40835             });
40836         }
40837     },
40838
40839     
40840     isDisplayed: function() {
40841         return this.visible && this.chart.series.findIndex('showInLegend', true) !== -1;
40842     },
40843
40844     
40845     createItems: function() {
40846         var me = this,
40847             chart = me.chart,
40848             surface = chart.surface,
40849             items = me.items,
40850             padding = me.padding,
40851             itemSpacing = me.itemSpacing,
40852             spacingOffset = 2,
40853             maxWidth = 0,
40854             maxHeight = 0,
40855             totalWidth = 0,
40856             totalHeight = 0,
40857             vertical = me.isVertical,
40858             math = Math,
40859             mfloor = math.floor,
40860             mmax = math.max,
40861             index = 0, 
40862             i = 0, 
40863             len = items ? items.length : 0,
40864             x, y, spacing, item, bbox, height, width;
40865
40866         
40867         if (len) {
40868             for (; i < len; i++) {
40869                 items[i].destroy();
40870             }
40871         }
40872         
40873         items.length = [];
40874         
40875         
40876         chart.series.each(function(series, i) {
40877             if (series.showInLegend) {
40878                 Ext.each([].concat(series.yField), function(field, j) {
40879                     item = Ext.create('Ext.chart.LegendItem', {
40880                         legend: this,
40881                         series: series,
40882                         surface: chart.surface,
40883                         yFieldIndex: j
40884                     });
40885                     bbox = item.getBBox();
40886
40887                     
40888                     width = bbox.width; 
40889                     height = bbox.height;
40890
40891                     if (i + j === 0) {
40892                         spacing = vertical ? padding + height / 2 : padding;
40893                     }
40894                     else {
40895                         spacing = itemSpacing / (vertical ? 2 : 1);
40896                     }
40897                     
40898                     item.x = mfloor(vertical ? padding : totalWidth + spacing);
40899                     item.y = mfloor(vertical ? totalHeight + spacing : padding + height / 2);
40900
40901                     
40902                     totalWidth += width + spacing;
40903                     totalHeight += height + spacing;
40904                     maxWidth = mmax(maxWidth, width);
40905                     maxHeight = mmax(maxHeight, height);
40906
40907                     items.push(item);
40908                 }, this);
40909             }
40910         }, me);
40911
40912         
40913         me.width = mfloor((vertical ? maxWidth : totalWidth) + padding * 2);
40914         if (vertical && items.length === 1) {
40915             spacingOffset = 1;
40916         }
40917         me.height = mfloor((vertical ? totalHeight - spacingOffset * spacing : maxHeight) + (padding * 2));
40918         me.itemHeight = maxHeight;
40919     },
40920
40921     
40922     getBBox: function() {
40923         var me = this;
40924         return {
40925             x: Math.round(me.x) - me.boxStrokeWidth / 2,
40926             y: Math.round(me.y) - me.boxStrokeWidth / 2,
40927             width: me.width,
40928             height: me.height
40929         };
40930     },
40931
40932     
40933     createBox: function() {
40934         var me = this,
40935             box = me.boxSprite = me.chart.surface.add(Ext.apply({
40936                 type: 'rect',
40937                 stroke: me.boxStroke,
40938                 "stroke-width": me.boxStrokeWidth,
40939                 fill: me.boxFill,
40940                 zIndex: me.boxZIndex
40941             }, me.getBBox()));
40942         box.redraw();
40943     },
40944
40945     
40946     updatePosition: function() {
40947         var me = this,
40948             x, y,
40949             legendWidth = me.width,
40950             legendHeight = me.height,
40951             padding = me.padding,
40952             chart = me.chart,
40953             chartBBox = chart.chartBBox,
40954             insets = chart.insetPadding,
40955             chartWidth = chartBBox.width - (insets * 2),
40956             chartHeight = chartBBox.height - (insets * 2),
40957             chartX = chartBBox.x + insets,
40958             chartY = chartBBox.y + insets,
40959             surface = chart.surface,
40960             mfloor = Math.floor;
40961         
40962         if (me.isDisplayed()) {
40963             
40964             switch(me.position) {
40965                 case "left":
40966                     x = insets;
40967                     y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
40968                     break;
40969                 case "right":
40970                     x = mfloor(surface.width - legendWidth) - insets;
40971                     y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
40972                     break;
40973                 case "top":
40974                     x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
40975                     y = insets;
40976                     break;
40977                 case "bottom":
40978                     x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
40979                     y = mfloor(surface.height - legendHeight) - insets;
40980                     break;
40981                 default:
40982                     x = mfloor(me.origX) + insets;
40983                     y = mfloor(me.origY) + insets;
40984             }
40985             me.x = x;
40986             me.y = y;
40987
40988             
40989             Ext.each(me.items, function(item) {
40990                 item.updatePosition();
40991             });
40992             
40993             me.boxSprite.setAttributes(me.getBBox(), true);
40994         }
40995     }
40996 });
40997
40998
40999 Ext.define('Ext.chart.Chart', {
41000
41001     
41002
41003     alias: 'widget.chart',
41004
41005     extend: 'Ext.draw.Component',
41006     
41007     mixins: {
41008         themeManager: 'Ext.chart.theme.Theme',
41009         mask: 'Ext.chart.Mask',
41010         navigation: 'Ext.chart.Navigation'
41011     },
41012
41013     requires: [
41014         'Ext.util.MixedCollection',
41015         'Ext.data.StoreManager',
41016         'Ext.chart.Legend',
41017         'Ext.util.DelayedTask'
41018     ],
41019
41020     
41021
41022     
41023     viewBox: false,
41024
41025     
41026
41027     
41028     animate: false,
41029
41030     
41031     legend: false,
41032
41033     
41034     insetPadding: 10,
41035
41036     
41037     enginePriority: ['Svg', 'Vml'],
41038
41039     
41040     background: false,
41041
41042     
41043
41044
41045     constructor: function(config) {
41046         var me = this,
41047             defaultAnim;
41048         me.initTheme(config.theme || me.theme);
41049         if (me.gradients) {
41050             Ext.apply(config, { gradients: me.gradients });
41051         }
41052         if (me.background) {
41053             Ext.apply(config, { background: me.background });
41054         }
41055         if (config.animate) {
41056             defaultAnim = {
41057                 easing: 'ease',
41058                 duration: 500
41059             };
41060             if (Ext.isObject(config.animate)) {
41061                 config.animate = Ext.applyIf(config.animate, defaultAnim);
41062             }
41063             else {
41064                 config.animate = defaultAnim;
41065             }
41066         }
41067         me.mixins.mask.constructor.call(me, config);
41068         me.mixins.navigation.constructor.call(me, config);
41069         me.callParent([config]);
41070     },
41071
41072     initComponent: function() {
41073         var me = this,
41074             axes,
41075             series;
41076         me.callParent();
41077         me.addEvents(
41078             'itemmousedown',
41079             'itemmouseup',
41080             'itemmouseover',
41081             'itemmouseout',
41082             'itemclick',
41083             'itemdoubleclick',
41084             'itemdragstart',
41085             'itemdrag',
41086             'itemdragend',
41087             
41088             'beforerefresh',
41089             
41090             'refresh'
41091         );
41092         Ext.applyIf(me, {
41093             zoom: {
41094                 width: 1,
41095                 height: 1,
41096                 x: 0,
41097                 y: 0
41098             }
41099         });
41100         me.maxGutter = [0, 0];
41101         me.store = Ext.data.StoreManager.lookup(me.store);
41102         axes = me.axes;
41103         me.axes = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.position; });
41104         if (axes) {
41105             me.axes.addAll(axes);
41106         }
41107         series = me.series;
41108         me.series = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.seriesId || (a.seriesId = Ext.id(null, 'ext-chart-series-')); });
41109         if (series) {
41110             me.series.addAll(series);
41111         }
41112         if (me.legend !== false) {
41113             me.legend = Ext.create('Ext.chart.Legend', Ext.applyIf({chart:me}, me.legend));
41114         }
41115
41116         me.on({
41117             mousemove: me.onMouseMove,
41118             mouseleave: me.onMouseLeave,
41119             mousedown: me.onMouseDown,
41120             mouseup: me.onMouseUp,
41121             scope: me
41122         });
41123     },
41124
41125     
41126     afterComponentLayout: function(width, height) {
41127         var me = this;
41128         if (Ext.isNumber(width) && Ext.isNumber(height)) {
41129             me.curWidth = width;
41130             me.curHeight = height;
41131             me.redraw(true);
41132         }
41133         this.callParent(arguments);
41134     },
41135
41136     
41137     redraw: function(resize) {
41138         var me = this,
41139             chartBBox = me.chartBBox = {
41140                 x: 0,
41141                 y: 0,
41142                 height: me.curHeight,
41143                 width: me.curWidth
41144             },
41145             legend = me.legend;
41146         me.surface.setSize(chartBBox.width, chartBBox.height);
41147         
41148         me.series.each(me.initializeSeries, me);
41149         me.axes.each(me.initializeAxis, me);
41150         
41151         
41152         me.axes.each(function(axis) {
41153             axis.processView();
41154         });
41155         me.axes.each(function(axis) {
41156             axis.drawAxis(true);
41157         });
41158
41159         
41160         if (legend !== false) {
41161             legend.create();
41162         }
41163
41164         
41165         me.alignAxes();
41166
41167         
41168         if (me.legend !== false) {
41169             legend.updatePosition();
41170         }
41171
41172         
41173         me.getMaxGutter();
41174
41175         
41176         me.resizing = !!resize;
41177
41178         me.axes.each(me.drawAxis, me);
41179         me.series.each(me.drawCharts, me);
41180         me.resizing = false;
41181     },
41182
41183     
41184     afterRender: function() {
41185         var ref,
41186             me = this;
41187         this.callParent();
41188
41189         if (me.categoryNames) {
41190             me.setCategoryNames(me.categoryNames);
41191         }
41192
41193         if (me.tipRenderer) {
41194             ref = me.getFunctionRef(me.tipRenderer);
41195             me.setTipRenderer(ref.fn, ref.scope);
41196         }
41197         me.bindStore(me.store, true);
41198         me.refresh();
41199     },
41200
41201     
41202     getEventXY: function(e) {
41203         var me = this,
41204             box = this.surface.getRegion(),
41205             pageXY = e.getXY(),
41206             x = pageXY[0] - box.left,
41207             y = pageXY[1] - box.top;
41208         return [x, y];
41209     },
41210
41211     
41212     onClick: function(e) {
41213         var me = this,
41214             position = me.getEventXY(e),
41215             item;
41216
41217         
41218         
41219         me.series.each(function(series) {
41220             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
41221                 if (series.getItemForPoint) {
41222                     item = series.getItemForPoint(position[0], position[1]);
41223                     if (item) {
41224                         series.fireEvent('itemclick', item);
41225                     }
41226                 }
41227             }
41228         }, me);
41229     },
41230
41231     
41232     onMouseDown: function(e) {
41233         var me = this,
41234             position = me.getEventXY(e),
41235             item;
41236
41237         if (me.mask) {
41238             me.mixins.mask.onMouseDown.call(me, e);
41239         }
41240         
41241         
41242         me.series.each(function(series) {
41243             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
41244                 if (series.getItemForPoint) {
41245                     item = series.getItemForPoint(position[0], position[1]);
41246                     if (item) {
41247                         series.fireEvent('itemmousedown', item);
41248                     }
41249                 }
41250             }
41251         }, me);
41252     },
41253
41254     
41255     onMouseUp: function(e) {
41256         var me = this,
41257             position = me.getEventXY(e),
41258             item;
41259
41260         if (me.mask) {
41261             me.mixins.mask.onMouseUp.call(me, e);
41262         }
41263         
41264         
41265         me.series.each(function(series) {
41266             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
41267                 if (series.getItemForPoint) {
41268                     item = series.getItemForPoint(position[0], position[1]);
41269                     if (item) {
41270                         series.fireEvent('itemmouseup', item);
41271                     }
41272                 }
41273             }
41274         }, me);
41275     },
41276
41277     
41278     onMouseMove: function(e) {
41279         var me = this,
41280             position = me.getEventXY(e),
41281             item, last, storeItem, storeField;
41282
41283         if (me.mask) {
41284             me.mixins.mask.onMouseMove.call(me, e);
41285         }
41286         
41287         
41288         me.series.each(function(series) {
41289             if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) {
41290                 if (series.getItemForPoint) {
41291                     item = series.getItemForPoint(position[0], position[1]);
41292                     last = series._lastItemForPoint;
41293                     storeItem = series._lastStoreItem;
41294                     storeField = series._lastStoreField;
41295
41296
41297                     if (item !== last || item && (item.storeItem != storeItem || item.storeField != storeField)) {
41298                         if (last) {
41299                             series.fireEvent('itemmouseout', last);
41300                             delete series._lastItemForPoint;
41301                             delete series._lastStoreField;
41302                             delete series._lastStoreItem;
41303                         }
41304                         if (item) {
41305                             series.fireEvent('itemmouseover', item);
41306                             series._lastItemForPoint = item;
41307                             series._lastStoreItem = item.storeItem;
41308                             series._lastStoreField = item.storeField;
41309                         }
41310                     }
41311                 }
41312             } else {
41313                 last = series._lastItemForPoint;
41314                 if (last) {
41315                     series.fireEvent('itemmouseout', last);
41316                     delete series._lastItemForPoint;
41317                     delete series._lastStoreField;
41318                     delete series._lastStoreItem;
41319                 }
41320             }
41321         }, me);
41322     },
41323
41324     
41325     onMouseLeave: function(e) {
41326         var me = this;
41327         if (me.mask) {
41328             me.mixins.mask.onMouseLeave.call(me, e);
41329         }
41330         me.series.each(function(series) {
41331             delete series._lastItemForPoint;
41332         });
41333     },
41334
41335     
41336     delayRefresh: function() {
41337         var me = this;
41338         if (!me.refreshTask) {
41339             me.refreshTask = Ext.create('Ext.util.DelayedTask', me.refresh, me);
41340         }
41341         me.refreshTask.delay(me.refreshBuffer);
41342     },
41343
41344     
41345     refresh: function() {
41346         var me = this;
41347         if (me.rendered && me.curWidth != undefined && me.curHeight != undefined) {
41348             if (me.fireEvent('beforerefresh', me) !== false) {
41349                 me.redraw();
41350                 me.fireEvent('refresh', me);
41351             }
41352         }
41353     },
41354
41355     
41356     bindStore: function(store, initial) {
41357         var me = this;
41358         if (!initial && me.store) {
41359             if (store !== me.store && me.store.autoDestroy) {
41360                 me.store.destroy();
41361             }
41362             else {
41363                 me.store.un('datachanged', me.refresh, me);
41364                 me.store.un('add', me.delayRefresh, me);
41365                 me.store.un('remove', me.delayRefresh, me);
41366                 me.store.un('update', me.delayRefresh, me);
41367                 me.store.un('clear', me.refresh, me);
41368             }
41369         }
41370         if (store) {
41371             store = Ext.data.StoreManager.lookup(store);
41372             store.on({
41373                 scope: me,
41374                 datachanged: me.refresh,
41375                 add: me.delayRefresh,
41376                 remove: me.delayRefresh,
41377                 update: me.delayRefresh,
41378                 clear: me.refresh
41379             });
41380         }
41381         me.store = store;
41382         if (store && !initial) {
41383             me.refresh();
41384         }
41385     },
41386
41387     
41388     initializeAxis: function(axis) {
41389         var me = this,
41390             chartBBox = me.chartBBox,
41391             w = chartBBox.width,
41392             h = chartBBox.height,
41393             x = chartBBox.x,
41394             y = chartBBox.y,
41395             themeAttrs = me.themeAttrs,
41396             config = {
41397                 chart: me
41398             };
41399         if (themeAttrs) {
41400             config.axisStyle = Ext.apply({}, themeAttrs.axis);
41401             config.axisLabelLeftStyle = Ext.apply({}, themeAttrs.axisLabelLeft);
41402             config.axisLabelRightStyle = Ext.apply({}, themeAttrs.axisLabelRight);
41403             config.axisLabelTopStyle = Ext.apply({}, themeAttrs.axisLabelTop);
41404             config.axisLabelBottomStyle = Ext.apply({}, themeAttrs.axisLabelBottom);
41405             config.axisTitleLeftStyle = Ext.apply({}, themeAttrs.axisTitleLeft);
41406             config.axisTitleRightStyle = Ext.apply({}, themeAttrs.axisTitleRight);
41407             config.axisTitleTopStyle = Ext.apply({}, themeAttrs.axisTitleTop);
41408             config.axisTitleBottomStyle = Ext.apply({}, themeAttrs.axisTitleBottom);
41409         }
41410         switch (axis.position) {
41411             case 'top':
41412                 Ext.apply(config, {
41413                     length: w,
41414                     width: h,
41415                     x: x,
41416                     y: y
41417                 });
41418             break;
41419             case 'bottom':
41420                 Ext.apply(config, {
41421                     length: w,
41422                     width: h,
41423                     x: x,
41424                     y: h
41425                 });
41426             break;
41427             case 'left':
41428                 Ext.apply(config, {
41429                     length: h,
41430                     width: w,
41431                     x: x,
41432                     y: h
41433                 });
41434             break;
41435             case 'right':
41436                 Ext.apply(config, {
41437                     length: h,
41438                     width: w,
41439                     x: w,
41440                     y: h
41441                 });
41442             break;
41443         }
41444         if (!axis.chart) {
41445             Ext.apply(config, axis);
41446             axis = me.axes.replace(Ext.createByAlias('axis.' + axis.type.toLowerCase(), config));
41447         }
41448         else {
41449             Ext.apply(axis, config);
41450         }
41451     },
41452
41453
41454     
41455     alignAxes: function() {
41456         var me = this,
41457             axes = me.axes,
41458             legend = me.legend,
41459             edges = ['top', 'right', 'bottom', 'left'],
41460             chartBBox,
41461             insetPadding = me.insetPadding,
41462             insets = {
41463                 top: insetPadding,
41464                 right: insetPadding,
41465                 bottom: insetPadding,
41466                 left: insetPadding
41467             };
41468
41469         function getAxis(edge) {
41470             var i = axes.findIndex('position', edge);
41471             return (i < 0) ? null : axes.getAt(i);
41472         }
41473
41474         
41475         Ext.each(edges, function(edge) {
41476             var isVertical = (edge === 'left' || edge === 'right'),
41477                 axis = getAxis(edge),
41478                 bbox;
41479
41480             
41481             if (legend !== false) {
41482                 if (legend.position === edge) {
41483                     bbox = legend.getBBox();
41484                     insets[edge] += (isVertical ? bbox.width : bbox.height) + insets[edge];
41485                 }
41486             }
41487
41488             
41489             
41490             if (axis && axis.bbox) {
41491                 bbox = axis.bbox;
41492                 insets[edge] += (isVertical ? bbox.width : bbox.height);
41493             }
41494         });
41495         
41496         chartBBox = {
41497             x: insets.left,
41498             y: insets.top,
41499             width: me.curWidth - insets.left - insets.right,
41500             height: me.curHeight - insets.top - insets.bottom
41501         };
41502         me.chartBBox = chartBBox;
41503
41504         
41505         
41506         axes.each(function(axis) {
41507             var pos = axis.position,
41508                 isVertical = (pos === 'left' || pos === 'right');
41509
41510             axis.x = (pos === 'right' ? chartBBox.x + chartBBox.width : chartBBox.x);
41511             axis.y = (pos === 'top' ? chartBBox.y : chartBBox.y + chartBBox.height);
41512             axis.width = (isVertical ? chartBBox.width : chartBBox.height);
41513             axis.length = (isVertical ? chartBBox.height : chartBBox.width);
41514         });
41515     },
41516
41517     
41518     initializeSeries: function(series, idx) {
41519         var me = this,
41520             themeAttrs = me.themeAttrs,
41521             seriesObj, markerObj, seriesThemes, st,
41522             markerThemes, colorArrayStyle = [],
41523             i = 0, l,
41524             config = {
41525                 chart: me,
41526                 seriesId: series.seriesId
41527             };
41528         if (themeAttrs) {
41529             seriesThemes = themeAttrs.seriesThemes;
41530             markerThemes = themeAttrs.markerThemes;
41531             seriesObj = Ext.apply({}, themeAttrs.series);
41532             markerObj = Ext.apply({}, themeAttrs.marker);
41533             config.seriesStyle = Ext.apply(seriesObj, seriesThemes[idx % seriesThemes.length]);
41534             config.seriesLabelStyle = Ext.apply({}, themeAttrs.seriesLabel);
41535             config.markerStyle = Ext.apply(markerObj, markerThemes[idx % markerThemes.length]);
41536             if (themeAttrs.colors) {
41537                 config.colorArrayStyle = themeAttrs.colors;
41538             } else {
41539                 colorArrayStyle = [];
41540                 for (l = seriesThemes.length; i < l; i++) {
41541                     st = seriesThemes[i];
41542                     if (st.fill || st.stroke) {
41543                         colorArrayStyle.push(st.fill || st.stroke);
41544                     }
41545                 }
41546                 if (colorArrayStyle.length) {
41547                     config.colorArrayStyle = colorArrayStyle;
41548                 }
41549             }
41550             config.seriesIdx = idx;
41551         }
41552         if (series instanceof Ext.chart.series.Series) {
41553             Ext.apply(series, config);
41554         } else {
41555             Ext.applyIf(config, series);
41556             series = me.series.replace(Ext.createByAlias('series.' + series.type.toLowerCase(), config));
41557         }
41558         if (series.initialize) {
41559             series.initialize();
41560         }
41561     },
41562
41563     
41564     getMaxGutter: function() {
41565         var me = this,
41566             maxGutter = [0, 0];
41567         me.series.each(function(s) {
41568             var gutter = s.getGutters && s.getGutters() || [0, 0];
41569             maxGutter[0] = Math.max(maxGutter[0], gutter[0]);
41570             maxGutter[1] = Math.max(maxGutter[1], gutter[1]);
41571         });
41572         me.maxGutter = maxGutter;
41573     },
41574
41575     
41576     drawAxis: function(axis) {
41577         axis.drawAxis();
41578     },
41579
41580     
41581     drawCharts: function(series) {
41582         series.triggerafterrender = false;
41583         series.drawSeries();
41584         if (!this.animate) {
41585             series.fireEvent('afterrender');
41586         }
41587     },
41588
41589     
41590     destroy: function() {
41591         this.surface.destroy();
41592         this.bindStore(null);
41593         this.callParent(arguments);
41594     }
41595 });
41596
41597
41598 Ext.define('Ext.chart.Highlight', {
41599
41600     
41601
41602     requires: ['Ext.fx.Anim'],
41603
41604     
41605
41606     
41607     highlight: false,
41608
41609     highlightCfg : null,
41610
41611     constructor: function(config) {
41612         if (config.highlight) {
41613             if (config.highlight !== true) { 
41614                 this.highlightCfg = Ext.apply({}, config.highlight);
41615             }
41616             else {
41617                 this.highlightCfg = {
41618                     fill: '#fdd',
41619                     radius: 20,
41620                     lineWidth: 5,
41621                     stroke: '#f55'
41622                 };
41623             }
41624         }
41625     },
41626
41627     
41628     highlightItem: function(item) {
41629         if (!item) {
41630             return;
41631         }
41632         
41633         var me = this,
41634             sprite = item.sprite,
41635             opts = me.highlightCfg,
41636             surface = me.chart.surface,
41637             animate = me.chart.animate,
41638             p,
41639             from,
41640             to,
41641             pi;
41642
41643         if (!me.highlight || !sprite || sprite._highlighted) {
41644             return;
41645         }
41646         if (sprite._anim) {
41647             sprite._anim.paused = true;
41648         }
41649         sprite._highlighted = true;
41650         if (!sprite._defaults) {
41651             sprite._defaults = Ext.apply(sprite._defaults || {},
41652             sprite.attr);
41653             from = {};
41654             to = {};
41655             for (p in opts) {
41656                 if (! (p in sprite._defaults)) {
41657                     sprite._defaults[p] = surface.availableAttrs[p];
41658                 }
41659                 from[p] = sprite._defaults[p];
41660                 to[p] = opts[p];
41661                 if (Ext.isObject(opts[p])) {
41662                     from[p] = {};
41663                     to[p] = {};
41664                     Ext.apply(sprite._defaults[p], sprite.attr[p]);
41665                     Ext.apply(from[p], sprite._defaults[p]);
41666                     for (pi in sprite._defaults[p]) {
41667                         if (! (pi in opts[p])) {
41668                             to[p][pi] = from[p][pi];
41669                         } else {
41670                             to[p][pi] = opts[p][pi];
41671                         }
41672                     }
41673                     for (pi in opts[p]) {
41674                         if (! (pi in to[p])) {
41675                             to[p][pi] = opts[p][pi];
41676                         }
41677                     }
41678                 }
41679             }
41680             sprite._from = from;
41681             sprite._to = to;
41682         }
41683         if (animate) {
41684             sprite._anim = Ext.create('Ext.fx.Anim', {
41685                 target: sprite,
41686                 from: sprite._from,
41687                 to: sprite._to,
41688                 duration: 150
41689             });
41690         } else {
41691             sprite.setAttributes(sprite._to, true);
41692         }
41693     },
41694
41695     
41696     unHighlightItem: function() {
41697         if (!this.highlight || !this.items) {
41698             return;
41699         }
41700
41701         var me = this,
41702             items = me.items,
41703             len = items.length,
41704             opts = me.highlightCfg,
41705             animate = me.chart.animate,
41706             i = 0,
41707             obj,
41708             p,
41709             sprite;
41710
41711         for (; i < len; i++) {
41712             if (!items[i]) {
41713                 continue;
41714             }
41715             sprite = items[i].sprite;
41716             if (sprite && sprite._highlighted) {
41717                 if (sprite._anim) {
41718                     sprite._anim.paused = true;
41719                 }
41720                 obj = {};
41721                 for (p in opts) {
41722                     if (Ext.isObject(sprite._defaults[p])) {
41723                         obj[p] = {};
41724                         Ext.apply(obj[p], sprite._defaults[p]);
41725                     }
41726                     else {
41727                         obj[p] = sprite._defaults[p];
41728                     }
41729                 }
41730                 if (animate) {
41731                     sprite._anim = Ext.create('Ext.fx.Anim', {
41732                         target: sprite,
41733                         to: obj,
41734                         duration: 150
41735                     });
41736                 }
41737                 else {
41738                     sprite.setAttributes(obj, true);
41739                 }
41740                 delete sprite._highlighted;
41741                 
41742             }
41743         }
41744     },
41745
41746     cleanHighlights: function() {
41747         if (!this.highlight) {
41748             return;
41749         }
41750
41751         var group = this.group,
41752             markerGroup = this.markerGroup,
41753             i = 0,
41754             l;
41755         for (l = group.getCount(); i < l; i++) {
41756             delete group.getAt(i)._defaults;
41757         }
41758         if (markerGroup) {
41759             for (l = markerGroup.getCount(); i < l; i++) {
41760                 delete markerGroup.getAt(i)._defaults;
41761             }
41762         }
41763     }
41764 });
41765
41766 Ext.define('Ext.chart.Label', {
41767
41768     
41769
41770     requires: ['Ext.draw.Color'],
41771     
41772     
41773
41774     
41775
41776     
41777
41778     
41779
41780     
41781
41782     
41783
41784     
41785
41786     
41787
41788     //@private a regex to parse url type colors.
41789
41790     colorStringRe: /url\s*\(\s*#([^\/)]+)\s*\)/,
41791     
41792     //@private the mixin constructor. Used internally by Series.
41793
41794     constructor: function(config) {
41795         var me = this;
41796         me.label = Ext.applyIf(me.label || {},
41797         {
41798             display: "none",
41799             color: "#000",
41800             field: "name",
41801             minMargin: 50,
41802             font: "11px Helvetica, sans-serif",
41803             orientation: "horizontal",
41804             renderer: function(v) {
41805                 return v;
41806             }
41807         });
41808
41809         if (me.label.display !== 'none') {
41810             me.labelsGroup = me.chart.surface.getGroup(me.seriesId + '-labels');
41811         }
41812     },
41813
41814     //@private a method to render all labels in the labelGroup
41815
41816     renderLabels: function() {
41817         var me = this,
41818             chart = me.chart,
41819             gradients = chart.gradients,
41820             gradient,
41821             items = me.items,
41822             animate = chart.animate,
41823             config = me.label,
41824             display = config.display,
41825             color = config.color,
41826             field = [].concat(config.field),
41827             group = me.labelsGroup,
41828             store = me.chart.store,
41829             len = store.getCount(),
41830             ratio = items.length / len,
41831             i, count, index, j, 
41832             k, gradientsCount = (gradients || 0) && gradients.length,
41833             colorStopTotal, colorStopIndex, colorStop,
41834             item, label, storeItem,
41835             sprite, spriteColor, spriteBrightness, labelColor,
41836             Color = Ext.draw.Color,
41837             colorString;
41838
41839         if (display == 'none') {
41840             return;
41841         }
41842
41843         for (i = 0, count = 0; i < len; i++) {
41844             index = 0;
41845             for (j = 0; j < ratio; j++) {
41846                 item = items[count];
41847                 label = group.getAt(count);
41848                 storeItem = store.getAt(i);
41849                 
41850                 
41851                 while(this.__excludes && this.__excludes[index]) {
41852                     index++;
41853                 }
41854
41855                 if (!item && label) {
41856                     label.hide(true);
41857                 }
41858
41859                 if (item && field[j]) {
41860                     if (!label) {
41861                         label = me.onCreateLabel(storeItem, item, i, display, j, index);
41862                     }
41863                     me.onPlaceLabel(label, storeItem, item, i, display, animate, j, index);
41864
41865                     
41866                     if (config.contrast && item.sprite) {
41867                         sprite = item.sprite;
41868                         colorString = sprite._to && sprite._to.fill || sprite.attr.fill;
41869                         spriteColor = Color.fromString(colorString);
41870                         
41871                         if (colorString && !spriteColor) {
41872                             colorString = colorString.match(me.colorStringRe)[1];
41873                             for (k = 0; k < gradientsCount; k++) {
41874                                 gradient = gradients[k];
41875                                 if (gradient.id == colorString) {
41876                                     
41877                                     colorStop = 0; colorStopTotal = 0;
41878                                     for (colorStopIndex in gradient.stops) {
41879                                         colorStop++;
41880                                         colorStopTotal += Color.fromString(gradient.stops[colorStopIndex].color).getGrayscale();
41881                                     }
41882                                     spriteBrightness = (colorStopTotal / colorStop) / 255;
41883                                     break;
41884                                 }
41885                             }
41886                         }
41887                         else {
41888                             spriteBrightness = spriteColor.getGrayscale() / 255;
41889                         }
41890                         labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL();
41891                         
41892                         labelColor[2] = spriteBrightness > 0.5? 0.2 : 0.8;
41893                         label.setAttributes({
41894                             fill: String(Color.fromHSL.apply({}, labelColor))
41895                         }, true);
41896                     }
41897                 }
41898                 count++;
41899                 index++;
41900             }
41901         }
41902         me.hideLabels(count);
41903     },
41904
41905     //@private a method to hide labels.
41906
41907     hideLabels: function(index) {
41908         var labelsGroup = this.labelsGroup, len;
41909         if (labelsGroup) {
41910             len = labelsGroup.getCount();
41911             while (len-->index) {
41912                 labelsGroup.getAt(len).hide(true);
41913             }
41914         }
41915     }
41916 });
41917 Ext.define('Ext.chart.MaskLayer', {
41918     extend: 'Ext.Component',
41919     
41920     constructor: function(config) {
41921         config = Ext.apply(config || {}, {
41922             style: 'position:absolute;background-color:#888;cursor:move;opacity:0.6;border:1px solid #222;'
41923         });
41924         this.callParent([config]);    
41925     },
41926     
41927     initComponent: function() {
41928         var me = this;
41929         me.callParent(arguments);
41930         me.addEvents(
41931             'mousedown',
41932             'mouseup',
41933             'mousemove',
41934             'mouseenter',
41935             'mouseleave'
41936         );
41937     },
41938
41939     initDraggable: function() {
41940         this.callParent(arguments);
41941         this.dd.onStart = function (e) {
41942             var me = this,
41943                 comp = me.comp;
41944     
41945             
41946             this.startPosition = comp.getPosition(true);
41947     
41948             
41949             
41950             if (comp.ghost && !comp.liveDrag) {
41951                  me.proxy = comp.ghost();
41952                  me.dragTarget = me.proxy.header.el;
41953             }
41954     
41955             
41956             if (me.constrain || me.constrainDelegate) {
41957                 me.constrainTo = me.calculateConstrainRegion();
41958             }
41959         };
41960     }
41961 });
41962
41963 Ext.define('Ext.chart.TipSurface', {
41964
41965     
41966
41967     extend: 'Ext.draw.Component',
41968
41969     
41970
41971     spriteArray: false,
41972     renderFirst: true,
41973
41974     constructor: function(config) {
41975         this.callParent([config]);
41976         if (config.sprites) {
41977             this.spriteArray = [].concat(config.sprites);
41978             delete config.sprites;
41979         }
41980     },
41981
41982     onRender: function() {
41983         var me = this,
41984             i = 0,
41985             l = 0,
41986             sp,
41987             sprites;
41988             this.callParent(arguments);
41989         sprites = me.spriteArray;
41990         if (me.renderFirst && sprites) {
41991             me.renderFirst = false;
41992             for (l = sprites.length; i < l; i++) {
41993                 sp = me.surface.add(sprites[i]);
41994                 sp.setAttributes({
41995                     hidden: false
41996                 },
41997                 true);
41998             }
41999         }
42000     }
42001 });
42002
42003
42004 Ext.define('Ext.chart.Tip', {
42005
42006     
42007
42008     requires: ['Ext.tip.ToolTip', 'Ext.chart.TipSurface'],
42009
42010     
42011
42012     constructor: function(config) {
42013         var me = this,
42014             surface,
42015             sprites,
42016             tipSurface;
42017         if (config.tips) {
42018             me.tipTimeout = null;
42019             me.tipConfig = Ext.apply({}, config.tips, {
42020                 renderer: Ext.emptyFn,
42021                 constrainPosition: false
42022             });
42023             me.tooltip = Ext.create('Ext.tip.ToolTip', me.tipConfig);
42024             Ext.getBody().on('mousemove', me.tooltip.onMouseMove, me.tooltip);
42025             if (me.tipConfig.surface) {
42026                 
42027                 surface = me.tipConfig.surface;
42028                 sprites = surface.sprites;
42029                 tipSurface = Ext.create('Ext.chart.TipSurface', {
42030                     id: 'tipSurfaceComponent',
42031                     sprites: sprites
42032                 });
42033                 if (surface.width && surface.height) {
42034                     tipSurface.setSize(surface.width, surface.height);
42035                 }
42036                 me.tooltip.add(tipSurface);
42037                 me.spriteTip = tipSurface;
42038             }
42039         }
42040     },
42041
42042     showTip: function(item) {
42043         var me = this;
42044         if (!me.tooltip) {
42045             return;
42046         }
42047         clearTimeout(me.tipTimeout);
42048         var tooltip = me.tooltip,
42049             spriteTip = me.spriteTip,
42050             tipConfig = me.tipConfig,
42051             trackMouse = tooltip.trackMouse,
42052             sprite, surface, surfaceExt, pos, x, y;
42053         if (!trackMouse) {
42054             tooltip.trackMouse = true;
42055             sprite = item.sprite;
42056             surface = sprite.surface;
42057             surfaceExt = Ext.get(surface.getId());
42058             if (surfaceExt) {
42059                 pos = surfaceExt.getXY();
42060                 x = pos[0] + (sprite.attr.x || 0) + (sprite.attr.translation && sprite.attr.translation.x || 0);
42061                 y = pos[1] + (sprite.attr.y || 0) + (sprite.attr.translation && sprite.attr.translation.y || 0);
42062                 tooltip.targetXY = [x, y];
42063             }
42064         }
42065         if (spriteTip) {
42066             tipConfig.renderer.call(tooltip, item.storeItem, item, spriteTip.surface);
42067         } else {
42068             tipConfig.renderer.call(tooltip, item.storeItem, item);
42069         }
42070         tooltip.show();
42071         tooltip.trackMouse = trackMouse;
42072     },
42073
42074     hideTip: function(item) {
42075         var tooltip = this.tooltip;
42076         if (!tooltip) {
42077             return;
42078         }
42079         clearTimeout(this.tipTimeout);
42080         this.tipTimeout = setTimeout(function() {
42081             tooltip.hide();
42082         }, 0);
42083     }
42084 });
42085
42086 Ext.define('Ext.chart.axis.Abstract', {
42087
42088     
42089
42090     requires: ['Ext.chart.Chart'],
42091
42092     
42093
42094     constructor: function(config) {
42095         config = config || {};
42096
42097         var me = this,
42098             pos = config.position || 'left';
42099
42100         pos = pos.charAt(0).toUpperCase() + pos.substring(1);
42101         
42102         config.label = Ext.apply(config['axisLabel' + pos + 'Style'] || {}, config.label || {});
42103         config.axisTitleStyle = Ext.apply(config['axisTitle' + pos + 'Style'] || {}, config.labelTitle || {});
42104         Ext.apply(me, config);
42105         me.fields = [].concat(me.fields);
42106         this.callParent();
42107         me.labels = [];
42108         me.getId();
42109         me.labelGroup = me.chart.surface.getGroup(me.axisId + "-labels");
42110     },
42111
42112     alignment: null,
42113     grid: false,
42114     steps: 10,
42115     x: 0,
42116     y: 0,
42117     minValue: 0,
42118     maxValue: 0,
42119
42120     getId: function() {
42121         return this.axisId || (this.axisId = Ext.id(null, 'ext-axis-'));
42122     },
42123
42124     
42125     processView: Ext.emptyFn,
42126
42127     drawAxis: Ext.emptyFn,
42128     addDisplayAndLabels: Ext.emptyFn
42129 });
42130
42131
42132 Ext.define('Ext.chart.axis.Axis', {
42133
42134     
42135
42136     extend: 'Ext.chart.axis.Abstract',
42137
42138     alternateClassName: 'Ext.chart.Axis',
42139
42140     requires: ['Ext.draw.Draw'],
42141
42142     
42143
42144     
42145
42146     
42147     
42148     //@private force min/max values from store
42149
42150     forceMinMax: false,
42151     
42152     
42153     dashSize: 3,
42154     
42155     
42156     position: 'bottom',
42157     
42158     
42159     skipFirst: false,
42160     
42161     
42162     length: 0,
42163     
42164     
42165     width: 0,
42166     
42167     majorTickSteps: false,
42168
42169     
42170     applyData: Ext.emptyFn,
42171
42172     
42173     calcEnds: function() {
42174         var me = this,
42175             math = Math,
42176             mmax = math.max,
42177             mmin = math.min,
42178             store = me.chart.substore || me.chart.store,
42179             series = me.chart.series.items,
42180             fields = me.fields,
42181             ln = fields.length,
42182             min = isNaN(me.minimum) ? Infinity : me.minimum,
42183             max = isNaN(me.maximum) ? -Infinity : me.maximum,
42184             prevMin = me.prevMin,
42185             prevMax = me.prevMax,
42186             aggregate = false,
42187             total = 0,
42188             excludes = [],
42189             outfrom, outto,
42190             i, l, values, rec, out;
42191
42192         
42193         
42194         for (i = 0, l = series.length; !aggregate && i < l; i++) {
42195             aggregate = aggregate || series[i].stacked;
42196             excludes = series[i].__excludes || excludes;
42197         }
42198         store.each(function(record) {
42199             if (aggregate) {
42200                 if (!isFinite(min)) {
42201                     min = 0;
42202                 }
42203                 for (values = [0, 0], i = 0; i < ln; i++) {
42204                     if (excludes[i]) {
42205                         continue;
42206                     }
42207                     rec = record.get(fields[i]);
42208                     values[+(rec > 0)] += math.abs(rec);
42209                 }
42210                 max = mmax(max, -values[0], values[1]);
42211                 min = mmin(min, -values[0], values[1]);
42212             }
42213             else {
42214                 for (i = 0; i < ln; i++) {
42215                     if (excludes[i]) {
42216                         continue;
42217                     }
42218                     value = record.get(fields[i]);
42219                     max = mmax(max, value);
42220                     min = mmin(min, value);
42221                 }
42222             }
42223         });
42224         if (!isFinite(max)) {
42225             max = me.prevMax || 0;
42226         }
42227         if (!isFinite(min)) {
42228             min = me.prevMin || 0;
42229         }
42230         
42231         if (min != max && (max != (max >> 0))) {
42232             max = (max >> 0) + 1;
42233         }
42234         out = Ext.draw.Draw.snapEnds(min, max, me.majorTickSteps !== false ?  (me.majorTickSteps +1) : me.steps);
42235         outfrom = out.from;
42236         outto = out.to;
42237         if (me.forceMinMax) {
42238             if (!isNaN(max)) {
42239                 out.to = max;
42240             }
42241             if (!isNaN(min)) {
42242                 out.from = min;
42243             }
42244         }
42245         if (!isNaN(me.maximum)) {
42246             
42247             
42248             out.to = me.maximum;
42249         }
42250         if (!isNaN(me.minimum)) {
42251             
42252             
42253             out.from = me.minimum;
42254         }
42255         
42256         
42257         out.step = (out.to - out.from) / (outto - outfrom) * out.step;
42258         
42259         if (me.adjustMaximumByMajorUnit) {
42260             out.to += out.step;
42261         }
42262         if (me.adjustMinimumByMajorUnit) {
42263             out.from -= out.step;
42264         }
42265         me.prevMin = min == max? 0 : min;
42266         me.prevMax = max;
42267         return out;
42268     },
42269
42270     
42271     drawAxis: function (init) {
42272         var me = this,
42273             i, j,
42274             x = me.x,
42275             y = me.y,
42276             gutterX = me.chart.maxGutter[0],
42277             gutterY = me.chart.maxGutter[1],
42278             dashSize = me.dashSize,
42279             subDashesX = me.minorTickSteps || 0,
42280             subDashesY = me.minorTickSteps || 0,
42281             length = me.length,
42282             position = me.position,
42283             inflections = [],
42284             calcLabels = false,
42285             stepCalcs = me.applyData(),
42286             step = stepCalcs.step,
42287             steps = stepCalcs.steps,
42288             from = stepCalcs.from,
42289             to = stepCalcs.to,
42290             trueLength,
42291             currentX,
42292             currentY,
42293             path,
42294             prev,
42295             dashesX,
42296             dashesY,
42297             delta;
42298         
42299         
42300         
42301         
42302         if (me.hidden || isNaN(step) || (from == to)) {
42303             return;
42304         }
42305
42306         me.from = stepCalcs.from;
42307         me.to = stepCalcs.to;
42308         if (position == 'left' || position == 'right') {
42309             currentX = Math.floor(x) + 0.5;
42310             path = ["M", currentX, y, "l", 0, -length];
42311             trueLength = length - (gutterY * 2);
42312         }
42313         else {
42314             currentY = Math.floor(y) + 0.5;
42315             path = ["M", x, currentY, "l", length, 0];
42316             trueLength = length - (gutterX * 2);
42317         }
42318         
42319         delta = trueLength / (steps || 1);
42320         dashesX = Math.max(subDashesX +1, 0);
42321         dashesY = Math.max(subDashesY +1, 0);
42322         if (me.type == 'Numeric') {
42323             calcLabels = true;
42324             me.labels = [stepCalcs.from];
42325         }
42326         if (position == 'right' || position == 'left') {
42327             currentY = y - gutterY;
42328             currentX = x - ((position == 'left') * dashSize * 2);
42329             while (currentY >= y - gutterY - trueLength) {
42330                 path.push("M", currentX, Math.floor(currentY) + 0.5, "l", dashSize * 2 + 1, 0);
42331                 if (currentY != y - gutterY) {
42332                     for (i = 1; i < dashesY; i++) {
42333                         path.push("M", currentX + dashSize, Math.floor(currentY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
42334                     }
42335                 }
42336                 inflections.push([ Math.floor(x), Math.floor(currentY) ]);
42337                 currentY -= delta;
42338                 if (calcLabels) {
42339                     me.labels.push(me.labels[me.labels.length -1] + step);
42340                 }
42341                 if (delta === 0) {
42342                     break;
42343                 }
42344             }
42345             if (Math.round(currentY + delta - (y - gutterY - trueLength))) {
42346                 path.push("M", currentX, Math.floor(y - length + gutterY) + 0.5, "l", dashSize * 2 + 1, 0);
42347                 for (i = 1; i < dashesY; i++) {
42348                     path.push("M", currentX + dashSize, Math.floor(y - length + gutterY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
42349                 }
42350                 inflections.push([ Math.floor(x), Math.floor(currentY) ]);
42351                 if (calcLabels) {
42352                     me.labels.push(me.labels[me.labels.length -1] + step);
42353                 }
42354             }
42355         } else {
42356             currentX = x + gutterX;
42357             currentY = y - ((position == 'top') * dashSize * 2);
42358             while (currentX <= x + gutterX + trueLength) {
42359                 path.push("M", Math.floor(currentX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
42360                 if (currentX != x + gutterX) {
42361                     for (i = 1; i < dashesX; i++) {
42362                         path.push("M", Math.floor(currentX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
42363                     }
42364                 }
42365                 inflections.push([ Math.floor(currentX), Math.floor(y) ]);
42366                 currentX += delta;
42367                 if (calcLabels) {
42368                     me.labels.push(me.labels[me.labels.length -1] + step);
42369                 }
42370                 if (delta === 0) {
42371                     break;
42372                 }
42373             }
42374             if (Math.round(currentX - delta - (x + gutterX + trueLength))) {
42375                 path.push("M", Math.floor(x + length - gutterX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
42376                 for (i = 1; i < dashesX; i++) {
42377                     path.push("M", Math.floor(x + length - gutterX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
42378                 }
42379                 inflections.push([ Math.floor(currentX), Math.floor(y) ]);
42380                 if (calcLabels) {
42381                     me.labels.push(me.labels[me.labels.length -1] + step);
42382                 }
42383             }
42384         }
42385         if (!me.axis) {
42386             me.axis = me.chart.surface.add(Ext.apply({
42387                 type: 'path',
42388                 path: path
42389             }, me.axisStyle));
42390         }
42391         me.axis.setAttributes({
42392             path: path
42393         }, true);
42394         me.inflections = inflections;
42395         if (!init && me.grid) {
42396             me.drawGrid();
42397         }
42398         me.axisBBox = me.axis.getBBox();
42399         me.drawLabel();
42400     },
42401
42402     
42403     drawGrid: function() {
42404         var me = this,
42405             surface = me.chart.surface, 
42406             grid = me.grid,
42407             odd = grid.odd,
42408             even = grid.even,
42409             inflections = me.inflections,
42410             ln = inflections.length - ((odd || even)? 0 : 1),
42411             position = me.position,
42412             gutter = me.chart.maxGutter,
42413             width = me.width - 2,
42414             vert = false,
42415             point, prevPoint,
42416             i = 1,
42417             path = [], styles, lineWidth, dlineWidth,
42418             oddPath = [], evenPath = [];
42419         
42420         if ((gutter[1] !== 0 && (position == 'left' || position == 'right')) ||
42421             (gutter[0] !== 0 && (position == 'top' || position == 'bottom'))) {
42422             i = 0;
42423             ln++;
42424         }
42425         for (; i < ln; i++) {
42426             point = inflections[i];
42427             prevPoint = inflections[i - 1];
42428             if (odd || even) {
42429                 path = (i % 2)? oddPath : evenPath;
42430                 styles = ((i % 2)? odd : even) || {};
42431                 lineWidth = (styles.lineWidth || styles['stroke-width'] || 0) / 2;
42432                 dlineWidth = 2 * lineWidth;
42433                 if (position == 'left') {
42434                     path.push("M", prevPoint[0] + 1 + lineWidth, prevPoint[1] + 0.5 - lineWidth, 
42435                               "L", prevPoint[0] + 1 + width - lineWidth, prevPoint[1] + 0.5 - lineWidth,
42436                               "L", point[0] + 1 + width - lineWidth, point[1] + 0.5 + lineWidth,
42437                               "L", point[0] + 1 + lineWidth, point[1] + 0.5 + lineWidth, "Z");
42438                 }
42439                 else if (position == 'right') {
42440                     path.push("M", prevPoint[0] - lineWidth, prevPoint[1] + 0.5 - lineWidth, 
42441                               "L", prevPoint[0] - width + lineWidth, prevPoint[1] + 0.5 - lineWidth,
42442                               "L", point[0] - width + lineWidth, point[1] + 0.5 + lineWidth,
42443                               "L", point[0] - lineWidth, point[1] + 0.5 + lineWidth, "Z");
42444                 }
42445                 else if (position == 'top') {
42446                     path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + lineWidth, 
42447                               "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + width - lineWidth,
42448                               "L", point[0] + 0.5 - lineWidth, point[1] + 1 + width - lineWidth,
42449                               "L", point[0] + 0.5 - lineWidth, point[1] + 1 + lineWidth, "Z");
42450                 }
42451                 else {
42452                     path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - lineWidth, 
42453                             "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - width + lineWidth,
42454                             "L", point[0] + 0.5 - lineWidth, point[1] - width + lineWidth,
42455                             "L", point[0] + 0.5 - lineWidth, point[1] - lineWidth, "Z");
42456                 }
42457             } else {
42458                 if (position == 'left') {
42459                     path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", width, 0]);
42460                 }
42461                 else if (position == 'right') {
42462                     path = path.concat(["M", point[0] - 0.5, point[1] + 0.5, "l", -width, 0]);
42463                 }
42464                 else if (position == 'top') {
42465                     path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", 0, width]);
42466                 }
42467                 else {
42468                     path = path.concat(["M", point[0] + 0.5, point[1] - 0.5, "l", 0, -width]);
42469                 }
42470             }
42471         }
42472         if (odd || even) {
42473             if (oddPath.length) {
42474                 if (!me.gridOdd && oddPath.length) {
42475                     me.gridOdd = surface.add({
42476                         type: 'path',
42477                         path: oddPath
42478                     });
42479                 }
42480                 me.gridOdd.setAttributes(Ext.apply({
42481                     path: oddPath,
42482                     hidden: false
42483                 }, odd || {}), true);
42484             }
42485             if (evenPath.length) {
42486                 if (!me.gridEven) {
42487                     me.gridEven = surface.add({
42488                         type: 'path',
42489                         path: evenPath
42490                     });
42491                 } 
42492                 me.gridEven.setAttributes(Ext.apply({
42493                     path: evenPath,
42494                     hidden: false
42495                 }, even || {}), true);
42496             }
42497         }
42498         else {
42499             if (path.length) {
42500                 if (!me.gridLines) {
42501                     me.gridLines = me.chart.surface.add({
42502                         type: 'path',
42503                         path: path,
42504                         "stroke-width": me.lineWidth || 1,
42505                         stroke: me.gridColor || '#ccc'
42506                     });
42507                 }
42508                 me.gridLines.setAttributes({
42509                     hidden: false,
42510                     path: path
42511                 }, true);
42512             }
42513             else if (me.gridLines) {
42514                 me.gridLines.hide(true);
42515             }
42516         }
42517     },
42518
42519     //@private
42520
42521     getOrCreateLabel: function(i, text) {
42522         var me = this,
42523             labelGroup = me.labelGroup,
42524             textLabel = labelGroup.getAt(i),
42525             surface = me.chart.surface;
42526         if (textLabel) {
42527             if (text != textLabel.attr.text) {
42528                 textLabel.setAttributes(Ext.apply({
42529                     text: text
42530                 }, me.label), true);
42531                 textLabel._bbox = textLabel.getBBox();
42532             }
42533         }
42534         else {
42535             textLabel = surface.add(Ext.apply({
42536                 group: labelGroup,
42537                 type: 'text',
42538                 x: 0,
42539                 y: 0,
42540                 text: text
42541             }, me.label));
42542             surface.renderItem(textLabel);
42543             textLabel._bbox = textLabel.getBBox();
42544         }
42545         
42546         if (me.label.rotation) {
42547             textLabel.setAttributes({
42548                 rotation: {
42549                     degrees: 0    
42550                 }    
42551             }, true);
42552             textLabel._ubbox = textLabel.getBBox();
42553             textLabel.setAttributes(me.label, true);
42554         } else {
42555             textLabel._ubbox = textLabel._bbox;
42556         }
42557         return textLabel;
42558     },
42559     
42560     rect2pointArray: function(sprite) {
42561         var surface = this.chart.surface,
42562             rect = surface.getBBox(sprite, true),
42563             p1 = [rect.x, rect.y],
42564             p1p = p1.slice(),
42565             p2 = [rect.x + rect.width, rect.y],
42566             p2p = p2.slice(),
42567             p3 = [rect.x + rect.width, rect.y + rect.height],
42568             p3p = p3.slice(),
42569             p4 = [rect.x, rect.y + rect.height],
42570             p4p = p4.slice(),
42571             matrix = sprite.matrix;
42572         
42573         p1[0] = matrix.x.apply(matrix, p1p);
42574         p1[1] = matrix.y.apply(matrix, p1p);
42575         
42576         p2[0] = matrix.x.apply(matrix, p2p);
42577         p2[1] = matrix.y.apply(matrix, p2p);
42578         
42579         p3[0] = matrix.x.apply(matrix, p3p);
42580         p3[1] = matrix.y.apply(matrix, p3p);
42581         
42582         p4[0] = matrix.x.apply(matrix, p4p);
42583         p4[1] = matrix.y.apply(matrix, p4p);
42584         return [p1, p2, p3, p4];
42585     },
42586     
42587     intersect: function(l1, l2) {
42588         var r1 = this.rect2pointArray(l1),
42589             r2 = this.rect2pointArray(l2);
42590         return !!Ext.draw.Draw.intersect(r1, r2).length;
42591     },
42592     
42593     drawHorizontalLabels: function() {
42594        var  me = this,
42595             labelConf = me.label,
42596             floor = Math.floor,
42597             max = Math.max,
42598             axes = me.chart.axes,
42599             position = me.position,
42600             inflections = me.inflections,
42601             ln = inflections.length,
42602             labels = me.labels,
42603             labelGroup = me.labelGroup,
42604             maxHeight = 0,
42605             ratio,
42606             gutterY = me.chart.maxGutter[1],
42607             ubbox, bbox, point, prevX, prevLabel,
42608             projectedWidth = 0,
42609             textLabel, attr, textRight, text,
42610             label, last, x, y, i, firstLabel;
42611
42612         last = ln - 1;
42613         
42614         point = inflections[0];
42615         firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0]));
42616         ratio = Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0)) >> 0;
42617         
42618         for (i = 0; i < ln; i++) {
42619             point = inflections[i];
42620             text = me.label.renderer(labels[i]);
42621             textLabel = me.getOrCreateLabel(i, text);
42622             bbox = textLabel._bbox;
42623             maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding);
42624             x = floor(point[0] - (ratio? bbox.height : bbox.width) / 2);
42625             if (me.chart.maxGutter[0] == 0) {
42626                 if (i == 0 && axes.findIndex('position', 'left') == -1) {
42627                     x = point[0];
42628                 }
42629                 else if (i == last && axes.findIndex('position', 'right') == -1) {
42630                     x = point[0] - bbox.width;
42631                 }
42632             }
42633             if (position == 'top') {
42634                 y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2);
42635             }
42636             else {
42637                 y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2);
42638             }
42639             
42640             textLabel.setAttributes({
42641                 hidden: false,
42642                 x: x,
42643                 y: y
42644             }, true);
42645
42646             
42647             if (i != 0 && (me.intersect(textLabel, prevLabel)
42648                 || me.intersect(textLabel, firstLabel))) {
42649                 textLabel.hide(true);
42650                 continue;
42651             }
42652             
42653             prevLabel = textLabel;
42654         }
42655
42656         return maxHeight;
42657     },
42658     
42659     drawVerticalLabels: function() {
42660         var me = this,
42661             inflections = me.inflections,
42662             position = me.position,
42663             ln = inflections.length,
42664             labels = me.labels,
42665             maxWidth = 0,
42666             max = Math.max,
42667             floor = Math.floor,
42668             ceil = Math.ceil,
42669             axes = me.chart.axes,
42670             gutterY = me.chart.maxGutter[1],
42671             ubbox, bbox, point, prevLabel,
42672             projectedWidth = 0,
42673             textLabel, attr, textRight, text,
42674             label, last, x, y, i;
42675
42676         last = ln;
42677         for (i = 0; i < last; i++) {
42678             point = inflections[i];
42679             text = me.label.renderer(labels[i]);
42680             textLabel = me.getOrCreateLabel(i, text);
42681             bbox = textLabel._bbox;
42682             
42683             maxWidth = max(maxWidth, bbox.width + me.dashSize + me.label.padding);
42684             y = point[1];
42685             if (gutterY < bbox.height / 2) {
42686                 if (i == last - 1 && axes.findIndex('position', 'top') == -1) {
42687                     y = me.y - me.length + ceil(bbox.height / 2);
42688                 }
42689                 else if (i == 0 && axes.findIndex('position', 'bottom') == -1) {
42690                     y = me.y - floor(bbox.height / 2);
42691                 }
42692             }
42693             if (position == 'left') {
42694                 x = point[0] - bbox.width - me.dashSize - me.label.padding - 2;
42695             }
42696             else {
42697                 x = point[0] + me.dashSize + me.label.padding + 2;
42698             }    
42699             textLabel.setAttributes(Ext.apply({
42700                 hidden: false,
42701                 x: x,
42702                 y: y
42703             }, me.label), true);
42704             
42705             if (i != 0 && me.intersect(textLabel, prevLabel)) {
42706                 textLabel.hide(true);
42707                 continue;
42708             }
42709             prevLabel = textLabel;
42710         }
42711         
42712         return maxWidth;
42713     },
42714
42715     
42716     drawLabel: function() {
42717         var me = this,
42718             position = me.position,
42719             labelGroup = me.labelGroup,
42720             inflections = me.inflections,
42721             maxWidth = 0,
42722             maxHeight = 0,
42723             ln, i;
42724
42725         if (position == 'left' || position == 'right') {
42726             maxWidth = me.drawVerticalLabels();    
42727         } else {
42728             maxHeight = me.drawHorizontalLabels();
42729         }
42730
42731         
42732         ln = labelGroup.getCount();
42733         i = inflections.length;
42734         for (; i < ln; i++) {
42735             labelGroup.getAt(i).hide(true);
42736         }
42737
42738         me.bbox = {};
42739         Ext.apply(me.bbox, me.axisBBox);
42740         me.bbox.height = maxHeight;
42741         me.bbox.width = maxWidth;
42742         if (Ext.isString(me.title)) {
42743             me.drawTitle(maxWidth, maxHeight);
42744         }
42745     },
42746
42747     
42748     elipsis: function(sprite, text, desiredWidth, minWidth, center) {
42749         var bbox,
42750             x;
42751
42752         if (desiredWidth < minWidth) {
42753             sprite.hide(true);
42754             return false;
42755         }
42756         while (text.length > 4) {
42757             text = text.substr(0, text.length - 4) + "...";
42758             sprite.setAttributes({
42759                 text: text
42760             }, true);
42761             bbox = sprite.getBBox();
42762             if (bbox.width < desiredWidth) {
42763                 if (typeof center == 'number') {
42764                     sprite.setAttributes({
42765                         x: Math.floor(center - (bbox.width / 2))
42766                     }, true);
42767                 }
42768                 break;
42769             }
42770         }
42771         return true;
42772     },
42773
42774     
42775     setTitle: function(title) {
42776         this.title = title;
42777         this.drawLabel();
42778     },
42779
42780     
42781     drawTitle: function(maxWidth, maxHeight) {
42782         var me = this,
42783             position = me.position,
42784             surface = me.chart.surface,
42785             displaySprite = me.displaySprite,
42786             title = me.title,
42787             rotate = (position == 'left' || position == 'right'),
42788             x = me.x,
42789             y = me.y,
42790             base, bbox, pad;
42791
42792         if (displaySprite) {
42793             displaySprite.setAttributes({text: title}, true);
42794         } else {
42795             base = {
42796                 type: 'text',
42797                 x: 0,
42798                 y: 0,
42799                 text: title
42800             };
42801             displaySprite = me.displaySprite = surface.add(Ext.apply(base, me.axisTitleStyle, me.labelTitle));
42802             surface.renderItem(displaySprite);
42803         }
42804         bbox = displaySprite.getBBox();
42805         pad = me.dashSize + me.label.padding;
42806
42807         if (rotate) {
42808             y -= ((me.length / 2) - (bbox.height / 2));
42809             if (position == 'left') {
42810                 x -= (maxWidth + pad + (bbox.width / 2));
42811             }
42812             else {
42813                 x += (maxWidth + pad + bbox.width - (bbox.width / 2));
42814             }
42815             me.bbox.width += bbox.width + 10;
42816         }
42817         else {
42818             x += (me.length / 2) - (bbox.width * 0.5);
42819             if (position == 'top') {
42820                 y -= (maxHeight + pad + (bbox.height * 0.3));
42821             }
42822             else {
42823                 y += (maxHeight + pad + (bbox.height * 0.8));
42824             }
42825             me.bbox.height += bbox.height + 10;
42826         }
42827         displaySprite.setAttributes({
42828             translate: {
42829                 x: x,
42830                 y: y
42831             }
42832         }, true);
42833     }
42834 });
42835
42836
42837 Ext.define('Ext.chart.axis.Category', {
42838
42839     
42840
42841     extend: 'Ext.chart.axis.Axis',
42842
42843     alternateClassName: 'Ext.chart.CategoryAxis',
42844
42845     alias: 'axis.category',
42846
42847     
42848
42849     
42850     categoryNames: null,
42851
42852     
42853     calculateCategoryCount: false,
42854
42855     
42856     setLabels: function() {
42857         var store = this.chart.store,
42858             fields = this.fields,
42859             ln = fields.length,
42860             i;
42861
42862         this.labels = [];
42863         store.each(function(record) {
42864             for (i = 0; i < ln; i++) {
42865                 this.labels.push(record.get(fields[i]));
42866             }
42867         }, this);
42868     },
42869
42870     
42871     applyData: function() {
42872         this.callParent();
42873         this.setLabels();
42874         var count = this.chart.store.getCount();
42875         return {
42876             from: 0,
42877             to: count,
42878             power: 1,
42879             step: 1,
42880             steps: count - 1
42881         };
42882     }
42883 });
42884
42885
42886 Ext.define('Ext.chart.axis.Gauge', {
42887
42888     
42889
42890     extend: 'Ext.chart.axis.Abstract',
42891
42892     
42893     
42894     
42895
42896     
42897
42898     
42899
42900     
42901
42902     position: 'gauge',
42903
42904     alias: 'axis.gauge',
42905
42906     drawAxis: function(init) {
42907         var chart = this.chart,
42908             surface = chart.surface,
42909             bbox = chart.chartBBox,
42910             centerX = bbox.x + (bbox.width / 2),
42911             centerY = bbox.y + bbox.height,
42912             margin = this.margin || 10,
42913             rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin,
42914             sprites = [], sprite,
42915             steps = this.steps,
42916             i, pi = Math.PI,
42917             cos = Math.cos,
42918             sin = Math.sin;
42919
42920         if (this.sprites && !chart.resizing) {
42921             this.drawLabel();
42922             return;
42923         }
42924
42925         if (this.margin >= 0) {
42926             if (!this.sprites) {
42927                 
42928                 for (i = 0; i <= steps; i++) {
42929                     sprite = surface.add({
42930                         type: 'path',
42931                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
42932                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
42933                                     'L', centerX + rho * cos(i / steps * pi - pi),
42934                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
42935                         stroke: '#ccc'
42936                     });
42937                     sprite.setAttributes({
42938                         hidden: false
42939                     }, true);
42940                     sprites.push(sprite);
42941                 }
42942             } else {
42943                 sprites = this.sprites;
42944                 
42945                 for (i = 0; i <= steps; i++) {
42946                     sprites[i].setAttributes({
42947                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
42948                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
42949                                'L', centerX + rho * cos(i / steps * pi - pi),
42950                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
42951                         stroke: '#ccc'
42952                     }, true);
42953                 }
42954             }
42955         }
42956         this.sprites = sprites;
42957         this.drawLabel();
42958         if (this.title) {
42959             this.drawTitle();
42960         }
42961     },
42962     
42963     drawTitle: function() {
42964         var me = this,
42965             chart = me.chart,
42966             surface = chart.surface,
42967             bbox = chart.chartBBox,
42968             labelSprite = me.titleSprite,
42969             labelBBox;
42970         
42971         if (!labelSprite) {
42972             me.titleSprite = labelSprite = surface.add({
42973                 type: 'text',
42974                 zIndex: 2
42975             });    
42976         }
42977         labelSprite.setAttributes(Ext.apply({
42978             text: me.title
42979         }, me.label || {}), true);
42980         labelBBox = labelSprite.getBBox();
42981         labelSprite.setAttributes({
42982             x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2),
42983             y: bbox.y + bbox.height - (labelBBox.height / 2) - 4
42984         }, true);
42985     },
42986
42987     
42988     setTitle: function(title) {
42989         this.title = title;
42990         this.drawTitle();
42991     },
42992
42993     drawLabel: function() {
42994         var chart = this.chart,
42995             surface = chart.surface,
42996             bbox = chart.chartBBox,
42997             centerX = bbox.x + (bbox.width / 2),
42998             centerY = bbox.y + bbox.height,
42999             margin = this.margin || 10,
43000             rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin,
43001             round = Math.round,
43002             labelArray = [], label,
43003             maxValue = this.maximum || 0,
43004             steps = this.steps, i = 0,
43005             adjY,
43006             pi = Math.PI,
43007             cos = Math.cos,
43008             sin = Math.sin,
43009             labelConf = this.label,
43010             renderer = labelConf.renderer || function(v) { return v; };
43011
43012         if (!this.labelArray) {
43013             
43014             for (i = 0; i <= steps; i++) {
43015                 
43016                 adjY = (i === 0 || i === steps) ? 7 : 0;
43017                 label = surface.add({
43018                     type: 'text',
43019                     text: renderer(round(i / steps * maxValue)),
43020                     x: centerX + rho * cos(i / steps * pi - pi),
43021                     y: centerY + rho * sin(i / steps * pi - pi) - adjY,
43022                     'text-anchor': 'middle',
43023                     'stroke-width': 0.2,
43024                     zIndex: 10,
43025                     stroke: '#333'
43026                 });
43027                 label.setAttributes({
43028                     hidden: false
43029                 }, true);
43030                 labelArray.push(label);
43031             }
43032         }
43033         else {
43034             labelArray = this.labelArray;
43035             
43036             for (i = 0; i <= steps; i++) {
43037                 
43038                 adjY = (i === 0 || i === steps) ? 7 : 0;
43039                 labelArray[i].setAttributes({
43040                     text: renderer(round(i / steps * maxValue)),
43041                     x: centerX + rho * cos(i / steps * pi - pi),
43042                     y: centerY + rho * sin(i / steps * pi - pi) - adjY
43043                 }, true);
43044             }
43045         }
43046         this.labelArray = labelArray;
43047     }
43048 });
43049
43050 Ext.define('Ext.chart.axis.Numeric', {
43051
43052     
43053
43054     extend: 'Ext.chart.axis.Axis',
43055
43056     alternateClassName: 'Ext.chart.NumericAxis',
43057
43058     
43059
43060     type: 'numeric',
43061
43062     alias: 'axis.numeric',
43063
43064     constructor: function(config) {
43065         var me = this, label, f;
43066         me.callParent([config]);
43067         label = me.label;
43068         if (me.roundToDecimal === false) {
43069             return;
43070         }
43071         if (label.renderer) {
43072             f = label.renderer;
43073             label.renderer = function(v) {
43074                 return me.roundToDecimal( f(v), me.decimals );
43075             };
43076         } else {
43077             label.renderer = function(v) {
43078                 return me.roundToDecimal(v, me.decimals);
43079             };
43080         }
43081     },
43082     
43083     roundToDecimal: function(v, dec) {
43084         var val = Math.pow(10, dec || 0);
43085         return ((v * val) >> 0) / val;
43086     },
43087     
43088     
43089     minimum: NaN,
43090
43091     
43092     maximum: NaN,
43093
43094     
43095     decimals: 2,
43096
43097     
43098     scale: "linear",
43099
43100     
43101     position: 'left',
43102
43103     
43104     adjustMaximumByMajorUnit: false,
43105
43106     
43107     adjustMinimumByMajorUnit: false,
43108
43109     
43110     applyData: function() {
43111         this.callParent();
43112         return this.calcEnds();
43113     }
43114 });
43115
43116
43117 Ext.define('Ext.chart.axis.Radial', {
43118
43119     
43120
43121     extend: 'Ext.chart.axis.Abstract',
43122
43123     
43124
43125     position: 'radial',
43126
43127     alias: 'axis.radial',
43128
43129     drawAxis: function(init) {
43130         var chart = this.chart,
43131             surface = chart.surface,
43132             bbox = chart.chartBBox,
43133             store = chart.store,
43134             l = store.getCount(),
43135             centerX = bbox.x + (bbox.width / 2),
43136             centerY = bbox.y + (bbox.height / 2),
43137             rho = Math.min(bbox.width, bbox.height) /2,
43138             sprites = [], sprite,
43139             steps = this.steps,
43140             i, j, pi2 = Math.PI * 2,
43141             cos = Math.cos, sin = Math.sin;
43142
43143         if (this.sprites && !chart.resizing) {
43144             this.drawLabel();
43145             return;
43146         }
43147
43148         if (!this.sprites) {
43149             
43150             for (i = 1; i <= steps; i++) {
43151                 sprite = surface.add({
43152                     type: 'circle',
43153                     x: centerX,
43154                     y: centerY,
43155                     radius: Math.max(rho * i / steps, 0),
43156                     stroke: '#ccc'
43157                 });
43158                 sprite.setAttributes({
43159                     hidden: false
43160                 }, true);
43161                 sprites.push(sprite);
43162             }
43163             
43164             store.each(function(rec, i) {
43165                 sprite = surface.add({
43166                     type: 'path',
43167                     path: ['M', centerX, centerY, 'L', centerX + rho * cos(i / l * pi2), centerY + rho * sin(i / l * pi2), 'Z'],
43168                     stroke: '#ccc'
43169                 });
43170                 sprite.setAttributes({
43171                     hidden: false
43172                 }, true);
43173                 sprites.push(sprite);
43174             });
43175         } else {
43176             sprites = this.sprites;
43177             
43178             for (i = 0; i < steps; i++) {
43179                 sprites[i].setAttributes({
43180                     x: centerX,
43181                     y: centerY,
43182                     radius: Math.max(rho * (i + 1) / steps, 0),
43183                     stroke: '#ccc'
43184                 }, true);
43185             }
43186             
43187             store.each(function(rec, j) {
43188                 sprites[i + j].setAttributes({
43189                     path: ['M', centerX, centerY, 'L', centerX + rho * cos(j / l * pi2), centerY + rho * sin(j / l * pi2), 'Z'],
43190                     stroke: '#ccc'
43191                 }, true);
43192             });
43193         }
43194         this.sprites = sprites;
43195
43196         this.drawLabel();
43197     },
43198
43199     drawLabel: function() {
43200         var chart = this.chart,
43201             surface = chart.surface,
43202             bbox = chart.chartBBox,
43203             store = chart.store,
43204             centerX = bbox.x + (bbox.width / 2),
43205             centerY = bbox.y + (bbox.height / 2),
43206             rho = Math.min(bbox.width, bbox.height) /2,
43207             max = Math.max, round = Math.round,
43208             labelArray = [], label,
43209             fields = [], nfields,
43210             categories = [], xField,
43211             aggregate = !this.maximum,
43212             maxValue = this.maximum || 0,
43213             steps = this.steps, i = 0, j, dx, dy,
43214             pi2 = Math.PI * 2,
43215             cos = Math.cos, sin = Math.sin,
43216             display = this.label.display,
43217             draw = display !== 'none',
43218             margin = 10;
43219
43220         if (!draw) {
43221             return;
43222         }
43223
43224         
43225         chart.series.each(function(series) {
43226             fields.push(series.yField);
43227             xField = series.xField;
43228         });
43229         
43230         
43231         store.each(function(record, i) {
43232             if (aggregate) {
43233                 for (i = 0, nfields = fields.length; i < nfields; i++) {
43234                     maxValue = max(+record.get(fields[i]), maxValue);
43235                 }
43236             }
43237             categories.push(record.get(xField));
43238         });
43239         if (!this.labelArray) {
43240             if (display != 'categories') {
43241                 
43242                 for (i = 1; i <= steps; i++) {
43243                     label = surface.add({
43244                         type: 'text',
43245                         text: round(i / steps * maxValue),
43246                         x: centerX,
43247                         y: centerY - rho * i / steps,
43248                         'text-anchor': 'middle',
43249                         'stroke-width': 0.1,
43250                         stroke: '#333'
43251                     });
43252                     label.setAttributes({
43253                         hidden: false
43254                     }, true);
43255                     labelArray.push(label);
43256                 }
43257             }
43258             if (display != 'scale') {
43259                 
43260                 for (j = 0, steps = categories.length; j < steps; j++) {
43261                     dx = cos(j / steps * pi2) * (rho + margin);
43262                     dy = sin(j / steps * pi2) * (rho + margin);
43263                     label = surface.add({
43264                         type: 'text',
43265                         text: categories[j],
43266                         x: centerX + dx,
43267                         y: centerY + dy,
43268                         'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start')
43269                     });
43270                     label.setAttributes({
43271                         hidden: false
43272                     }, true);
43273                     labelArray.push(label);
43274                 }
43275             }
43276         }
43277         else {
43278             labelArray = this.labelArray;
43279             if (display != 'categories') {
43280                 
43281                 for (i = 0; i < steps; i++) {
43282                     labelArray[i].setAttributes({
43283                         text: round((i + 1) / steps * maxValue),
43284                         x: centerX,
43285                         y: centerY - rho * (i + 1) / steps,
43286                         'text-anchor': 'middle',
43287                         'stroke-width': 0.1,
43288                         stroke: '#333'
43289                     }, true);
43290                 }
43291             }
43292             if (display != 'scale') {
43293                 
43294                 for (j = 0, steps = categories.length; j < steps; j++) {
43295                     dx = cos(j / steps * pi2) * (rho + margin);
43296                     dy = sin(j / steps * pi2) * (rho + margin);
43297                     if (labelArray[i + j]) {
43298                         labelArray[i + j].setAttributes({
43299                             type: 'text',
43300                             text: categories[j],
43301                             x: centerX + dx,
43302                             y: centerY + dy,
43303                             'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start')
43304                         }, true);
43305                     }
43306                 }
43307             }
43308         }
43309         this.labelArray = labelArray;
43310     }
43311 });
43312
43313 Ext.define('Ext.data.AbstractStore', {
43314     requires: ['Ext.util.MixedCollection', 'Ext.data.Operation', 'Ext.util.Filter'],
43315     
43316     mixins: {
43317         observable: 'Ext.util.Observable',
43318         sortable: 'Ext.util.Sortable'
43319     },
43320     
43321     statics: {
43322         create: function(store){
43323             if (!store.isStore) {
43324                 if (!store.type) {
43325                     store.type = 'store';
43326                 }
43327                 store = Ext.createByAlias('store.' + store.type, store);
43328             }
43329             return store;
43330         }    
43331     },
43332     
43333     remoteSort  : false,
43334     remoteFilter: false,
43335
43336     
43337
43338     
43339     autoLoad: false,
43340
43341     
43342     autoSync: false,
43343
43344     
43345     batchUpdateMode: 'operation',
43346
43347     
43348     filterOnLoad: true,
43349
43350     
43351     sortOnLoad: true,
43352
43353     
43354     implicitModel: false,
43355
43356     
43357     defaultProxyType: 'memory',
43358
43359     
43360     isDestroyed: false,
43361
43362     isStore: true,
43363
43364     
43365     
43366     
43367
43368     sortRoot: 'data',
43369     
43370     
43371     constructor: function(config) {
43372         var me = this,
43373             filters;
43374         
43375         me.addEvents(
43376             
43377             'add',
43378
43379             
43380             'remove',
43381             
43382             
43383             'update',
43384
43385             
43386             'datachanged',
43387
43388             
43389             'beforeload',
43390
43391             
43392             'load',
43393
43394             
43395             'beforesync',
43396             
43397             'clear'
43398         );
43399         
43400         Ext.apply(me, config);
43401         
43402
43403         
43404         me.removed = [];
43405
43406         me.mixins.observable.constructor.apply(me, arguments);
43407         me.model = Ext.ModelManager.getModel(me.model);
43408
43409         
43410         Ext.applyIf(me, {
43411             modelDefaults: {}
43412         });
43413
43414         
43415         if (!me.model && me.fields) {
43416             me.model = Ext.define('Ext.data.Store.ImplicitModel-' + (me.storeId || Ext.id()), {
43417                 extend: 'Ext.data.Model',
43418                 fields: me.fields,
43419                 proxy: me.proxy || me.defaultProxyType
43420             });
43421
43422             delete me.fields;
43423
43424             me.implicitModel = true;
43425         }
43426
43427         
43428         me.setProxy(me.proxy || me.model.getProxy());
43429
43430         if (me.id && !me.storeId) {
43431             me.storeId = me.id;
43432             delete me.id;
43433         }
43434
43435         if (me.storeId) {
43436             Ext.data.StoreManager.register(me);
43437         }
43438         
43439         me.mixins.sortable.initSortable.call(me);        
43440         
43441         
43442         filters = me.decodeFilters(me.filters);
43443         me.filters = Ext.create('Ext.util.MixedCollection');
43444         me.filters.addAll(filters);
43445     },
43446
43447     
43448     setProxy: function(proxy) {
43449         var me = this;
43450         
43451         if (proxy instanceof Ext.data.proxy.Proxy) {
43452             proxy.setModel(me.model);
43453         } else {
43454             if (Ext.isString(proxy)) {
43455                 proxy = {
43456                     type: proxy    
43457                 };
43458             }
43459             Ext.applyIf(proxy, {
43460                 model: me.model
43461             });
43462             
43463             proxy = Ext.createByAlias('proxy.' + proxy.type, proxy);
43464         }
43465         
43466         me.proxy = proxy;
43467         
43468         return me.proxy;
43469     },
43470
43471     
43472     getProxy: function() {
43473         return this.proxy;
43474     },
43475
43476     
43477     create: function(data, options) {
43478         var me = this,
43479             instance = Ext.ModelManager.create(Ext.applyIf(data, me.modelDefaults), me.model.modelName),
43480             operation;
43481         
43482         options = options || {};
43483
43484         Ext.applyIf(options, {
43485             action : 'create',
43486             records: [instance]
43487         });
43488
43489         operation = Ext.create('Ext.data.Operation', options);
43490
43491         me.proxy.create(operation, me.onProxyWrite, me);
43492         
43493         return instance;
43494     },
43495
43496     read: function() {
43497         return this.load.apply(this, arguments);
43498     },
43499
43500     onProxyRead: Ext.emptyFn,
43501
43502     update: function(options) {
43503         var me = this,
43504             operation;
43505         options = options || {};
43506
43507         Ext.applyIf(options, {
43508             action : 'update',
43509             records: me.getUpdatedRecords()
43510         });
43511
43512         operation = Ext.create('Ext.data.Operation', options);
43513
43514         return me.proxy.update(operation, me.onProxyWrite, me);
43515     },
43516
43517     
43518     onProxyWrite: function(operation) {
43519         var me = this,
43520             success = operation.wasSuccessful(),
43521             records = operation.getRecords();
43522
43523         switch (operation.action) {
43524             case 'create':
43525                 me.onCreateRecords(records, operation, success);
43526                 break;
43527             case 'update':
43528                 me.onUpdateRecords(records, operation, success);
43529                 break;
43530             case 'destroy':
43531                 me.onDestroyRecords(records, operation, success);
43532                 break;
43533         }
43534
43535         if (success) {
43536             me.fireEvent('write', me, operation);
43537             me.fireEvent('datachanged', me);
43538         }
43539         
43540         Ext.callback(operation.callback, operation.scope || me, [records, operation, success]);
43541     },
43542
43543
43544     
43545     destroy: function(options) {
43546         var me = this,
43547             operation;
43548             
43549         options = options || {};
43550
43551         Ext.applyIf(options, {
43552             action : 'destroy',
43553             records: me.getRemovedRecords()
43554         });
43555
43556         operation = Ext.create('Ext.data.Operation', options);
43557
43558         return me.proxy.destroy(operation, me.onProxyWrite, me);
43559     },
43560
43561     
43562     onBatchOperationComplete: function(batch, operation) {
43563         return this.onProxyWrite(operation);
43564     },
43565
43566     
43567     onBatchComplete: function(batch, operation) {
43568         var me = this,
43569             operations = batch.operations,
43570             length = operations.length,
43571             i;
43572
43573         me.suspendEvents();
43574
43575         for (i = 0; i < length; i++) {
43576             me.onProxyWrite(operations[i]);
43577         }
43578
43579         me.resumeEvents();
43580
43581         me.fireEvent('datachanged', me);
43582     },
43583
43584     onBatchException: function(batch, operation) {
43585         
43586         
43587         
43588         
43589         
43590     },
43591
43592     
43593     filterNew: function(item) {
43594         
43595         return item.phantom === true && item.isValid();
43596     },
43597
43598     
43599     getNewRecords: function() {
43600         return [];
43601     },
43602
43603     
43604     getUpdatedRecords: function() {
43605         return [];
43606     },
43607
43608     
43609     filterUpdated: function(item) {
43610         
43611         return item.dirty === true && item.phantom !== true && item.isValid();
43612     },
43613
43614     
43615     getRemovedRecords: function() {
43616         return this.removed;
43617     },
43618
43619     filter: function(filters, value) {
43620
43621     },
43622
43623     
43624     decodeFilters: function(filters) {
43625         if (!Ext.isArray(filters)) {
43626             if (filters === undefined) {
43627                 filters = [];
43628             } else {
43629                 filters = [filters];
43630             }
43631         }
43632
43633         var length = filters.length,
43634             Filter = Ext.util.Filter,
43635             config, i;
43636
43637         for (i = 0; i < length; i++) {
43638             config = filters[i];
43639
43640             if (!(config instanceof Filter)) {
43641                 Ext.apply(config, {
43642                     root: 'data'
43643                 });
43644
43645                 
43646                 if (config.fn) {
43647                     config.filterFn = config.fn;
43648                 }
43649
43650                 
43651                 if (typeof config == 'function') {
43652                     config = {
43653                         filterFn: config
43654                     };
43655                 }
43656
43657                 filters[i] = new Filter(config);
43658             }
43659         }
43660
43661         return filters;
43662     },
43663
43664     clearFilter: function(supressEvent) {
43665
43666     },
43667
43668     isFiltered: function() {
43669
43670     },
43671
43672     filterBy: function(fn, scope) {
43673
43674     },
43675     
43676     
43677     sync: function() {
43678         var me        = this,
43679             options   = {},
43680             toCreate  = me.getNewRecords(),
43681             toUpdate  = me.getUpdatedRecords(),
43682             toDestroy = me.getRemovedRecords(),
43683             needsSync = false;
43684
43685         if (toCreate.length > 0) {
43686             options.create = toCreate;
43687             needsSync = true;
43688         }
43689
43690         if (toUpdate.length > 0) {
43691             options.update = toUpdate;
43692             needsSync = true;
43693         }
43694
43695         if (toDestroy.length > 0) {
43696             options.destroy = toDestroy;
43697             needsSync = true;
43698         }
43699
43700         if (needsSync && me.fireEvent('beforesync', options) !== false) {
43701             me.proxy.batch(options, me.getBatchListeners());
43702         }
43703     },
43704
43705
43706     
43707     getBatchListeners: function() {
43708         var me = this,
43709             listeners = {
43710                 scope: me,
43711                 exception: me.onBatchException
43712             };
43713
43714         if (me.batchUpdateMode == 'operation') {
43715             listeners.operationcomplete = me.onBatchOperationComplete;
43716         } else {
43717             listeners.complete = me.onBatchComplete;
43718         }
43719
43720         return listeners;
43721     },
43722
43723     
43724     save: function() {
43725         return this.sync.apply(this, arguments);
43726     },
43727
43728     
43729     load: function(options) {
43730         var me = this,
43731             operation;
43732
43733         options = options || {};
43734
43735         Ext.applyIf(options, {
43736             action : 'read',
43737             filters: me.filters.items,
43738             sorters: me.getSorters()
43739         });
43740         
43741         operation = Ext.create('Ext.data.Operation', options);
43742
43743         if (me.fireEvent('beforeload', me, operation) !== false) {
43744             me.loading = true;
43745             me.proxy.read(operation, me.onProxyLoad, me);
43746         }
43747         
43748         return me;
43749     },
43750
43751     
43752     afterEdit : function(record) {
43753         var me = this;
43754         
43755         if (me.autoSync) {
43756             me.sync();
43757         }
43758         
43759         me.fireEvent('update', me, record, Ext.data.Model.EDIT);
43760     },
43761
43762     
43763     afterReject : function(record) {
43764         this.fireEvent('update', this, record, Ext.data.Model.REJECT);
43765     },
43766
43767     
43768     afterCommit : function(record) {
43769         this.fireEvent('update', this, record, Ext.data.Model.COMMIT);
43770     },
43771
43772     clearData: Ext.emptyFn,
43773
43774     destroyStore: function() {
43775         var me = this;
43776         
43777         if (!me.isDestroyed) {
43778             if (me.storeId) {
43779                 Ext.data.StoreManager.unregister(me);
43780             }
43781             me.clearData();
43782             me.data = null;
43783             me.tree = null;
43784             
43785             me.reader = me.writer = null;
43786             me.clearListeners();
43787             me.isDestroyed = true;
43788
43789             if (me.implicitModel) {
43790                 Ext.destroy(me.model);
43791             }
43792         }
43793     },
43794     
43795     doSort: function(sorterFn) {
43796         var me = this;
43797         if (me.remoteSort) {
43798             
43799             me.load();
43800         } else {
43801             me.data.sortBy(sorterFn);
43802             me.fireEvent('datachanged', me);
43803         }
43804     },
43805
43806     getCount: Ext.emptyFn,
43807
43808     getById: Ext.emptyFn,
43809     
43810     
43811     removeAll: Ext.emptyFn,
43812     
43813     
43814
43815     
43816     isLoading: function() {
43817         return this.loading;
43818      }
43819 });
43820
43821
43822  
43823 Ext.define('Ext.util.Grouper', {
43824
43825     
43826
43827     extend: 'Ext.util.Sorter',
43828
43829     
43830
43831     
43832     getGroupString: function(instance) {
43833         return instance.get(this.property);
43834     }
43835 });
43836
43837 Ext.define('Ext.data.Store', {
43838     extend: 'Ext.data.AbstractStore',
43839
43840     alias: 'store.store',
43841
43842     requires: ['Ext.ModelManager', 'Ext.data.Model', 'Ext.util.Grouper'],
43843     uses: ['Ext.data.proxy.Memory'],
43844
43845     
43846     remoteSort: false,
43847
43848     
43849     remoteFilter: false,
43850     
43851     
43852     remoteGroup : false,
43853
43854     
43855
43856     
43857
43858     
43859
43860     
43861     groupField: undefined,
43862
43863     
43864     groupDir: "ASC",
43865
43866     
43867     pageSize: 25,
43868
43869     
43870     currentPage: 1,
43871
43872     
43873     clearOnPageLoad: true,
43874
43875     
43876     loading: false,
43877
43878     
43879     sortOnFilter: true,
43880     
43881     
43882     buffered: false,
43883     
43884     
43885     purgePageCount: 5,
43886
43887     isStore: true,
43888
43889     
43890     constructor: function(config) {
43891         config = config || {};
43892
43893         var me = this,
43894             groupers = config.groupers || me.groupers,
43895             groupField = config.groupField || me.groupField,
43896             proxy,
43897             data;
43898             
43899         if (config.buffered || me.buffered) {
43900             me.prefetchData = Ext.create('Ext.util.MixedCollection', false, function(record) {
43901                 return record.index;
43902             });
43903             me.pendingRequests = [];
43904             me.pagesRequested = [];
43905             
43906             me.sortOnLoad = false;
43907             me.filterOnLoad = false;
43908         }
43909             
43910         me.addEvents(
43911             
43912             'beforeprefetch',
43913             
43914             'groupchange',
43915             
43916             'prefetch'
43917         );
43918         data = config.data || me.data;
43919
43920         
43921         me.data = Ext.create('Ext.util.MixedCollection', false, function(record) {
43922             return record.internalId;
43923         });
43924
43925         if (data) {
43926             me.inlineData = data;
43927             delete config.data;
43928         }
43929         
43930         if (!groupers && groupField) {
43931             groupers = [{
43932                 property : groupField,
43933                 direction: config.groupDir || me.groupDir
43934             }];
43935         }
43936         delete config.groupers;
43937         
43938         
43939         me.groupers = Ext.create('Ext.util.MixedCollection');
43940         me.groupers.addAll(me.decodeGroupers(groupers));
43941
43942         this.callParent([config]);
43943         
43944         
43945         if (me.groupers.items.length) {
43946             me.sort(me.groupers.items, 'prepend', false);
43947         }
43948
43949         proxy = me.proxy;
43950         data = me.inlineData;
43951
43952         if (data) {
43953             if (proxy instanceof Ext.data.proxy.Memory) {
43954                 proxy.data = data;
43955                 me.read();
43956             } else {
43957                 me.add.apply(me, data);
43958             }
43959
43960             me.sort();
43961             delete me.inlineData;
43962         } else if (me.autoLoad) {
43963             Ext.defer(me.load, 10, me, [typeof me.autoLoad === 'object' ? me.autoLoad: undefined]);
43964             
43965             
43966         }
43967     },
43968     
43969     onBeforeSort: function() {
43970         this.sort(this.groupers.items, 'prepend', false);
43971     },
43972     
43973     
43974     decodeGroupers: function(groupers) {
43975         if (!Ext.isArray(groupers)) {
43976             if (groupers === undefined) {
43977                 groupers = [];
43978             } else {
43979                 groupers = [groupers];
43980             }
43981         }
43982
43983         var length  = groupers.length,
43984             Grouper = Ext.util.Grouper,
43985             config, i;
43986
43987         for (i = 0; i < length; i++) {
43988             config = groupers[i];
43989
43990             if (!(config instanceof Grouper)) {
43991                 if (Ext.isString(config)) {
43992                     config = {
43993                         property: config
43994                     };
43995                 }
43996                 
43997                 Ext.applyIf(config, {
43998                     root     : 'data',
43999                     direction: "ASC"
44000                 });
44001
44002                 
44003                 if (config.fn) {
44004                     config.sorterFn = config.fn;
44005                 }
44006
44007                 
44008                 if (typeof config == 'function') {
44009                     config = {
44010                         sorterFn: config
44011                     };
44012                 }
44013
44014                 groupers[i] = new Grouper(config);
44015             }
44016         }
44017
44018         return groupers;
44019     },
44020     
44021     
44022     group: function(groupers, direction) {
44023         var me = this,
44024             grouper,
44025             newGroupers;
44026             
44027         if (Ext.isArray(groupers)) {
44028             newGroupers = groupers;
44029         } else if (Ext.isObject(groupers)) {
44030             newGroupers = [groupers];
44031         } else if (Ext.isString(groupers)) {
44032             grouper = me.groupers.get(groupers);
44033
44034             if (!grouper) {
44035                 grouper = {
44036                     property : groupers,
44037                     direction: direction
44038                 };
44039                 newGroupers = [grouper];
44040             } else if (direction === undefined) {
44041                 grouper.toggle();
44042             } else {
44043                 grouper.setDirection(direction);
44044             }
44045         }
44046         
44047         if (newGroupers && newGroupers.length) {
44048             newGroupers = me.decodeGroupers(newGroupers);
44049             me.groupers.clear();
44050             me.groupers.addAll(newGroupers);
44051         }
44052         
44053         if (me.remoteGroup) {
44054             me.load({
44055                 scope: me,
44056                 callback: me.fireGroupChange
44057             });
44058         } else {
44059             me.sort();
44060             me.fireEvent('groupchange', me, me.groupers);
44061         }
44062     },
44063     
44064     
44065     clearGrouping: function(){
44066         var me = this;
44067         
44068         me.groupers.each(function(grouper){
44069             me.sorters.remove(grouper);
44070         });
44071         me.groupers.clear();
44072         if (me.remoteGroup) {
44073             me.load({
44074                 scope: me,
44075                 callback: me.fireGroupChange
44076             });
44077         } else {
44078             me.sort();
44079             me.fireEvent('groupchange', me, me.groupers);
44080         }
44081     },
44082     
44083     
44084     isGrouped: function() {
44085         return this.groupers.getCount() > 0;    
44086     },
44087     
44088     
44089     fireGroupChange: function(){
44090         this.fireEvent('groupchange', this, this.groupers);    
44091     },
44092
44093     
44094     getGroups: function(requestGroupString) {
44095         var records = this.data.items,
44096             length = records.length,
44097             groups = [],
44098             pointers = {},
44099             record,
44100             groupStr,
44101             group,
44102             i;
44103
44104         for (i = 0; i < length; i++) {
44105             record = records[i];
44106             groupStr = this.getGroupString(record);
44107             group = pointers[groupStr];
44108
44109             if (group === undefined) {
44110                 group = {
44111                     name: groupStr,
44112                     children: []
44113                 };
44114
44115                 groups.push(group);
44116                 pointers[groupStr] = group;
44117             }
44118
44119             group.children.push(record);
44120         }
44121
44122         return requestGroupString ? pointers[requestGroupString] : groups;
44123     },
44124
44125     
44126     getGroupsForGrouper: function(records, grouper) {
44127         var length = records.length,
44128             groups = [],
44129             oldValue,
44130             newValue,
44131             record,
44132             group,
44133             i;
44134
44135         for (i = 0; i < length; i++) {
44136             record = records[i];
44137             newValue = grouper.getGroupString(record);
44138
44139             if (newValue !== oldValue) {
44140                 group = {
44141                     name: newValue,
44142                     grouper: grouper,
44143                     records: []
44144                 };
44145                 groups.push(group);
44146             }
44147
44148             group.records.push(record);
44149
44150             oldValue = newValue;
44151         }
44152
44153         return groups;
44154     },
44155
44156     
44157     getGroupsForGrouperIndex: function(records, grouperIndex) {
44158         var me = this,
44159             groupers = me.groupers,
44160             grouper = groupers.getAt(grouperIndex),
44161             groups = me.getGroupsForGrouper(records, grouper),
44162             length = groups.length,
44163             i;
44164
44165         if (grouperIndex + 1 < groupers.length) {
44166             for (i = 0; i < length; i++) {
44167                 groups[i].children = me.getGroupsForGrouperIndex(groups[i].records, grouperIndex + 1);
44168             }
44169         }
44170
44171         for (i = 0; i < length; i++) {
44172             groups[i].depth = grouperIndex;
44173         }
44174
44175         return groups;
44176     },
44177
44178     
44179     getGroupData: function(sort) {
44180         var me = this;
44181         if (sort !== false) {
44182             me.sort();
44183         }
44184
44185         return me.getGroupsForGrouperIndex(me.data.items, 0);
44186     },
44187
44188     
44189     getGroupString: function(instance) {
44190         var group = this.groupers.first();
44191         if (group) {
44192             return instance.get(group.property);
44193         }
44194         return '';
44195     },
44196     
44197     insert: function(index, records) {
44198         var me = this,
44199             sync = false,
44200             i,
44201             record,
44202             len;
44203
44204         records = [].concat(records);
44205         for (i = 0, len = records.length; i < len; i++) {
44206             record = me.createModel(records[i]);
44207             record.set(me.modelDefaults);
44208             
44209             records[i] = record;
44210             
44211             me.data.insert(index + i, record);
44212             record.join(me);
44213
44214             sync = sync || record.phantom === true;
44215         }
44216
44217         if (me.snapshot) {
44218             me.snapshot.addAll(records);
44219         }
44220
44221         me.fireEvent('add', me, records, index);
44222         me.fireEvent('datachanged', me);
44223         if (me.autoSync && sync) {
44224             me.sync();
44225         }
44226     },
44227
44228     
44229     add: function(records) {
44230         
44231         if (!Ext.isArray(records)) {
44232             records = Array.prototype.slice.apply(arguments);
44233         }
44234
44235         var me = this,
44236             i = 0,
44237             length = records.length,
44238             record;
44239
44240         for (; i < length; i++) {
44241             record = me.createModel(records[i]);
44242             
44243             records[i] = record;
44244         }
44245
44246         me.insert(me.data.length, records);
44247
44248         return records;
44249     },
44250
44251     
44252     createModel: function(record) {
44253         if (!record.isModel) {
44254             record = Ext.ModelManager.create(record, this.model);
44255         }
44256
44257         return record;
44258     },
44259
44260     
44261     each: function(fn, scope) {
44262         this.data.each(fn, scope);
44263     },
44264
44265     
44266     remove: function(records,  isMove) {
44267         if (!Ext.isArray(records)) {
44268             records = [records];
44269         }
44270
44271         
44272         isMove = isMove === true;
44273         var me = this,
44274             sync = false,
44275             i = 0,
44276             length = records.length,
44277             isPhantom,
44278             index,
44279             record;
44280
44281         for (; i < length; i++) {
44282             record = records[i];
44283             index = me.data.indexOf(record);
44284             
44285             if (me.snapshot) {
44286                 me.snapshot.remove(record);
44287             }
44288             
44289             if (index > -1) {
44290                 isPhantom = record.phantom === true;
44291                 if (!isMove && !isPhantom) {
44292                     
44293                     me.removed.push(record);
44294                 }
44295
44296                 record.unjoin(me);
44297                 me.data.remove(record);
44298                 sync = sync || !isPhantom;
44299
44300                 me.fireEvent('remove', me, record, index);
44301             }
44302         }
44303
44304         me.fireEvent('datachanged', me);
44305         if (!isMove && me.autoSync && sync) {
44306             me.sync();
44307         }
44308     },
44309
44310     
44311     removeAt: function(index) {
44312         var record = this.getAt(index);
44313
44314         if (record) {
44315             this.remove(record);
44316         }
44317     },
44318
44319     
44320     load: function(options) {
44321         var me = this;
44322             
44323         options = options || {};
44324
44325         if (Ext.isFunction(options)) {
44326             options = {
44327                 callback: options
44328             };
44329         }
44330
44331         Ext.applyIf(options, {
44332             groupers: me.groupers.items,
44333             page: me.currentPage,
44334             start: (me.currentPage - 1) * me.pageSize,
44335             limit: me.pageSize,
44336             addRecords: false
44337         });      
44338
44339         return me.callParent([options]);
44340     },
44341
44342     
44343     onProxyLoad: function(operation) {
44344         var me = this,
44345             resultSet = operation.getResultSet(),
44346             records = operation.getRecords(),
44347             successful = operation.wasSuccessful();
44348
44349         if (resultSet) {
44350             me.totalCount = resultSet.total;
44351         }
44352
44353         if (successful) {
44354             me.loadRecords(records, operation);
44355         }
44356
44357         me.loading = false;
44358         me.fireEvent('load', me, records, successful);
44359
44360         
44361         
44362         me.fireEvent('read', me, records, operation.wasSuccessful());
44363
44364         
44365         Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
44366     },
44367     
44368     
44369     onCreateRecords: function(records, operation, success) {
44370         if (success) {
44371             var i = 0,
44372                 data = this.data,
44373                 snapshot = this.snapshot,
44374                 length = records.length,
44375                 originalRecords = operation.records,
44376                 record,
44377                 original,
44378                 index;
44379
44380             
44381             for (; i < length; ++i) {
44382                 record = records[i];
44383                 original = originalRecords[i];
44384                 if (original) {
44385                     index = data.indexOf(original);
44386                     if (index > -1) {
44387                         data.removeAt(index);
44388                         data.insert(index, record);
44389                     }
44390                     if (snapshot) {
44391                         index = snapshot.indexOf(original);
44392                         if (index > -1) {
44393                             snapshot.removeAt(index);
44394                             snapshot.insert(index, record);
44395                         }
44396                     }
44397                     record.phantom = false;
44398                     record.join(this);
44399                 }
44400             }
44401         }
44402     },
44403
44404     
44405     onUpdateRecords: function(records, operation, success){
44406         if (success) {
44407             var i = 0,
44408                 length = records.length,
44409                 data = this.data,
44410                 snapshot = this.snapshot,
44411                 record;
44412
44413             for (; i < length; ++i) {
44414                 record = records[i];
44415                 data.replace(record);
44416                 if (snapshot) {
44417                     snapshot.replace(record);
44418                 }
44419                 record.join(this);
44420             }
44421         }
44422     },
44423
44424     
44425     onDestroyRecords: function(records, operation, success){
44426         if (success) {
44427             var me = this,
44428                 i = 0,
44429                 length = records.length,
44430                 data = me.data,
44431                 snapshot = me.snapshot,
44432                 record;
44433
44434             for (; i < length; ++i) {
44435                 record = records[i];
44436                 record.unjoin(me);
44437                 data.remove(record);
44438                 if (snapshot) {
44439                     snapshot.remove(record);
44440                 }
44441             }
44442             me.removed = [];
44443         }
44444     },
44445
44446     
44447     getNewRecords: function() {
44448         return this.data.filterBy(this.filterNew).items;
44449     },
44450
44451     
44452     getUpdatedRecords: function() {
44453         return this.data.filterBy(this.filterUpdated).items;
44454     },
44455
44456     
44457     filter: function(filters, value) {
44458         if (Ext.isString(filters)) {
44459             filters = {
44460                 property: filters,
44461                 value: value
44462             };
44463         }
44464
44465         var me = this,
44466             decoded = me.decodeFilters(filters),
44467             i = 0,
44468             doLocalSort = me.sortOnFilter && !me.remoteSort,
44469             length = decoded.length;
44470
44471         for (; i < length; i++) {
44472             me.filters.replace(decoded[i]);
44473         }
44474
44475         if (me.remoteFilter) {
44476             
44477             me.load();
44478         } else {
44479             
44480             if (me.filters.getCount()) {
44481                 me.snapshot = me.snapshot || me.data.clone();
44482                 me.data = me.data.filter(me.filters.items);
44483
44484                 if (doLocalSort) {
44485                     me.sort();
44486                 }
44487                 
44488                 if (!doLocalSort || me.sorters.length < 1) {
44489                     me.fireEvent('datachanged', me);
44490                 }
44491             }
44492         }
44493     },
44494
44495     
44496     clearFilter: function(suppressEvent) {
44497         var me = this;
44498
44499         me.filters.clear();
44500
44501         if (me.remoteFilter) {
44502             me.load();
44503         } else if (me.isFiltered()) {
44504             me.data = me.snapshot.clone();
44505             delete me.snapshot;
44506
44507             if (suppressEvent !== true) {
44508                 me.fireEvent('datachanged', me);
44509             }
44510         }
44511     },
44512
44513     
44514     isFiltered: function() {
44515         var snapshot = this.snapshot;
44516         return !! snapshot && snapshot !== this.data;
44517     },
44518
44519     
44520     filterBy: function(fn, scope) {
44521         var me = this;
44522
44523         me.snapshot = me.snapshot || me.data.clone();
44524         me.data = me.queryBy(fn, scope || me);
44525         me.fireEvent('datachanged', me);
44526     },
44527
44528     
44529     queryBy: function(fn, scope) {
44530         var me = this,
44531         data = me.snapshot || me.data;
44532         return data.filterBy(fn, scope || me);
44533     },
44534
44535     
44536     loadData: function(data, append) {
44537         var model = this.model,
44538             length = data.length,
44539             i,
44540             record;
44541
44542         
44543         for (i = 0; i < length; i++) {
44544             record = data[i];
44545
44546             if (! (record instanceof Ext.data.Model)) {
44547                 data[i] = Ext.ModelManager.create(record, model);
44548             }
44549         }
44550
44551         this.loadRecords(data, {addRecords: append});
44552     },
44553
44554     
44555     loadRecords: function(records, options) {
44556         var me     = this,
44557             i      = 0,
44558             length = records.length;
44559
44560         options = options || {};
44561
44562
44563         if (!options.addRecords) {
44564             delete me.snapshot;
44565             me.data.clear();
44566         }
44567
44568         me.data.addAll(records);
44569
44570         
44571         for (; i < length; i++) {
44572             if (options.start !== undefined) {
44573                 records[i].index = options.start + i;
44574
44575             }
44576             records[i].join(me);
44577         }
44578
44579         
44580         me.suspendEvents();
44581
44582         if (me.filterOnLoad && !me.remoteFilter) {
44583             me.filter();
44584         }
44585
44586         if (me.sortOnLoad && !me.remoteSort) {
44587             me.sort();
44588         }
44589
44590         me.resumeEvents();
44591         me.fireEvent('datachanged', me, records);
44592     },
44593
44594     
44595     
44596     loadPage: function(page) {
44597         var me = this;
44598
44599         me.currentPage = page;
44600
44601         me.read({
44602             page: page,
44603             start: (page - 1) * me.pageSize,
44604             limit: me.pageSize,
44605             addRecords: !me.clearOnPageLoad
44606         });
44607     },
44608
44609     
44610     nextPage: function() {
44611         this.loadPage(this.currentPage + 1);
44612     },
44613
44614     
44615     previousPage: function() {
44616         this.loadPage(this.currentPage - 1);
44617     },
44618
44619     
44620     clearData: function() {
44621         this.data.each(function(record) {
44622             record.unjoin();
44623         });
44624
44625         this.data.clear();
44626     },
44627     
44628     
44629     
44630     prefetch: function(options) {
44631         var me = this,
44632             operation,
44633             requestId = me.getRequestId();
44634
44635         options = options || {};
44636
44637         Ext.applyIf(options, {
44638             action : 'read',
44639             filters: me.filters.items,
44640             sorters: me.sorters.items,
44641             requestId: requestId
44642         });
44643         me.pendingRequests.push(requestId);
44644
44645         operation = Ext.create('Ext.data.Operation', options);
44646
44647         
44648         
44649         
44650         
44651         if (me.fireEvent('beforeprefetch', me, operation) !== false) {
44652             me.loading = true;
44653             me.proxy.read(operation, me.onProxyPrefetch, me);
44654         }
44655         
44656         return me;
44657     },
44658     
44659     
44660     prefetchPage: function(page, options) {
44661         var me = this,
44662             pageSize = me.pageSize,
44663             start = (page - 1) * me.pageSize,
44664             end = start + pageSize;
44665         
44666         
44667         if (Ext.Array.indexOf(me.pagesRequested, page) === -1 && !me.rangeSatisfied(start, end)) {
44668             options = options || {};
44669             me.pagesRequested.push(page);
44670             Ext.applyIf(options, {
44671                 page : page,
44672                 start: start,
44673                 limit: pageSize,
44674                 callback: me.onWaitForGuarantee,
44675                 scope: me
44676             });
44677             
44678             me.prefetch(options);
44679         }
44680         
44681     },
44682     
44683     
44684     getRequestId: function() {
44685         this.requestSeed = this.requestSeed || 1;
44686         return this.requestSeed++;
44687     },
44688     
44689     
44690     onProxyPrefetch: function(operation) {
44691         var me         = this,
44692             resultSet  = operation.getResultSet(),
44693             records    = operation.getRecords(),
44694             
44695             successful = operation.wasSuccessful();
44696         
44697         if (resultSet) {
44698             me.totalCount = resultSet.total;
44699             me.fireEvent('totalcountchange', me.totalCount);
44700         }
44701         
44702         if (successful) {
44703             me.cacheRecords(records, operation);
44704         }
44705         Ext.Array.remove(me.pendingRequests, operation.requestId);
44706         if (operation.page) {
44707             Ext.Array.remove(me.pagesRequested, operation.page);
44708         }
44709         
44710         me.loading = false;
44711         me.fireEvent('prefetch', me, records, successful, operation);
44712         
44713         
44714         if (operation.blocking) {
44715             me.fireEvent('load', me, records, successful);
44716         }
44717
44718         
44719         Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
44720     },
44721     
44722     
44723     cacheRecords: function(records, operation) {
44724         var me     = this,
44725             i      = 0,
44726             length = records.length,
44727             start  = operation ? operation.start : 0;
44728         
44729         if (!Ext.isDefined(me.totalCount)) {
44730             me.totalCount = records.length;
44731             me.fireEvent('totalcountchange', me.totalCount);
44732         }
44733         
44734         for (; i < length; i++) {
44735             
44736             records[i].index = start + i;
44737         }
44738         
44739         me.prefetchData.addAll(records);
44740         if (me.purgePageCount) {
44741             me.purgeRecords();
44742         }
44743         
44744     },
44745     
44746     
44747     
44748     purgeRecords: function() {
44749         var me = this,
44750             prefetchCount = me.prefetchData.getCount(),
44751             purgeCount = me.purgePageCount * me.pageSize,
44752             numRecordsToPurge = prefetchCount - purgeCount - 1,
44753             i = 0;
44754
44755         for (; i <= numRecordsToPurge; i++) {
44756             me.prefetchData.removeAt(0);
44757         }
44758     },
44759     
44760     
44761     rangeSatisfied: function(start, end) {
44762         var me = this,
44763             i = start,
44764             satisfied = true;
44765
44766         for (; i < end; i++) {
44767             if (!me.prefetchData.getByKey(i)) {
44768                 satisfied = false;
44769                 if (end - i > me.pageSize) {
44770                     Ext.Error.raise("A single page prefetch could never satisfy this request.");
44771                 }
44772                 break;
44773             }
44774         }
44775         return satisfied;
44776     },
44777     
44778     
44779     getPageFromRecordIndex: function(index) {
44780         return Math.floor(index / this.pageSize) + 1;
44781     },
44782     
44783     
44784     onGuaranteedRange: function() {
44785         var me = this,
44786             totalCount = me.getTotalCount(),
44787             start = me.requestStart,
44788             end = ((totalCount - 1) < me.requestEnd) ? totalCount - 1 : me.requestEnd,
44789             range = [],
44790             record,
44791             i = start;
44792             
44793         if (start > end) {
44794             Ext.Error.raise("Start (" + start + ") was greater than end (" + end + ")");
44795         }
44796         
44797         if (start !== me.guaranteedStart && end !== me.guaranteedEnd) {
44798             me.guaranteedStart = start;
44799             me.guaranteedEnd = end;
44800             
44801             for (; i <= end; i++) {
44802                 record = me.prefetchData.getByKey(i);
44803                 if (!record) {
44804                     Ext.Error.raise("Record was not found and store said it was guaranteed");
44805                 }
44806                 range.push(record);
44807             }
44808             me.fireEvent('guaranteedrange', range, start, end);
44809             if (me.cb) {
44810                 me.cb.call(me.scope || me, range);
44811             }
44812         }
44813         
44814         me.unmask();
44815     },
44816     
44817     
44818     mask: function() {
44819         this.masked = true;
44820         this.fireEvent('beforeload');
44821     },
44822     
44823     
44824     unmask: function() {
44825         if (this.masked) {
44826             this.fireEvent('load');
44827         }
44828     },
44829     
44830     
44831     hasPendingRequests: function() {
44832         return this.pendingRequests.length;
44833     },
44834     
44835     
44836     
44837     onWaitForGuarantee: function() {
44838         if (!this.hasPendingRequests()) {
44839             this.onGuaranteedRange();
44840         }
44841     },
44842     
44843     
44844     guaranteeRange: function(start, end, cb, scope) {
44845         if (start && end) {
44846             if (end - start > this.pageSize) {
44847                 Ext.Error.raise({
44848                     start: start,
44849                     end: end,
44850                     pageSize: this.pageSize,
44851                     msg: "Requested a bigger range than the specified pageSize"
44852                 });
44853             }
44854         }
44855         
44856         end = (end > this.totalCount) ? this.totalCount - 1 : end;
44857         
44858         var me = this,
44859             i = start,
44860             prefetchData = me.prefetchData,
44861             range = [],
44862             startLoaded = !!prefetchData.getByKey(start),
44863             endLoaded = !!prefetchData.getByKey(end),
44864             startPage = me.getPageFromRecordIndex(start),
44865             endPage = me.getPageFromRecordIndex(end);
44866             
44867         me.cb = cb;
44868         me.scope = scope;
44869
44870         me.requestStart = start;
44871         me.requestEnd = end;
44872         
44873         if (!startLoaded || !endLoaded) {
44874             
44875             if (startPage === endPage) {
44876                 me.mask();
44877                 me.prefetchPage(startPage, {
44878                     
44879                     callback: me.onWaitForGuarantee,
44880                     scope: me
44881                 });
44882             
44883             } else {
44884                 me.mask();
44885                 me.prefetchPage(startPage, {
44886                     
44887                     callback: me.onWaitForGuarantee,
44888                     scope: me
44889                 });
44890                 me.prefetchPage(endPage, {
44891                     
44892                     callback: me.onWaitForGuarantee,
44893                     scope: me
44894                 });
44895             }
44896         
44897         } else {
44898             me.onGuaranteedRange();
44899         }
44900     },
44901     
44902     
44903     
44904     sort: function() {
44905         var me = this,
44906             prefetchData = me.prefetchData,
44907             sorters,
44908             start,
44909             end,
44910             range;
44911             
44912         if (me.buffered) {
44913             if (me.remoteSort) {
44914                 prefetchData.clear();
44915                 me.callParent(arguments);
44916             } else {
44917                 sorters = me.getSorters();
44918                 start = me.guaranteedStart;
44919                 end = me.guaranteedEnd;
44920                 
44921                 if (sorters.length) {
44922                     prefetchData.sort(sorters);
44923                     range = prefetchData.getRange();
44924                     prefetchData.clear();
44925                     me.cacheRecords(range);
44926                     delete me.guaranteedStart;
44927                     delete me.guaranteedEnd;
44928                     me.guaranteeRange(start, end);
44929                 }
44930                 me.callParent(arguments);
44931             }
44932         } else {
44933             me.callParent(arguments);
44934         }
44935     },
44936
44937     
44938     
44939     
44940     doSort: function(sorterFn) {
44941         var me = this;
44942         if (me.remoteSort) {
44943             
44944             me.load();
44945         } else {
44946             me.data.sortBy(sorterFn);
44947             if (!me.buffered) {
44948                 var range = me.getRange(),
44949                     ln = range.length,
44950                     i  = 0;
44951                 for (; i < ln; i++) {
44952                     range[i].index = i;
44953                 }
44954             }
44955             me.fireEvent('datachanged', me);
44956         }
44957     },
44958     
44959     
44960     find: function(property, value, start, anyMatch, caseSensitive, exactMatch) {
44961         var fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch);
44962         return fn ? this.data.findIndexBy(fn, null, start) : -1;
44963     },
44964
44965     
44966     findRecord: function() {
44967         var me = this,
44968             index = me.find.apply(me, arguments);
44969         return index !== -1 ? me.getAt(index) : null;
44970     },
44971
44972     
44973     createFilterFn: function(property, value, anyMatch, caseSensitive, exactMatch) {
44974         if (Ext.isEmpty(value)) {
44975             return false;
44976         }
44977         value = this.data.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
44978         return function(r) {
44979             return value.test(r.data[property]);
44980         };
44981     },
44982
44983     
44984     findExact: function(property, value, start) {
44985         return this.data.findIndexBy(function(rec) {
44986             return rec.get(property) === value;
44987         },
44988         this, start);
44989     },
44990
44991     
44992     findBy: function(fn, scope, start) {
44993         return this.data.findIndexBy(fn, scope, start);
44994     },
44995
44996     
44997     collect: function(dataIndex, allowNull, bypassFilter) {
44998         var me = this,
44999             data = (bypassFilter === true && me.snapshot) ? me.snapshot: me.data;
45000
45001         return data.collect(dataIndex, 'data', allowNull);
45002     },
45003
45004     
45005     getCount: function() {
45006         return this.data.length || 0;
45007     },
45008
45009     
45010     getTotalCount: function() {
45011         return this.totalCount;
45012     },
45013
45014     
45015     getAt: function(index) {
45016         return this.data.getAt(index);
45017     },
45018
45019     
45020     getRange: function(start, end) {
45021         return this.data.getRange(start, end);
45022     },
45023
45024     
45025     getById: function(id) {
45026         return (this.snapshot || this.data).findBy(function(record) {
45027             return record.getId() === id;
45028         });
45029     },
45030
45031     
45032     indexOf: function(record) {
45033         return this.data.indexOf(record);
45034     },
45035
45036
45037     
45038     indexOfTotal: function(record) {
45039         return record.index || this.indexOf(record);
45040     },
45041
45042     
45043     indexOfId: function(id) {
45044         return this.data.indexOfKey(id);
45045     },
45046         
45047     
45048     removeAll: function(silent) {
45049         var me = this;
45050
45051         me.clearData();
45052         if (me.snapshot) {
45053             me.snapshot.clear();
45054         }
45055         if (silent !== true) {
45056             me.fireEvent('clear', me);
45057         }
45058     },
45059
45060     
45061
45062     
45063     first: function(grouped) {
45064         var me = this;
45065
45066         if (grouped && me.isGrouped()) {
45067             return me.aggregate(function(records) {
45068                 return records.length ? records[0] : undefined;
45069             }, me, true);
45070         } else {
45071             return me.data.first();
45072         }
45073     },
45074
45075     
45076     last: function(grouped) {
45077         var me = this;
45078
45079         if (grouped && me.isGrouped()) {
45080             return me.aggregate(function(records) {
45081                 var len = records.length;
45082                 return len ? records[len - 1] : undefined;
45083             }, me, true);
45084         } else {
45085             return me.data.last();
45086         }
45087     },
45088
45089     
45090     sum: function(field, grouped) {
45091         var me = this;
45092
45093         if (grouped && me.isGrouped()) {
45094             return me.aggregate(me.getSum, me, true, [field]);
45095         } else {
45096             return me.getSum(me.data.items, field);
45097         }
45098     },
45099
45100     
45101     getSum: function(records, field) {
45102         var total = 0,
45103             i = 0,
45104             len = records.length;
45105
45106         for (; i < len; ++i) {
45107             total += records[i].get(field);
45108         }
45109
45110         return total;
45111     },
45112
45113     
45114     count: function(grouped) {
45115         var me = this;
45116
45117         if (grouped && me.isGrouped()) {
45118             return me.aggregate(function(records) {
45119                 return records.length;
45120             }, me, true);
45121         } else {
45122             return me.getCount();
45123         }
45124     },
45125
45126     
45127     min: function(field, grouped) {
45128         var me = this;
45129
45130         if (grouped && me.isGrouped()) {
45131             return me.aggregate(me.getMin, me, true, [field]);
45132         } else {
45133             return me.getMin(me.data.items, field);
45134         }
45135     },
45136
45137     
45138     getMin: function(records, field){
45139         var i = 1,
45140             len = records.length,
45141             value, min;
45142
45143         if (len > 0) {
45144             min = records[0].get(field);
45145         }
45146
45147         for (; i < len; ++i) {
45148             value = records[i].get(field);
45149             if (value < min) {
45150                 min = value;
45151             }
45152         }
45153         return min;
45154     },
45155
45156     
45157     max: function(field, grouped) {
45158         var me = this;
45159
45160         if (grouped && me.isGrouped()) {
45161             return me.aggregate(me.getMax, me, true, [field]);
45162         } else {
45163             return me.getMax(me.data.items, field);
45164         }
45165     },
45166
45167     
45168     getMax: function(records, field) {
45169         var i = 1,
45170             len = records.length,
45171             value,
45172             max;
45173
45174         if (len > 0) {
45175             max = records[0].get(field);
45176         }
45177
45178         for (; i < len; ++i) {
45179             value = records[i].get(field);
45180             if (value > max) {
45181                 max = value;
45182             }
45183         }
45184         return max;
45185     },
45186
45187     
45188     average: function(field, grouped) {
45189         var me = this;
45190         if (grouped && me.isGrouped()) {
45191             return me.aggregate(me.getAverage, me, true, [field]);
45192         } else {
45193             return me.getAverage(me.data.items, field);
45194         }
45195     },
45196
45197     
45198     getAverage: function(records, field) {
45199         var i = 0,
45200             len = records.length,
45201             sum = 0;
45202
45203         if (records.length > 0) {
45204             for (; i < len; ++i) {
45205                 sum += records[i].get(field);
45206             }
45207             return sum / len;
45208         }
45209         return 0;
45210     },
45211
45212     
45213     aggregate: function(fn, scope, grouped, args) {
45214         args = args || [];
45215         if (grouped && this.isGrouped()) {
45216             var groups = this.getGroups(),
45217                 i = 0,
45218                 len = groups.length,
45219                 out = {},
45220                 group;
45221
45222             for (; i < len; ++i) {
45223                 group = groups[i];
45224                 out[group.name] = fn.apply(scope || this, [group.children].concat(args));
45225             }
45226             return out;
45227         } else {
45228             return fn.apply(scope || this, [this.data.items].concat(args));
45229         }
45230     }
45231 });
45232
45233
45234 Ext.define('Ext.data.JsonStore',  {
45235     extend: 'Ext.data.Store',
45236     alias: 'store.json',
45237
45238     
45239     constructor: function(config) {
45240         config = config || {};
45241
45242         Ext.applyIf(config, {
45243             proxy: {
45244                 type  : 'ajax',
45245                 reader: 'json',
45246                 writer: 'json'
45247             }
45248         });
45249
45250         this.callParent([config]);
45251     }
45252 });
45253
45254
45255 Ext.define('Ext.chart.axis.Time', {
45256
45257     
45258
45259     extend: 'Ext.chart.axis.Category',
45260
45261     alternateClassName: 'Ext.chart.TimeAxis',
45262
45263     alias: 'axis.time',
45264
45265     requires: ['Ext.data.Store', 'Ext.data.JsonStore'],
45266
45267     
45268
45269      
45270     calculateByLabelSize: true,
45271     
45272      
45273     dateFormat: false,
45274     
45275      
45276     groupBy: 'year,month,day',
45277     
45278     
45279     aggregateOp: 'sum',
45280     
45281     
45282     fromDate: false,
45283     
45284     
45285     toDate: false,
45286     
45287     
45288     step: [Ext.Date.DAY, 1],
45289     
45290     
45291     constrain: false,
45292     
45293     
45294     dateMethods: {
45295         'year': function(date) {
45296             return date.getFullYear();
45297         },
45298         'month': function(date) {
45299             return date.getMonth() + 1;
45300         },
45301         'day': function(date) {
45302             return date.getDate();
45303         },
45304         'hour': function(date) {
45305             return date.getHours();
45306         },
45307         'minute': function(date) {
45308             return date.getMinutes();
45309         },
45310         'second': function(date) {
45311             return date.getSeconds();
45312         },
45313         'millisecond': function(date) {
45314             return date.getMilliseconds();
45315         }
45316     },
45317     
45318     
45319     aggregateFn: (function() {
45320         var etype = (function() {
45321             var rgxp = /^\[object\s(.*)\]$/,
45322                 toString = Object.prototype.toString;
45323             return function(e) {
45324                 return toString.call(e).match(rgxp)[1];
45325             };
45326         })();
45327         return {
45328             'sum': function(list) {
45329                 var i = 0, l = list.length, acum = 0;
45330                 if (!list.length || etype(list[0]) != 'Number') {
45331                     return list[0];
45332                 }
45333                 for (; i < l; i++) {
45334                     acum += list[i];
45335                 }
45336                 return acum;
45337             },
45338             'max': function(list) {
45339                 if (!list.length || etype(list[0]) != 'Number') {
45340                     return list[0];
45341                 }
45342                 return Math.max.apply(Math, list);
45343             },
45344             'min': function(list) {
45345                 if (!list.length || etype(list[0]) != 'Number') {
45346                     return list[0];
45347                 }
45348                 return Math.min.apply(Math, list);
45349             },
45350             'avg': function(list) {
45351                 var i = 0, l = list.length, acum = 0;
45352                 if (!list.length || etype(list[0]) != 'Number') {
45353                     return list[0];
45354                 }
45355                 for (; i < l; i++) {
45356                     acum += list[i];
45357                 }
45358                 return acum / l;
45359             }
45360         };
45361     })(),
45362     
45363     
45364     constrainDates: function() {
45365         var fromDate = Ext.Date.clone(this.fromDate),
45366             toDate = Ext.Date.clone(this.toDate),
45367             step = this.step,
45368             field = this.fields,
45369             store = this.chart.store,
45370             record, recObj, fieldNames = [],
45371             newStore = Ext.create('Ext.data.Store', {
45372                 model: store.model
45373             });
45374         
45375         var getRecordByDate = (function() {
45376             var index = 0, l = store.getCount();
45377             return function(date) {
45378                 var rec, recDate;
45379                 for (; index < l; index++) {
45380                     rec = store.getAt(index);
45381                     recDate = rec.get(field);
45382                     if (+recDate > +date) {
45383                         return false;
45384                     } else if (+recDate == +date) {
45385                         return rec;
45386                     }
45387                 }
45388                 return false;
45389             };
45390         })();
45391         
45392         if (!this.constrain) {
45393             this.chart.filteredStore = this.chart.store;
45394             return;
45395         }
45396
45397         while(+fromDate <= +toDate) {
45398             record = getRecordByDate(fromDate);
45399             recObj = {};
45400             if (record) {
45401                 newStore.add(record.data);
45402             } else {
45403                 newStore.model.prototype.fields.each(function(f) {
45404                     recObj[f.name] = false;
45405                 });
45406                 recObj.date = fromDate;
45407                 newStore.add(recObj);
45408             }
45409             fromDate = Ext.Date.add(fromDate, step[0], step[1]);
45410         }
45411          
45412         this.chart.filteredStore = newStore;
45413     },
45414     
45415     
45416     aggregate: function() {
45417         var aggStore = {}, 
45418             aggKeys = [], key, value,
45419             op = this.aggregateOp,
45420             field = this.fields, i,
45421             fields = this.groupBy.split(','),
45422             curField,
45423             recFields = [],
45424             recFieldsLen = 0,
45425             obj,
45426             dates = [],
45427             json = [],
45428             l = fields.length,
45429             dateMethods = this.dateMethods,
45430             aggregateFn = this.aggregateFn,
45431             store = this.chart.filteredStore || this.chart.store;
45432         
45433         store.each(function(rec) {
45434             
45435             if (!recFields.length) {
45436                 rec.fields.each(function(f) {
45437                     recFields.push(f.name);
45438                 });
45439                 recFieldsLen = recFields.length;
45440             }
45441             
45442             value = rec.get(field);
45443             
45444             for (i = 0; i < l; i++) {
45445                 if (i == 0) {
45446                     key = String(dateMethods[fields[i]](value));
45447                 } else {
45448                     key += '||' + dateMethods[fields[i]](value);
45449                 }
45450             }
45451             
45452             if (key in aggStore) {
45453                 obj = aggStore[key];
45454             } else {
45455                 obj = aggStore[key] = {};
45456                 aggKeys.push(key);
45457                 dates.push(value);
45458             }
45459             
45460             for (i = 0; i < recFieldsLen; i++) {
45461                 curField = recFields[i];
45462                 if (!obj[curField]) {
45463                     obj[curField] = [];
45464                 }
45465                 if (rec.get(curField) !== undefined) {
45466                     obj[curField].push(rec.get(curField));
45467                 }
45468             }
45469         });
45470         
45471         for (key in aggStore) {
45472             obj = aggStore[key];
45473             for (i = 0; i < recFieldsLen; i++) {
45474                 curField = recFields[i];
45475                 obj[curField] = aggregateFn[op](obj[curField]);
45476             }
45477             json.push(obj);
45478         }
45479         this.chart.substore = Ext.create('Ext.data.JsonStore', {
45480             fields: recFields,
45481             data: json
45482         });
45483         
45484         this.dates = dates;
45485     },
45486     
45487     
45488      setLabels: function() {
45489         var store = this.chart.substore,
45490             fields = this.fields,
45491             format = this.dateFormat,
45492             labels, i, dates = this.dates,
45493             formatFn = Ext.Date.format;
45494         this.labels = labels = [];
45495         store.each(function(record, i) {
45496             if (!format) {
45497                 labels.push(record.get(fields));
45498             } else {
45499                 labels.push(formatFn(dates[i], format));
45500             }
45501          }, this);
45502      },
45503
45504     processView: function() {
45505          
45506          if (this.constrain) {
45507              this.constrainDates();
45508              this.aggregate();
45509              this.chart.substore = this.chart.filteredStore;
45510          } else {
45511              this.aggregate();
45512          }
45513     },
45514
45515      
45516      applyData: function() {
45517         this.setLabels();
45518         var count = this.chart.substore.getCount();
45519          return {
45520              from: 0,
45521              to: count,
45522              steps: count - 1,
45523              step: 1
45524          };
45525      }
45526  });
45527
45528
45529
45530 Ext.define('Ext.chart.series.Series', {
45531
45532     
45533
45534     mixins: {
45535         observable: 'Ext.util.Observable',
45536         labels: 'Ext.chart.Label',
45537         highlights: 'Ext.chart.Highlight',
45538         tips: 'Ext.chart.Tip',
45539         callouts: 'Ext.chart.Callout'
45540     },
45541
45542     
45543
45544     
45545
45546     
45547
45548     
45549     type: null,
45550
45551     
45552     title: null,
45553
45554     
45555     showInLegend: true,
45556
45557     
45558     renderer: function(sprite, record, attributes, index, store) {
45559         return attributes;
45560     },
45561
45562     
45563     shadowAttributes: null,
45564     
45565     //@private triggerdrawlistener flag
45566
45567     triggerAfterDraw: false,
45568
45569     
45570     
45571     constructor: function(config) {
45572         var me = this;
45573         if (config) {
45574             Ext.apply(me, config);
45575         }
45576         
45577         me.shadowGroups = [];
45578         
45579         me.mixins.labels.constructor.call(me, config);
45580         me.mixins.highlights.constructor.call(me, config);
45581         me.mixins.tips.constructor.call(me, config);
45582         me.mixins.callouts.constructor.call(me, config);
45583
45584         me.addEvents({
45585             scope: me,
45586             itemmouseover: true,
45587             itemmouseout: true,
45588             itemmousedown: true,
45589             itemmouseup: true,
45590             mouseleave: true,
45591             afterdraw: true,
45592
45593             
45594             titlechange: true
45595         });
45596
45597         me.mixins.observable.constructor.call(me, config);
45598
45599         me.on({
45600             scope: me,
45601             itemmouseover: me.onItemMouseOver,
45602             itemmouseout: me.onItemMouseOut,
45603             mouseleave: me.onMouseLeave
45604         });
45605     },
45606
45607     
45608     setBBox: function(noGutter) {
45609         var me = this,
45610             chart = me.chart,
45611             chartBBox = chart.chartBBox,
45612             gutterX = noGutter ? 0 : chart.maxGutter[0],
45613             gutterY = noGutter ? 0 : chart.maxGutter[1],
45614             clipBox, bbox;
45615
45616         clipBox = {
45617             x: chartBBox.x,
45618             y: chartBBox.y,
45619             width: chartBBox.width,
45620             height: chartBBox.height
45621         };
45622         me.clipBox = clipBox;
45623
45624         bbox = {
45625             x: (clipBox.x + gutterX) - (chart.zoom.x * chart.zoom.width),
45626             y: (clipBox.y + gutterY) - (chart.zoom.y * chart.zoom.height),
45627             width: (clipBox.width - (gutterX * 2)) * chart.zoom.width,
45628             height: (clipBox.height - (gutterY * 2)) * chart.zoom.height
45629         };
45630         me.bbox = bbox;
45631     },
45632
45633     
45634     onAnimate: function(sprite, attr) {
45635         var me = this;
45636         sprite.stopAnimation();
45637         if (me.triggerAfterDraw) {
45638             return sprite.animate(Ext.applyIf(attr, me.chart.animate));
45639         } else {
45640             me.triggerAfterDraw = true;
45641             return sprite.animate(Ext.apply(Ext.applyIf(attr, me.chart.animate), {
45642                 listeners: {
45643                     'afteranimate': function() {
45644                         me.triggerAfterDraw = false;
45645                         me.fireEvent('afterrender');
45646                     }    
45647                 }    
45648             }));
45649         }
45650     },
45651     
45652     
45653     getGutters: function() {
45654         return [0, 0];
45655     },
45656
45657     
45658     onItemMouseOver: function(item) { 
45659         var me = this;
45660         if (item.series === me) {
45661             if (me.highlight) {
45662                 me.highlightItem(item);
45663             }
45664             if (me.tooltip) {
45665                 me.showTip(item);
45666             }
45667         }
45668     },
45669
45670     
45671     onItemMouseOut: function(item) {
45672         var me = this;
45673         if (item.series === me) {
45674             me.unHighlightItem();
45675             if (me.tooltip) {
45676                 me.hideTip(item);
45677             }
45678         }
45679     },
45680
45681     
45682     onMouseLeave: function() {
45683         var me = this;
45684         me.unHighlightItem();
45685         if (me.tooltip) {
45686             me.hideTip();
45687         }
45688     },
45689
45690     
45691     getItemForPoint: function(x, y) {
45692         
45693         if (!this.items || !this.items.length || this.seriesIsHidden) {
45694             return null;
45695         }
45696         var me = this,
45697             items = me.items,
45698             bbox = me.bbox,
45699             item, i, ln;
45700         
45701         if (!Ext.draw.Draw.withinBox(x, y, bbox)) {
45702             return null;
45703         }
45704         for (i = 0, ln = items.length; i < ln; i++) {
45705             if (items[i] && this.isItemInPoint(x, y, items[i], i)) {
45706                 return items[i];
45707             }
45708         }
45709         
45710         return null;
45711     },
45712     
45713     isItemInPoint: function(x, y, item, i) {
45714         return false;
45715     },
45716
45717     
45718     hideAll: function() {
45719         var me = this,
45720             items = me.items,
45721             item, len, i, sprite;
45722
45723         me.seriesIsHidden = true;
45724         me._prevShowMarkers = me.showMarkers;
45725
45726         me.showMarkers = false;
45727         
45728         me.hideLabels(0);
45729         
45730         for (i = 0, len = items.length; i < len; i++) {
45731             item = items[i];
45732             sprite = item.sprite;
45733             if (sprite) {
45734                 sprite.setAttributes({
45735                     hidden: true
45736                 }, true);
45737             }
45738         }
45739     },
45740
45741     
45742     showAll: function() {
45743         var me = this,
45744             prevAnimate = me.chart.animate;
45745         me.chart.animate = false;
45746         me.seriesIsHidden = false;
45747         me.showMarkers = me._prevShowMarkers;
45748         me.drawSeries();
45749         me.chart.animate = prevAnimate;
45750     },
45751     
45752     
45753     getLegendColor: function(index) {
45754         var me = this, fill, stroke;
45755         if (me.seriesStyle) {
45756             fill = me.seriesStyle.fill;
45757             stroke = me.seriesStyle.stroke;
45758             if (fill && fill != 'none') {
45759                 return fill;
45760             }
45761             return stroke;
45762         }
45763         return '#000';
45764     },
45765     
45766     
45767     visibleInLegend: function(index){
45768         var excludes = this.__excludes;
45769         if (excludes) {
45770             return !excludes[index];
45771         }
45772         return !this.seriesIsHidden;
45773     },
45774
45775     
45776     setTitle: function(index, title) {
45777         var me = this,
45778             oldTitle = me.title;
45779
45780         if (Ext.isString(index)) {
45781             title = index;
45782             index = 0;
45783         }
45784
45785         if (Ext.isArray(oldTitle)) {
45786             oldTitle[index] = title;
45787         } else {
45788             me.title = title;
45789         }
45790
45791         me.fireEvent('titlechange', title, index);
45792     }
45793 });
45794
45795
45796 Ext.define('Ext.chart.series.Cartesian', {
45797
45798     
45799
45800     extend: 'Ext.chart.series.Series',
45801
45802     alternateClassName: ['Ext.chart.CartesianSeries', 'Ext.chart.CartesianChart'],
45803
45804     
45805
45806     
45807     xField: null,
45808
45809     
45810     yField: null,
45811
45812     
45813     axis: 'left'
45814 });
45815
45816
45817 Ext.define('Ext.chart.series.Area', {
45818
45819     
45820
45821     extend: 'Ext.chart.series.Cartesian',
45822     
45823     alias: 'series.area',
45824
45825     requires: ['Ext.chart.axis.Axis', 'Ext.draw.Color', 'Ext.fx.Anim'],
45826
45827     
45828
45829     type: 'area',
45830
45831     
45832     stacked: true,
45833
45834     
45835     style: {},
45836
45837     constructor: function(config) {
45838         this.callParent(arguments);
45839         var me = this,
45840             surface = me.chart.surface,
45841             i, l;
45842         Ext.apply(me, config, {
45843             __excludes: [],
45844             highlightCfg: {
45845                 lineWidth: 3,
45846                 stroke: '#55c',
45847                 opacity: 0.8,
45848                 color: '#f00'
45849             }
45850         });
45851         if (me.highlight) {
45852             me.highlightSprite = surface.add({
45853                 type: 'path',
45854                 path: ['M', 0, 0],
45855                 zIndex: 1000,
45856                 opacity: 0.3,
45857                 lineWidth: 5,
45858                 hidden: true,
45859                 stroke: '#444'
45860             });
45861         }
45862         me.group = surface.getGroup(me.seriesId);
45863     },
45864
45865     
45866     shrink: function(xValues, yValues, size) {
45867         var len = xValues.length,
45868             ratio = Math.floor(len / size),
45869             i, j,
45870             xSum = 0,
45871             yCompLen = this.areas.length,
45872             ySum = [],
45873             xRes = [],
45874             yRes = [];
45875         
45876         for (j = 0; j < yCompLen; ++j) {
45877             ySum[j] = 0;
45878         }
45879         for (i = 0; i < len; ++i) {
45880             xSum += xValues[i];
45881             for (j = 0; j < yCompLen; ++j) {
45882                 ySum[j] += yValues[i][j];
45883             }
45884             if (i % ratio == 0) {
45885                 
45886                 xRes.push(xSum/ratio);
45887                 for (j = 0; j < yCompLen; ++j) {
45888                     ySum[j] /= ratio;
45889                 }
45890                 yRes.push(ySum);
45891                 
45892                 xSum = 0;
45893                 for (j = 0, ySum = []; j < yCompLen; ++j) {
45894                     ySum[j] = 0;
45895                 }
45896             }
45897         }
45898         return {
45899             x: xRes,
45900             y: yRes
45901         };
45902     },
45903
45904     
45905     getBounds: function() {
45906         var me = this,
45907             chart = me.chart,
45908             store = chart.substore || chart.store,
45909             areas = [].concat(me.yField),
45910             areasLen = areas.length,
45911             xValues = [],
45912             yValues = [],
45913             infinity = Infinity,
45914             minX = infinity,
45915             minY = infinity,
45916             maxX = -infinity,
45917             maxY = -infinity,
45918             math = Math,
45919             mmin = math.min,
45920             mmax = math.max,
45921             bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem;
45922
45923         me.setBBox();
45924         bbox = me.bbox;
45925
45926         
45927         if (me.axis) {
45928             axis = chart.axes.get(me.axis);
45929             if (axis) {
45930                 out = axis.calcEnds();
45931                 minY = out.from || axis.prevMin;
45932                 maxY = mmax(out.to || axis.prevMax, 0);
45933             }
45934         }
45935
45936         if (me.yField && !Ext.isNumber(minY)) {
45937             axis = Ext.create('Ext.chart.axis.Axis', {
45938                 chart: chart,
45939                 fields: [].concat(me.yField)
45940             });
45941             out = axis.calcEnds();
45942             minY = out.from || axis.prevMin;
45943             maxY = mmax(out.to || axis.prevMax, 0);
45944         }
45945
45946         if (!Ext.isNumber(minY)) {
45947             minY = 0;
45948         }
45949         if (!Ext.isNumber(maxY)) {
45950             maxY = 0;
45951         }
45952
45953         store.each(function(record, i) {
45954             xValue = record.get(me.xField);
45955             yValue = [];
45956             if (typeof xValue != 'number') {
45957                 xValue = i;
45958             }
45959             xValues.push(xValue);
45960             acumY = 0;
45961             for (areaIndex = 0; areaIndex < areasLen; areaIndex++) {
45962                 areaElem = record.get(areas[areaIndex]);
45963                 if (typeof areaElem == 'number') {
45964                     minY = mmin(minY, areaElem);
45965                     yValue.push(areaElem);
45966                     acumY += areaElem;
45967                 }
45968             }
45969             minX = mmin(minX, xValue);
45970             maxX = mmax(maxX, xValue);
45971             maxY = mmax(maxY, acumY);
45972             yValues.push(yValue);
45973         }, me);
45974
45975         xScale = bbox.width / (maxX - minX);
45976         yScale = bbox.height / (maxY - minY);
45977
45978         ln = xValues.length;
45979         if ((ln > bbox.width) && me.areas) {
45980             sumValues = me.shrink(xValues, yValues, bbox.width);
45981             xValues = sumValues.x;
45982             yValues = sumValues.y;
45983         }
45984
45985         return {
45986             bbox: bbox,
45987             minX: minX,
45988             minY: minY,
45989             xValues: xValues,
45990             yValues: yValues,
45991             xScale: xScale,
45992             yScale: yScale,
45993             areasLen: areasLen
45994         };
45995     },
45996
45997     
45998     getPaths: function() {
45999         var me = this,
46000             chart = me.chart,
46001             store = chart.substore || chart.store,
46002             first = true,
46003             bounds = me.getBounds(),
46004             bbox = bounds.bbox,
46005             items = me.items = [],
46006             componentPaths = [],
46007             componentPath,
46008             paths = [],
46009             i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path;
46010
46011         ln = bounds.xValues.length;
46012         
46013         for (i = 0; i < ln; i++) {
46014             xValue = bounds.xValues[i];
46015             yValue = bounds.yValues[i];
46016             x = bbox.x + (xValue - bounds.minX) * bounds.xScale;
46017             acumY = 0;
46018             for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
46019                 
46020                 if (me.__excludes[areaIndex]) {
46021                     continue;
46022                 }
46023                 if (!componentPaths[areaIndex]) {
46024                     componentPaths[areaIndex] = [];
46025                 }
46026                 areaElem = yValue[areaIndex];
46027                 acumY += areaElem;
46028                 y = bbox.y + bbox.height - (acumY - bounds.minY) * bounds.yScale;
46029                 if (!paths[areaIndex]) {
46030                     paths[areaIndex] = ['M', x, y];
46031                     componentPaths[areaIndex].push(['L', x, y]);
46032                 } else {
46033                     paths[areaIndex].push('L', x, y);
46034                     componentPaths[areaIndex].push(['L', x, y]);
46035                 }
46036                 if (!items[areaIndex]) {
46037                     items[areaIndex] = {
46038                         pointsUp: [],
46039                         pointsDown: [],
46040                         series: me
46041                     };
46042                 }
46043                 items[areaIndex].pointsUp.push([x, y]);
46044             }
46045         }
46046         
46047         
46048         for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
46049             
46050             if (me.__excludes[areaIndex]) {
46051                 continue;
46052             }
46053             path = paths[areaIndex];
46054             
46055             if (areaIndex == 0 || first) {
46056                 first = false;
46057                 path.push('L', x, bbox.y + bbox.height,
46058                           'L', bbox.x, bbox.y + bbox.height,
46059                           'Z');
46060             }
46061             
46062             else {
46063                 componentPath = componentPaths[prevAreaIndex];
46064                 componentPath.reverse();
46065                 path.push('L', x, componentPath[0][2]);
46066                 for (i = 0; i < ln; i++) {
46067                     path.push(componentPath[i][0],
46068                               componentPath[i][1],
46069                               componentPath[i][2]);
46070                     items[areaIndex].pointsDown[ln -i -1] = [componentPath[i][1], componentPath[i][2]];
46071                 }
46072                 path.push('L', bbox.x, path[2], 'Z');
46073             }
46074             prevAreaIndex = areaIndex;
46075         }
46076         return {
46077             paths: paths,
46078             areasLen: bounds.areasLen
46079         };
46080     },
46081
46082     
46083     drawSeries: function() {
46084         var me = this,
46085             chart = me.chart,
46086             store = chart.substore || chart.store,
46087             surface = chart.surface,
46088             animate = chart.animate,
46089             group = me.group,
46090             endLineStyle = Ext.apply(me.seriesStyle, me.style),
46091             colorArrayStyle = me.colorArrayStyle,
46092             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
46093             areaIndex, areaElem, paths, path, rendererAttributes;
46094
46095         me.unHighlightItem();
46096         me.cleanHighlights();
46097
46098         if (!store || !store.getCount()) {
46099             return;
46100         }
46101         
46102         paths = me.getPaths();
46103
46104         if (!me.areas) {
46105             me.areas = [];
46106         }
46107
46108         for (areaIndex = 0; areaIndex < paths.areasLen; areaIndex++) {
46109             
46110             if (me.__excludes[areaIndex]) {
46111                 continue;
46112             }
46113             if (!me.areas[areaIndex]) {
46114                 me.items[areaIndex].sprite = me.areas[areaIndex] = surface.add(Ext.apply({}, {
46115                     type: 'path',
46116                     group: group,
46117                     
46118                     path: paths.paths[areaIndex],
46119                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength],
46120                     fill: colorArrayStyle[areaIndex % colorArrayLength]
46121                 }, endLineStyle || {}));
46122             }
46123             areaElem = me.areas[areaIndex];
46124             path = paths.paths[areaIndex];
46125             if (animate) {
46126                 
46127                 rendererAttributes = me.renderer(areaElem, false, { 
46128                     path: path,
46129                     
46130                     fill: colorArrayStyle[areaIndex % colorArrayLength],
46131                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
46132                 }, areaIndex, store);
46133                 
46134                 me.animation = me.onAnimate(areaElem, {
46135                     to: rendererAttributes
46136                 });
46137             } else {
46138                 rendererAttributes = me.renderer(areaElem, false, { 
46139                     path: path,
46140                     
46141                     hidden: false,
46142                     fill: colorArrayStyle[areaIndex % colorArrayLength],
46143                     stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength]
46144                 }, areaIndex, store);
46145                 me.areas[areaIndex].setAttributes(rendererAttributes, true);
46146             }
46147         }
46148         me.renderLabels();
46149         me.renderCallouts();
46150     },
46151
46152     
46153     onAnimate: function(sprite, attr) {
46154         sprite.show();
46155         return this.callParent(arguments);
46156     },
46157
46158     
46159     onCreateLabel: function(storeItem, item, i, display) {
46160         var me = this,
46161             group = me.labelsGroup,
46162             config = me.label,
46163             bbox = me.bbox,
46164             endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
46165
46166         return me.chart.surface.add(Ext.apply({
46167             'type': 'text',
46168             'text-anchor': 'middle',
46169             'group': group,
46170             'x': item.point[0],
46171             'y': bbox.y + bbox.height / 2
46172         }, endLabelStyle || {}));
46173     },
46174
46175     
46176     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
46177         var me = this,
46178             chart = me.chart,
46179             resizing = chart.resizing,
46180             config = me.label,
46181             format = config.renderer,
46182             field = config.field,
46183             bbox = me.bbox,
46184             x = item.point[0],
46185             y = item.point[1],
46186             bb, width, height;
46187         
46188         label.setAttributes({
46189             text: format(storeItem.get(field[index])),
46190             hidden: true
46191         }, true);
46192         
46193         bb = label.getBBox();
46194         width = bb.width / 2;
46195         height = bb.height / 2;
46196         
46197         x = x - width < bbox.x? bbox.x + width : x;
46198         x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
46199         y = y - height < bbox.y? bbox.y + height : y;
46200         y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
46201
46202         if (me.chart.animate && !me.chart.resizing) {
46203             label.show(true);
46204             me.onAnimate(label, {
46205                 to: {
46206                     x: x,
46207                     y: y
46208                 }
46209             });
46210         } else {
46211             label.setAttributes({
46212                 x: x,
46213                 y: y
46214             }, true);
46215             if (resizing) {
46216                 me.animation.on('afteranimate', function() {
46217                     label.show(true);
46218                 });
46219             } else {
46220                 label.show(true);
46221             }
46222         }
46223     },
46224
46225     
46226     onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
46227         var me = this,
46228             chart = me.chart,
46229             surface = chart.surface,
46230             resizing = chart.resizing,
46231             config = me.callouts,
46232             items = me.items,
46233             prev = (i == 0) ? false : items[i -1].point,
46234             next = (i == items.length -1) ? false : items[i +1].point,
46235             cur = item.point,
46236             dir, norm, normal, a, aprev, anext,
46237             bbox = callout.label.getBBox(),
46238             offsetFromViz = 30,
46239             offsetToSide = 10,
46240             offsetBox = 3,
46241             boxx, boxy, boxw, boxh,
46242             p, clipRect = me.clipRect,
46243             x, y;
46244
46245         
46246         if (!prev) {
46247             prev = cur;
46248         }
46249         if (!next) {
46250             next = cur;
46251         }
46252         a = (next[1] - prev[1]) / (next[0] - prev[0]);
46253         aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
46254         anext = (next[1] - cur[1]) / (next[0] - cur[0]);
46255         
46256         norm = Math.sqrt(1 + a * a);
46257         dir = [1 / norm, a / norm];
46258         normal = [-dir[1], dir[0]];
46259         
46260         
46261         if (aprev > 0 && anext < 0 && normal[1] < 0 || aprev < 0 && anext > 0 && normal[1] > 0) {
46262             normal[0] *= -1;
46263             normal[1] *= -1;
46264         } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0 || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
46265             normal[0] *= -1;
46266             normal[1] *= -1;
46267         }
46268
46269         
46270         x = cur[0] + normal[0] * offsetFromViz;
46271         y = cur[1] + normal[1] * offsetFromViz;
46272         
46273         
46274         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
46275         boxy = y - bbox.height /2 - offsetBox;
46276         boxw = bbox.width + 2 * offsetBox;
46277         boxh = bbox.height + 2 * offsetBox;
46278         
46279         
46280         
46281         if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
46282             normal[0] *= -1;
46283         }
46284         if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
46285             normal[1] *= -1;
46286         }
46287
46288         
46289         x = cur[0] + normal[0] * offsetFromViz;
46290         y = cur[1] + normal[1] * offsetFromViz;
46291         
46292         
46293         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
46294         boxy = y - bbox.height /2 - offsetBox;
46295         boxw = bbox.width + 2 * offsetBox;
46296         boxh = bbox.height + 2 * offsetBox;
46297         
46298         
46299         callout.lines.setAttributes({
46300             path: ["M", cur[0], cur[1], "L", x, y, "Z"]
46301         }, true);
46302         
46303         callout.box.setAttributes({
46304             x: boxx,
46305             y: boxy,
46306             width: boxw,
46307             height: boxh
46308         }, true);
46309         
46310         callout.label.setAttributes({
46311             x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
46312             y: y
46313         }, true);
46314         for (p in callout) {
46315             callout[p].show(true);
46316         }
46317     },
46318     
46319     isItemInPoint: function(x, y, item, i) {
46320         var me = this,
46321             pointsUp = item.pointsUp,
46322             pointsDown = item.pointsDown,
46323             abs = Math.abs,
46324             dist = Infinity, p, pln, point;
46325         
46326         for (p = 0, pln = pointsUp.length; p < pln; p++) {
46327             point = [pointsUp[p][0], pointsUp[p][1]];
46328             if (dist > abs(x - point[0])) {
46329                 dist = abs(x - point[0]);
46330             } else {
46331                 point = pointsUp[p -1];
46332                 if (y >= point[1] && (!pointsDown.length || y <= (pointsDown[p -1][1]))) {
46333                     item.storeIndex = p -1;
46334                     item.storeField = me.yField[i];
46335                     item.storeItem = me.chart.store.getAt(p -1);
46336                     item._points = pointsDown.length? [point, pointsDown[p -1]] : [point];
46337                     return true;
46338                 } else {
46339                     break;
46340                 }
46341             }
46342         }
46343         return false;
46344     },
46345
46346     
46347     highlightSeries: function() {
46348         var area, to, fillColor;
46349         if (this._index !== undefined) {
46350             area = this.areas[this._index];
46351             if (area.__highlightAnim) {
46352                 area.__highlightAnim.paused = true;
46353             }
46354             area.__highlighted = true;
46355             area.__prevOpacity = area.__prevOpacity || area.attr.opacity || 1;
46356             area.__prevFill = area.__prevFill || area.attr.fill;
46357             area.__prevLineWidth = area.__prevLineWidth || area.attr.lineWidth;
46358             fillColor = Ext.draw.Color.fromString(area.__prevFill);
46359             to = {
46360                 lineWidth: (area.__prevLineWidth || 0) + 2
46361             };
46362             if (fillColor) {
46363                 to.fill = fillColor.getLighter(0.2).toString();
46364             }
46365             else {
46366                 to.opacity = Math.max(area.__prevOpacity - 0.3, 0);
46367             }
46368             if (this.chart.animate) {
46369                 area.__highlightAnim = Ext.create('Ext.fx.Anim', Ext.apply({
46370                     target: area,
46371                     to: to
46372                 }, this.chart.animate));
46373             }
46374             else {
46375                 area.setAttributes(to, true);
46376             }
46377         }
46378     },
46379
46380     
46381     unHighlightSeries: function() {
46382         var area;
46383         if (this._index !== undefined) {
46384             area = this.areas[this._index];
46385             if (area.__highlightAnim) {
46386                 area.__highlightAnim.paused = true;
46387             }
46388             if (area.__highlighted) {
46389                 area.__highlighted = false;
46390                 area.__highlightAnim = Ext.create('Ext.fx.Anim', {
46391                     target: area,
46392                     to: {
46393                         fill: area.__prevFill,
46394                         opacity: area.__prevOpacity,
46395                         lineWidth: area.__prevLineWidth
46396                     }
46397                 });
46398             }
46399         }
46400     },
46401
46402     
46403     highlightItem: function(item) {
46404         var me = this,
46405             points, path;
46406         if (!item) {
46407             this.highlightSeries();
46408             return;
46409         }
46410         points = item._points;
46411         path = points.length == 2? ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]
46412                 : ['M', points[0][0], points[0][1], 'L', points[0][0], me.bbox.y + me.bbox.height];
46413         me.highlightSprite.setAttributes({
46414             path: path,
46415             hidden: false
46416         }, true);
46417     },
46418
46419     
46420     unHighlightItem: function(item) {
46421         if (!item) {
46422             this.unHighlightSeries();
46423         }
46424
46425         if (this.highlightSprite) {
46426             this.highlightSprite.hide(true);
46427         }
46428     },
46429
46430     
46431     hideAll: function() {
46432         if (!isNaN(this._index)) {
46433             this.__excludes[this._index] = true;
46434             this.areas[this._index].hide(true);
46435             this.drawSeries();
46436         }
46437     },
46438
46439     
46440     showAll: function() {
46441         if (!isNaN(this._index)) {
46442             this.__excludes[this._index] = false;
46443             this.areas[this._index].show(true);
46444             this.drawSeries();
46445         }
46446     },
46447
46448     
46449     getLegendColor: function(index) {
46450         var me = this;
46451         return me.colorArrayStyle[index % me.colorArrayStyle.length];
46452     }
46453 });
46454
46455
46456 Ext.define('Ext.chart.series.Bar', {
46457
46458     
46459
46460     extend: 'Ext.chart.series.Cartesian',
46461
46462     alternateClassName: ['Ext.chart.BarSeries', 'Ext.chart.BarChart', 'Ext.chart.StackedBarChart'],
46463
46464     requires: ['Ext.chart.axis.Axis', 'Ext.fx.Anim'],
46465
46466     
46467
46468     type: 'bar',
46469
46470     alias: 'series.bar',
46471     
46472     column: false,
46473     
46474     
46475     style: {},
46476     
46477     
46478     gutter: 38.2,
46479
46480     
46481     groupGutter: 38.2,
46482
46483     
46484     xPadding: 0,
46485
46486     
46487     yPadding: 10,
46488
46489     constructor: function(config) {
46490         this.callParent(arguments);
46491         var me = this,
46492             surface = me.chart.surface,
46493             shadow = me.chart.shadow,
46494             i, l;
46495         Ext.apply(me, config, {
46496             highlightCfg: {
46497                 lineWidth: 3,
46498                 stroke: '#55c',
46499                 opacity: 0.8,
46500                 color: '#f00'
46501             },
46502             
46503             shadowAttributes: [{
46504                 "stroke-width": 6,
46505                 "stroke-opacity": 0.05,
46506                 stroke: 'rgb(200, 200, 200)',
46507                 translate: {
46508                     x: 1.2,
46509                     y: 1.2
46510                 }
46511             }, {
46512                 "stroke-width": 4,
46513                 "stroke-opacity": 0.1,
46514                 stroke: 'rgb(150, 150, 150)',
46515                 translate: {
46516                     x: 0.9,
46517                     y: 0.9
46518                 }
46519             }, {
46520                 "stroke-width": 2,
46521                 "stroke-opacity": 0.15,
46522                 stroke: 'rgb(100, 100, 100)',
46523                 translate: {
46524                     x: 0.6,
46525                     y: 0.6
46526                 }
46527             }]
46528         });
46529         me.group = surface.getGroup(me.seriesId + '-bars');
46530         if (shadow) {
46531             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
46532                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
46533             }
46534         }
46535     },
46536
46537     
46538     getBarGirth: function() {
46539         var me = this,
46540             store = me.chart.store,
46541             column = me.column,
46542             ln = store.getCount(),
46543             gutter = me.gutter / 100;
46544         
46545         return (me.chart.chartBBox[column ? 'width' : 'height'] - me[column ? 'xPadding' : 'yPadding'] * 2) / (ln * (gutter + 1) - gutter);
46546     },
46547
46548     
46549     getGutters: function() {
46550         var me = this,
46551             column = me.column,
46552             gutter = Math.ceil(me[column ? 'xPadding' : 'yPadding'] + me.getBarGirth() / 2);
46553         return me.column ? [gutter, 0] : [0, gutter];
46554     },
46555
46556     
46557     getBounds: function() {
46558         var me = this,
46559             chart = me.chart,
46560             store = chart.substore || chart.store,
46561             bars = [].concat(me.yField),
46562             barsLen = bars.length,
46563             groupBarsLen = barsLen,
46564             groupGutter = me.groupGutter / 100,
46565             column = me.column,
46566             xPadding = me.xPadding,
46567             yPadding = me.yPadding,
46568             stacked = me.stacked,
46569             barWidth = me.getBarGirth(),
46570             math = Math,
46571             mmax = math.max,
46572             mabs = math.abs,
46573             groupBarWidth, bbox, minY, maxY, axis, out,
46574             scale, zero, total, rec, j, plus, minus;
46575
46576         me.setBBox(true);
46577         bbox = me.bbox;
46578
46579         
46580         if (me.__excludes) {
46581             for (j = 0, total = me.__excludes.length; j < total; j++) {
46582                 if (me.__excludes[j]) {
46583                     groupBarsLen--;
46584                 }
46585             }
46586         }
46587
46588         if (me.axis) {
46589             axis = chart.axes.get(me.axis);
46590             if (axis) {
46591                 out = axis.calcEnds();
46592                 minY = out.from || axis.prevMin;
46593                 maxY = mmax(out.to || axis.prevMax, 0);
46594             }
46595         }
46596
46597         if (me.yField && !Ext.isNumber(minY)) {
46598             axis = Ext.create('Ext.chart.axis.Axis', {
46599                 chart: chart,
46600                 fields: [].concat(me.yField)
46601             });
46602             out = axis.calcEnds();
46603             minY = out.from || axis.prevMin;
46604             maxY = mmax(out.to || axis.prevMax, 0);
46605         }
46606
46607         if (!Ext.isNumber(minY)) {
46608             minY = 0;
46609         }
46610         if (!Ext.isNumber(maxY)) {
46611             maxY = 0;
46612         }
46613         scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (maxY - minY);
46614         groupBarWidth = barWidth / ((stacked ? 1 : groupBarsLen) * (groupGutter + 1) - groupGutter);
46615         zero = (column) ? bbox.y + bbox.height - yPadding : bbox.x + xPadding;
46616
46617         if (stacked) {
46618             total = [[], []];
46619             store.each(function(record, i) {
46620                 total[0][i] = total[0][i] || 0;
46621                 total[1][i] = total[1][i] || 0;
46622                 for (j = 0; j < barsLen; j++) {
46623                     if (me.__excludes && me.__excludes[j]) {
46624                         continue;
46625                     }
46626                     rec = record.get(bars[j]);
46627                     total[+(rec > 0)][i] += mabs(rec);
46628                 }
46629             });
46630             total[+(maxY > 0)].push(mabs(maxY));
46631             total[+(minY > 0)].push(mabs(minY));
46632             minus = mmax.apply(math, total[0]);
46633             plus = mmax.apply(math, total[1]);
46634             scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (plus + minus);
46635             zero = zero + minus * scale * (column ? -1 : 1);
46636         }
46637         else if (minY / maxY < 0) {
46638             zero = zero - minY * scale * (column ? -1 : 1);
46639         }
46640         return {
46641             bars: bars,
46642             bbox: bbox,
46643             barsLen: barsLen,
46644             groupBarsLen: groupBarsLen,
46645             barWidth: barWidth,
46646             groupBarWidth: groupBarWidth,
46647             scale: scale,
46648             zero: zero,
46649             xPadding: xPadding,
46650             yPadding: yPadding,
46651             signed: minY / maxY < 0,
46652             minY: minY,
46653             maxY: maxY
46654         };
46655     },
46656
46657     
46658     getPaths: function() {
46659         var me = this,
46660             chart = me.chart,
46661             store = chart.substore || chart.store,
46662             bounds = me.bounds = me.getBounds(),
46663             items = me.items = [],
46664             gutter = me.gutter / 100,
46665             groupGutter = me.groupGutter / 100,
46666             animate = chart.animate,
46667             column = me.column,
46668             group = me.group,
46669             enableShadows = chart.shadow,
46670             shadowGroups = me.shadowGroups,
46671             shadowAttributes = me.shadowAttributes,
46672             shadowGroupsLn = shadowGroups.length,
46673             bbox = bounds.bbox,
46674             xPadding = me.xPadding,
46675             yPadding = me.yPadding,
46676             stacked = me.stacked,
46677             barsLen = bounds.barsLen,
46678             colors = me.colorArrayStyle,
46679             colorLength = colors && colors.length || 0,
46680             math = Math,
46681             mmax = math.max,
46682             mmin = math.min,
46683             mabs = math.abs,
46684             j, yValue, height, totalDim, totalNegDim, bottom, top, hasShadow, barAttr, attrs, counter,
46685             shadowIndex, shadow, sprite, offset, floorY;
46686
46687         store.each(function(record, i, total) {
46688             bottom = bounds.zero;
46689             top = bounds.zero;
46690             totalDim = 0;
46691             totalNegDim = 0;
46692             hasShadow = false; 
46693             for (j = 0, counter = 0; j < barsLen; j++) {
46694                 
46695                 if (me.__excludes && me.__excludes[j]) {
46696                     continue;
46697                 }
46698                 yValue = record.get(bounds.bars[j]);
46699                 height = Math.round((yValue - ((bounds.minY < 0) ? 0 : bounds.minY)) * bounds.scale);
46700                 barAttr = {
46701                     fill: colors[(barsLen > 1 ? j : 0) % colorLength]
46702                 };
46703                 if (column) {
46704                     Ext.apply(barAttr, {
46705                         height: height,
46706                         width: mmax(bounds.groupBarWidth, 0),
46707                         x: (bbox.x + xPadding + i * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked),
46708                         y: bottom - height
46709                     });
46710                 }
46711                 else {
46712                     
46713                     offset = (total - 1) - i;
46714                     Ext.apply(barAttr, {
46715                         height: mmax(bounds.groupBarWidth, 0),
46716                         width: height + (bottom == bounds.zero),
46717                         x: bottom + (bottom != bounds.zero),
46718                         y: (bbox.y + yPadding + offset * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked + 1)
46719                     });
46720                 }
46721                 if (height < 0) {
46722                     if (column) {
46723                         barAttr.y = top;
46724                         barAttr.height = mabs(height);
46725                     } else {
46726                         barAttr.x = top + height;
46727                         barAttr.width = mabs(height);
46728                     }
46729                 }
46730                 if (stacked) {
46731                     if (height < 0) {
46732                         top += height * (column ? -1 : 1);
46733                     } else {
46734                         bottom += height * (column ? -1 : 1);
46735                     }
46736                     totalDim += mabs(height);
46737                     if (height < 0) {
46738                         totalNegDim += mabs(height);
46739                     }
46740                 }
46741                 barAttr.x = Math.floor(barAttr.x) + 1;
46742                 floorY = Math.floor(barAttr.y);
46743                 if (!Ext.isIE9 && barAttr.y > floorY) {
46744                     floorY--;
46745                 }
46746                 barAttr.y = floorY;
46747                 barAttr.width = Math.floor(barAttr.width);
46748                 barAttr.height = Math.floor(barAttr.height);
46749                 items.push({
46750                     series: me,
46751                     storeItem: record,
46752                     value: [record.get(me.xField), yValue],
46753                     attr: barAttr,
46754                     point: column ? [barAttr.x + barAttr.width / 2, yValue >= 0 ? barAttr.y : barAttr.y + barAttr.height] :
46755                                     [yValue >= 0 ? barAttr.x + barAttr.width : barAttr.x, barAttr.y + barAttr.height / 2]
46756                 });
46757                 
46758                 if (animate && chart.resizing) {
46759                     attrs = column ? {
46760                         x: barAttr.x,
46761                         y: bounds.zero,
46762                         width: barAttr.width,
46763                         height: 0
46764                     } : {
46765                         x: bounds.zero,
46766                         y: barAttr.y,
46767                         width: 0,
46768                         height: barAttr.height
46769                     };
46770                     if (enableShadows && (stacked && !hasShadow || !stacked)) {
46771                         hasShadow = true;
46772                         
46773                         for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
46774                             shadow = shadowGroups[shadowIndex].getAt(stacked ? i : (i * barsLen + j));
46775                             if (shadow) {
46776                                 shadow.setAttributes(attrs, true);
46777                             }
46778                         }
46779                     }
46780                     
46781                     sprite = group.getAt(i * barsLen + j);
46782                     if (sprite) {
46783                         sprite.setAttributes(attrs, true);
46784                     }
46785                 }
46786                 counter++;
46787             }
46788             if (stacked && items.length) {
46789                 items[i * counter].totalDim = totalDim;
46790                 items[i * counter].totalNegDim = totalNegDim;
46791             }
46792         }, me);
46793     },
46794
46795     
46796     renderShadows: function(i, barAttr, baseAttrs, bounds) {
46797         var me = this,
46798             chart = me.chart,
46799             surface = chart.surface,
46800             animate = chart.animate,
46801             stacked = me.stacked,
46802             shadowGroups = me.shadowGroups,
46803             shadowAttributes = me.shadowAttributes,
46804             shadowGroupsLn = shadowGroups.length,
46805             store = chart.substore || chart.store,
46806             column = me.column,
46807             items = me.items,
46808             shadows = [],
46809             zero = bounds.zero,
46810             shadowIndex, shadowBarAttr, shadow, totalDim, totalNegDim, j, rendererAttributes;
46811
46812         if ((stacked && (i % bounds.groupBarsLen === 0)) || !stacked) {
46813             j = i / bounds.groupBarsLen;
46814             
46815             for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
46816                 shadowBarAttr = Ext.apply({}, shadowAttributes[shadowIndex]);
46817                 shadow = shadowGroups[shadowIndex].getAt(stacked ? j : i);
46818                 Ext.copyTo(shadowBarAttr, barAttr, 'x,y,width,height');
46819                 if (!shadow) {
46820                     shadow = surface.add(Ext.apply({
46821                         type: 'rect',
46822                         group: shadowGroups[shadowIndex]
46823                     }, Ext.apply({}, baseAttrs, shadowBarAttr)));
46824                 }
46825                 if (stacked) {
46826                     totalDim = items[i].totalDim;
46827                     totalNegDim = items[i].totalNegDim;
46828                     if (column) {
46829                         shadowBarAttr.y = zero - totalNegDim;
46830                         shadowBarAttr.height = totalDim;
46831                     }
46832                     else {
46833                         shadowBarAttr.x = zero - totalNegDim;
46834                         shadowBarAttr.width = totalDim;
46835                     }
46836                 }
46837                 if (animate) {
46838                     if (!stacked) {
46839                         rendererAttributes = me.renderer(shadow, store.getAt(j), shadowBarAttr, i, store);
46840                         me.onAnimate(shadow, { to: rendererAttributes });
46841                     }
46842                     else {
46843                         rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: true }), i, store);
46844                         shadow.setAttributes(rendererAttributes, true);
46845                     }
46846                 }
46847                 else {
46848                     rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: false }), i, store);
46849                     shadow.setAttributes(rendererAttributes, true);
46850                 }
46851                 shadows.push(shadow);
46852             }
46853         }
46854         return shadows;
46855     },
46856
46857     
46858     drawSeries: function() {
46859         var me = this,
46860             chart = me.chart,
46861             store = chart.substore || chart.store,
46862             surface = chart.surface,
46863             animate = chart.animate,
46864             stacked = me.stacked,
46865             column = me.column,
46866             enableShadows = chart.shadow,
46867             shadowGroups = me.shadowGroups,
46868             shadowGroupsLn = shadowGroups.length,
46869             group = me.group,
46870             seriesStyle = me.seriesStyle,
46871             items, ln, i, j, baseAttrs, sprite, rendererAttributes, shadowIndex, shadowGroup,
46872             bounds, endSeriesStyle, barAttr, attrs, anim;
46873         
46874         if (!store || !store.getCount()) {
46875             return;
46876         }
46877         
46878         
46879         delete seriesStyle.fill;
46880         endSeriesStyle = Ext.apply(seriesStyle, this.style);
46881         me.unHighlightItem();
46882         me.cleanHighlights();
46883
46884         me.getPaths();
46885         bounds = me.bounds;
46886         items = me.items;
46887
46888         baseAttrs = column ? {
46889             y: bounds.zero,
46890             height: 0
46891         } : {
46892             x: bounds.zero,
46893             width: 0
46894         };
46895         ln = items.length;
46896         
46897         for (i = 0; i < ln; i++) {
46898             sprite = group.getAt(i);
46899             barAttr = items[i].attr;
46900
46901             if (enableShadows) {
46902                 items[i].shadows = me.renderShadows(i, barAttr, baseAttrs, bounds);
46903             }
46904
46905             
46906             if (!sprite) {
46907                 attrs = Ext.apply({}, baseAttrs, barAttr);
46908                 attrs = Ext.apply(attrs, endSeriesStyle || {});
46909                 sprite = surface.add(Ext.apply({}, {
46910                     type: 'rect',
46911                     group: group
46912                 }, attrs));
46913             }
46914             if (animate) {
46915                 rendererAttributes = me.renderer(sprite, store.getAt(i), barAttr, i, store);
46916                 sprite._to = rendererAttributes;
46917                 anim = me.onAnimate(sprite, { to: Ext.apply(rendererAttributes, endSeriesStyle) });
46918                 if (enableShadows && stacked && (i % bounds.barsLen === 0)) {
46919                     j = i / bounds.barsLen;
46920                     for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
46921                         anim.on('afteranimate', function() {
46922                             this.show(true);
46923                         }, shadowGroups[shadowIndex].getAt(j));
46924                     }
46925                 }
46926             }
46927             else {
46928                 rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(barAttr, { hidden: false }), i, store);
46929                 sprite.setAttributes(Ext.apply(rendererAttributes, endSeriesStyle), true);
46930             }
46931             items[i].sprite = sprite;
46932         }
46933
46934         
46935         ln = group.getCount();
46936         for (j = i; j < ln; j++) {
46937             group.getAt(j).hide(true);
46938         }
46939         
46940         if (enableShadows) {
46941             for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) {
46942                 shadowGroup = shadowGroups[shadowIndex];
46943                 ln = shadowGroup.getCount();
46944                 for (j = i; j < ln; j++) {
46945                     shadowGroup.getAt(j).hide(true);
46946                 }
46947             }
46948         }
46949         me.renderLabels();
46950     },
46951     
46952     
46953     onCreateLabel: function(storeItem, item, i, display) {
46954         var me = this,
46955             surface = me.chart.surface,
46956             group = me.labelsGroup,
46957             config = me.label,
46958             endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle || {}),
46959             sprite;
46960         return surface.add(Ext.apply({
46961             type: 'text',
46962             group: group
46963         }, endLabelStyle || {}));
46964     },
46965     
46966     
46967     onPlaceLabel: function(label, storeItem, item, i, display, animate, j, index) {
46968         
46969         
46970         var me = this,
46971             opt = me.bounds,
46972             groupBarWidth = opt.groupBarWidth,
46973             column = me.column,
46974             chart = me.chart,
46975             chartBBox = chart.chartBBox,
46976             resizing = chart.resizing,
46977             xValue = item.value[0],
46978             yValue = item.value[1],
46979             attr = item.attr,
46980             config = me.label,
46981             rotate = config.orientation == 'vertical',
46982             field = [].concat(config.field),
46983             format = config.renderer,
46984             text = format(storeItem.get(field[index])),
46985             size = me.getLabelSize(text),
46986             width = size.width,
46987             height = size.height,
46988             zero = opt.zero,
46989             outside = 'outside',
46990             insideStart = 'insideStart',
46991             insideEnd = 'insideEnd',
46992             offsetX = 10,
46993             offsetY = 6,
46994             signed = opt.signed,
46995             x, y, finalAttr;
46996
46997         label.setAttributes({
46998             text: text
46999         });
47000
47001         if (column) {
47002             if (display == outside) {
47003                 if (height + offsetY + attr.height > (yValue >= 0 ? zero - chartBBox.y : chartBBox.y + chartBBox.height - zero)) {
47004                     display = insideEnd;
47005                 }
47006             } else {
47007                 if (height + offsetY > attr.height) {
47008                     display = outside;
47009                 }
47010             }
47011             x = attr.x + groupBarWidth / 2;
47012             y = display == insideStart ?
47013                     (zero + ((height / 2 + 3) * (yValue >= 0 ? -1 : 1))) :
47014                     (yValue >= 0 ? (attr.y + ((height / 2 + 3) * (display == outside ? -1 : 1))) :
47015                                    (attr.y + attr.height + ((height / 2 + 3) * (display === outside ? 1 : -1))));
47016         }
47017         else {
47018             if (display == outside) {
47019                 if (width + offsetX + attr.width > (yValue >= 0 ? chartBBox.x + chartBBox.width - zero : zero - chartBBox.x)) {
47020                     display = insideEnd;
47021                 }
47022             }
47023             else {
47024                 if (width + offsetX > attr.width) {
47025                     display = outside;
47026                 }
47027             }
47028             x = display == insideStart ?
47029                 (zero + ((width / 2 + 5) * (yValue >= 0 ? 1 : -1))) :
47030                 (yValue >= 0 ? (attr.x + attr.width + ((width / 2 + 5) * (display === outside ? 1 : -1))) :
47031                 (attr.x + ((width / 2 + 5) * (display === outside ? -1 : 1))));
47032             y = attr.y + groupBarWidth / 2;
47033         }
47034         
47035         finalAttr = {
47036             x: x,
47037             y: y
47038         };
47039         
47040         if (rotate) {
47041             finalAttr.rotate = {
47042                 x: x,
47043                 y: y,
47044                 degrees: 270
47045             };
47046         }
47047         
47048         if (animate && resizing) {
47049             if (column) {
47050                 x = attr.x + attr.width / 2;
47051                 y = zero;
47052             } else {
47053                 x = zero;
47054                 y = attr.y + attr.height / 2;
47055             }
47056             label.setAttributes({
47057                 x: x,
47058                 y: y
47059             }, true);
47060             if (rotate) {
47061                 label.setAttributes({
47062                     rotate: {
47063                         x: x,
47064                         y: y,
47065                         degrees: 270
47066                     }
47067                 }, true);
47068             }
47069         }
47070         
47071         if (animate) {
47072             me.onAnimate(label, { to: finalAttr });
47073         }
47074         else {
47075             label.setAttributes(Ext.apply(finalAttr, {
47076                 hidden: false
47077             }), true);
47078         }
47079     },
47080
47081     
47082     getLabelSize: function(value) {
47083         var tester = this.testerLabel,
47084             config = this.label,
47085             endLabelStyle = Ext.apply({}, config, this.seriesLabelStyle || {}),
47086             rotated = config.orientation === 'vertical',
47087             bbox, w, h,
47088             undef;
47089         if (!tester) {
47090             tester = this.testerLabel = this.chart.surface.add(Ext.apply({
47091                 type: 'text',
47092                 opacity: 0
47093             }, endLabelStyle));
47094         }
47095         tester.setAttributes({
47096             text: value
47097         }, true);
47098
47099         
47100         bbox = tester.getBBox();
47101         w = bbox.width;
47102         h = bbox.height;
47103         return {
47104             width: rotated ? h : w,
47105             height: rotated ? w : h
47106         };
47107     },
47108
47109     
47110     onAnimate: function(sprite, attr) {
47111         sprite.show();
47112         return this.callParent(arguments);
47113     },
47114     
47115     isItemInPoint: function(x, y, item) {
47116         var bbox = item.sprite.getBBox();
47117         return bbox.x <= x && bbox.y <= y
47118             && (bbox.x + bbox.width) >= x
47119             && (bbox.y + bbox.height) >= y;
47120     },
47121     
47122     
47123     hideAll: function() {
47124         var axes = this.chart.axes;
47125         if (!isNaN(this._index)) {
47126             if (!this.__excludes) {
47127                 this.__excludes = [];
47128             }
47129             this.__excludes[this._index] = true;
47130             this.drawSeries();
47131             axes.each(function(axis) {
47132                 axis.drawAxis();
47133             });
47134         }
47135     },
47136
47137     
47138     showAll: function() {
47139         var axes = this.chart.axes;
47140         if (!isNaN(this._index)) {
47141             if (!this.__excludes) {
47142                 this.__excludes = [];
47143             }
47144             this.__excludes[this._index] = false;
47145             this.drawSeries();
47146             axes.each(function(axis) {
47147                 axis.drawAxis();
47148             });
47149         }
47150     },
47151     
47152     
47153     getLegendColor: function(index) {
47154         var me = this;
47155         return me.colorArrayStyle[index % me.colorArrayStyle.length];
47156     }
47157 });
47158
47159 Ext.define('Ext.chart.series.Column', {
47160
47161     
47162
47163     alternateClassName: ['Ext.chart.ColumnSeries', 'Ext.chart.ColumnChart', 'Ext.chart.StackedColumnChart'],
47164
47165     extend: 'Ext.chart.series.Bar',
47166
47167     
47168
47169     type: 'column',
47170     alias: 'series.column',
47171
47172     column: true,
47173
47174     
47175     xPadding: 10,
47176
47177     
47178     yPadding: 0
47179 });
47180
47181 Ext.define('Ext.chart.series.Gauge', {
47182
47183     
47184
47185     extend: 'Ext.chart.series.Series',
47186
47187     
47188
47189     type: "gauge",
47190     alias: 'series.gauge',
47191
47192     rad: Math.PI / 180,
47193
47194     
47195     highlightDuration: 150,
47196
47197     
47198     angleField: false,
47199
47200     
47201     needle: false,
47202     
47203     
47204     donut: false,
47205
47206     
47207     showInLegend: false,
47208
47209     
47210     style: {},
47211     
47212     constructor: function(config) {
47213         this.callParent(arguments);
47214         var me = this,
47215             chart = me.chart,
47216             surface = chart.surface,
47217             store = chart.store,
47218             shadow = chart.shadow, i, l, cfg;
47219         Ext.apply(me, config, {
47220             shadowAttributes: [{
47221                 "stroke-width": 6,
47222                 "stroke-opacity": 1,
47223                 stroke: 'rgb(200, 200, 200)',
47224                 translate: {
47225                     x: 1.2,
47226                     y: 2
47227                 }
47228             },
47229             {
47230                 "stroke-width": 4,
47231                 "stroke-opacity": 1,
47232                 stroke: 'rgb(150, 150, 150)',
47233                 translate: {
47234                     x: 0.9,
47235                     y: 1.5
47236                 }
47237             },
47238             {
47239                 "stroke-width": 2,
47240                 "stroke-opacity": 1,
47241                 stroke: 'rgb(100, 100, 100)',
47242                 translate: {
47243                     x: 0.6,
47244                     y: 1
47245                 }
47246             }]
47247         });
47248         me.group = surface.getGroup(me.seriesId);
47249         if (shadow) {
47250             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
47251                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
47252             }
47253         }
47254         surface.customAttributes.segment = function(opt) {
47255             return me.getSegment(opt);
47256         };
47257     },
47258     
47259     //@private updates some onbefore render parameters.
47260
47261     initialize: function() {
47262         var me = this,
47263             store = me.chart.substore || me.chart.store;
47264         
47265         me.yField = [];
47266         if (me.label.field) {
47267             store.each(function(rec) {
47268                 me.yField.push(rec.get(me.label.field));
47269             });
47270         }
47271     },
47272
47273     
47274     getSegment: function(opt) {
47275         var me = this,
47276             rad = me.rad,
47277             cos = Math.cos,
47278             sin = Math.sin,
47279             abs = Math.abs,
47280             x = me.centerX,
47281             y = me.centerY,
47282             x1 = 0, x2 = 0, x3 = 0, x4 = 0,
47283             y1 = 0, y2 = 0, y3 = 0, y4 = 0,
47284             delta = 1e-2,
47285             r = opt.endRho - opt.startRho,
47286             startAngle = opt.startAngle,
47287             endAngle = opt.endAngle,
47288             midAngle = (startAngle + endAngle) / 2 * rad,
47289             margin = opt.margin || 0,
47290             flag = abs(endAngle - startAngle) > 180,
47291             a1 = Math.min(startAngle, endAngle) * rad,
47292             a2 = Math.max(startAngle, endAngle) * rad,
47293             singleSlice = false;
47294
47295         x += margin * cos(midAngle);
47296         y += margin * sin(midAngle);
47297
47298         x1 = x + opt.startRho * cos(a1);
47299         y1 = y + opt.startRho * sin(a1);
47300
47301         x2 = x + opt.endRho * cos(a1);
47302         y2 = y + opt.endRho * sin(a1);
47303
47304         x3 = x + opt.startRho * cos(a2);
47305         y3 = y + opt.startRho * sin(a2);
47306
47307         x4 = x + opt.endRho * cos(a2);
47308         y4 = y + opt.endRho * sin(a2);
47309
47310         if (abs(x1 - x3) <= delta && abs(y1 - y3) <= delta) {
47311             singleSlice = true;
47312         }
47313         
47314         if (singleSlice) {
47315             return {
47316                 path: [
47317                 ["M", x1, y1],
47318                 ["L", x2, y2],
47319                 ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
47320                 ["Z"]]
47321             };
47322         } else {
47323             return {
47324                 path: [
47325                 ["M", x1, y1],
47326                 ["L", x2, y2],
47327                 ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
47328                 ["L", x3, y3],
47329                 ["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
47330                 ["Z"]]
47331             };
47332         }
47333     },
47334
47335     
47336     calcMiddle: function(item) {
47337         var me = this,
47338             rad = me.rad,
47339             slice = item.slice,
47340             x = me.centerX,
47341             y = me.centerY,
47342             startAngle = slice.startAngle,
47343             endAngle = slice.endAngle,
47344             radius = Math.max(('rho' in slice) ? slice.rho: me.radius, me.label.minMargin),
47345             donut = +me.donut,
47346             a1 = Math.min(startAngle, endAngle) * rad,
47347             a2 = Math.max(startAngle, endAngle) * rad,
47348             midAngle = -(a1 + (a2 - a1) / 2),
47349             xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle),
47350             ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle);
47351
47352         item.middle = {
47353             x: xm,
47354             y: ym
47355         };
47356     },
47357
47358     
47359     drawSeries: function() {
47360         var me = this,
47361             chart = me.chart,
47362             store = chart.substore || chart.store,
47363             group = me.group,
47364             animate = me.chart.animate,
47365             axis = me.chart.axes.get(0),
47366             minimum = axis && axis.minimum || me.minimum || 0,
47367             maximum = axis && axis.maximum || me.maximum || 0,
47368             field = me.angleField || me.field || me.xField,
47369             surface = chart.surface,
47370             chartBBox = chart.chartBBox,
47371             rad = me.rad,
47372             donut = +me.donut,
47373             values = {},
47374             items = [],
47375             seriesStyle = me.seriesStyle,
47376             seriesLabelStyle = me.seriesLabelStyle,
47377             colorArrayStyle = me.colorArrayStyle,
47378             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
47379             gutterX = chart.maxGutter[0],
47380             gutterY = chart.maxGutter[1],
47381             cos = Math.cos,
47382             sin = Math.sin,
47383             rendererAttributes, centerX, centerY, slice, slices, sprite, value,
47384             item, ln, record, i, j, startAngle, endAngle, middleAngle, sliceLength, path,
47385             p, spriteOptions, bbox, splitAngle, sliceA, sliceB;
47386         
47387         Ext.apply(seriesStyle, me.style || {});
47388
47389         me.setBBox();
47390         bbox = me.bbox;
47391
47392         
47393         if (me.colorSet) {
47394             colorArrayStyle = me.colorSet;
47395             colorArrayLength = colorArrayStyle.length;
47396         }
47397         
47398         
47399         if (!store || !store.getCount()) {
47400             return;
47401         }
47402         
47403         centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
47404         centerY = me.centerY = chartBBox.y + chartBBox.height;
47405         me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
47406         me.slices = slices = [];
47407         me.items = items = [];
47408         
47409         if (!me.value) {
47410             record = store.getAt(0);
47411             me.value = record.get(field);
47412         }
47413         
47414         value = me.value;
47415         if (me.needle) {
47416             sliceA = {
47417                 series: me,
47418                 value: value,
47419                 startAngle: -180,
47420                 endAngle: 0,
47421                 rho: me.radius
47422             };
47423             splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
47424             slices.push(sliceA);
47425         } else {
47426             splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
47427             sliceA = {
47428                 series: me,
47429                 value: value,
47430                 startAngle: -180,
47431                 endAngle: splitAngle,
47432                 rho: me.radius
47433             };
47434             sliceB = {
47435                 series: me,
47436                 value: me.maximum - value,
47437                 startAngle: splitAngle,
47438                 endAngle: 0,
47439                 rho: me.radius
47440             };
47441             slices.push(sliceA, sliceB);
47442         }
47443         
47444         
47445         for (i = 0, ln = slices.length; i < ln; i++) {
47446             slice = slices[i];
47447             sprite = group.getAt(i);
47448             
47449             rendererAttributes = Ext.apply({
47450                 segment: {
47451                     startAngle: slice.startAngle,
47452                     endAngle: slice.endAngle,
47453                     margin: 0,
47454                     rho: slice.rho,
47455                     startRho: slice.rho * +donut / 100,
47456                     endRho: slice.rho
47457                 } 
47458             }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
47459
47460             item = Ext.apply({},
47461             rendererAttributes.segment, {
47462                 slice: slice,
47463                 series: me,
47464                 storeItem: record,
47465                 index: i
47466             });
47467             items[i] = item;
47468             
47469             if (!sprite) {
47470                 spriteOptions = Ext.apply({
47471                     type: "path",
47472                     group: group
47473                 }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {}));
47474                 sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
47475             }
47476             slice.sprite = slice.sprite || [];
47477             item.sprite = sprite;
47478             slice.sprite.push(sprite);
47479             if (animate) {
47480                 rendererAttributes = me.renderer(sprite, record, rendererAttributes, i, store);
47481                 sprite._to = rendererAttributes;
47482                 me.onAnimate(sprite, {
47483                     to: rendererAttributes
47484                 });
47485             } else {
47486                 rendererAttributes = me.renderer(sprite, record, Ext.apply(rendererAttributes, {
47487                     hidden: false
47488                 }), i, store);
47489                 sprite.setAttributes(rendererAttributes, true);
47490             }
47491         }
47492         
47493         if (me.needle) {
47494             splitAngle = splitAngle * Math.PI / 180;
47495             
47496             if (!me.needleSprite) {
47497                 me.needleSprite = me.chart.surface.add({
47498                     type: 'path',
47499                     path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
47500                                 centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
47501                            'L', centerX + me.radius * cos(splitAngle),
47502                                 centerY + -Math.abs(me.radius * sin(splitAngle))],
47503                     'stroke-width': 4,
47504                     'stroke': '#222'
47505                 });
47506             } else {
47507                 if (animate) {
47508                     me.onAnimate(me.needleSprite, {
47509                         to: {
47510                         path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
47511                                     centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
47512                                'L', centerX + me.radius * cos(splitAngle),
47513                                     centerY + -Math.abs(me.radius * sin(splitAngle))]
47514                         }
47515                     });
47516                 } else {
47517                     me.needleSprite.setAttributes({
47518                         type: 'path',
47519                         path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
47520                                     centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
47521                                'L', centerX + me.radius * cos(splitAngle),
47522                                     centerY + -Math.abs(me.radius * sin(splitAngle))]
47523                     });
47524                 }
47525             }
47526             me.needleSprite.setAttributes({
47527                 hidden: false    
47528             }, true);
47529         }
47530         
47531         delete me.value;
47532     },
47533     
47534     
47535     setValue: function (value) {
47536         this.value = value;
47537         this.drawSeries();
47538     },
47539
47540     
47541     onCreateLabel: function(storeItem, item, i, display) {},
47542
47543     
47544     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {},
47545
47546     
47547     onPlaceCallout: function() {},
47548
47549     
47550     onAnimate: function(sprite, attr) {
47551         sprite.show();
47552         return this.callParent(arguments);
47553     },
47554
47555     isItemInPoint: function(x, y, item, i) {
47556         return false;
47557     },
47558     
47559     
47560     showAll: function() {
47561         if (!isNaN(this._index)) {
47562             this.__excludes[this._index] = false;
47563             this.drawSeries();
47564         }
47565     },
47566     
47567     
47568     getLegendColor: function(index) {
47569         var me = this;
47570         return me.colorArrayStyle[index % me.colorArrayStyle.length];
47571     }
47572 });
47573
47574
47575
47576 Ext.define('Ext.chart.series.Line', {
47577
47578     
47579
47580     extend: 'Ext.chart.series.Cartesian',
47581
47582     alternateClassName: ['Ext.chart.LineSeries', 'Ext.chart.LineChart'],
47583
47584     requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.draw.Draw', 'Ext.fx.Anim'],
47585
47586     
47587
47588     type: 'line',
47589     
47590     alias: 'series.line',
47591     
47592     
47593
47594     
47595     selectionTolerance: 20,
47596     
47597     
47598     showMarkers: true,
47599
47600     
47601     markerConfig: {},
47602
47603     
47604     style: {},
47605     
47606     
47607     smooth: false,
47608
47609     
47610     fill: false,
47611
47612     constructor: function(config) {
47613         this.callParent(arguments);
47614         var me = this,
47615             surface = me.chart.surface,
47616             shadow = me.chart.shadow,
47617             i, l;
47618         Ext.apply(me, config, {
47619             highlightCfg: {
47620                 'stroke-width': 3
47621             },
47622             shadowAttributes: [{
47623                 "stroke-width": 6,
47624                 "stroke-opacity": 0.05,
47625                 stroke: 'rgb(0, 0, 0)',
47626                 translate: {
47627                     x: 1,
47628                     y: 1
47629                 }
47630             }, {
47631                 "stroke-width": 4,
47632                 "stroke-opacity": 0.1,
47633                 stroke: 'rgb(0, 0, 0)',
47634                 translate: {
47635                     x: 1,
47636                     y: 1
47637                 }
47638             }, {
47639                 "stroke-width": 2,
47640                 "stroke-opacity": 0.15,
47641                 stroke: 'rgb(0, 0, 0)',
47642                 translate: {
47643                     x: 1,
47644                     y: 1
47645                 }
47646             }]
47647         });
47648         me.group = surface.getGroup(me.seriesId);
47649         if (me.showMarkers) {
47650             me.markerGroup = surface.getGroup(me.seriesId + '-markers');
47651         }
47652         if (shadow) {
47653             for (i = 0, l = this.shadowAttributes.length; i < l; i++) {
47654                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
47655             }
47656         }
47657     },
47658     
47659     
47660     shrink: function(xValues, yValues, size) {
47661         
47662         var len = xValues.length,
47663             ratio = Math.floor(len / size),
47664             i = 1,
47665             xSum = 0,
47666             ySum = 0,
47667             xRes = [xValues[0]],
47668             yRes = [yValues[0]];
47669         
47670         for (; i < len; ++i) {
47671             xSum += xValues[i] || 0;
47672             ySum += yValues[i] || 0;
47673             if (i % ratio == 0) {
47674                 xRes.push(xSum/ratio);
47675                 yRes.push(ySum/ratio);
47676                 xSum = 0;
47677                 ySum = 0;
47678             }
47679         }
47680         return {
47681             x: xRes,
47682             y: yRes
47683         };
47684     },
47685
47686     
47687     drawSeries: function() {
47688         var me = this,
47689             chart = me.chart,
47690             store = chart.substore || chart.store,
47691             surface = chart.surface,
47692             chartBBox = chart.chartBBox,
47693             bbox = {},
47694             group = me.group,
47695             gutterX = chart.maxGutter[0],
47696             gutterY = chart.maxGutter[1],
47697             showMarkers = me.showMarkers,
47698             markerGroup = me.markerGroup,
47699             enableShadows = chart.shadow,
47700             shadowGroups = me.shadowGroups,
47701             shadowAttributes = this.shadowAttributes,
47702             lnsh = shadowGroups.length,
47703             dummyPath = ["M"],
47704             path = ["M"],
47705             markerIndex = chart.markerIndex,
47706             axes = [].concat(me.axis),
47707             shadowGroup,
47708             shadowBarAttr,
47709             xValues = [],
47710             yValues = [],
47711             numericAxis = true,
47712             axisCount = 0,
47713             onbreak = false,
47714             markerStyle = me.markerStyle,
47715             seriesStyle = me.seriesStyle,
47716             seriesLabelStyle = me.seriesLabelStyle,
47717             colorArrayStyle = me.colorArrayStyle,
47718             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
47719             posHash = {
47720                 'left': 'right',
47721                 'right': 'left',
47722                 'top': 'bottom',
47723                 'bottom': 'top'
47724             },
47725             seriesIdx = me.seriesIdx, shadows, shadow, shindex, fromPath, fill, fillPath, rendererAttributes,
47726             x, y, prevX, prevY, firstY, markerCount, i, j, ln, axis, ends, marker, markerAux, item, xValue,
47727             yValue, coords, xScale, yScale, minX, maxX, minY, maxY, line, animation, endMarkerStyle,
47728             endLineStyle, type, props, firstMarker, count;
47729         
47730         
47731         if (!store || !store.getCount()) {
47732             return;
47733         }
47734         
47735         
47736         endMarkerStyle = Ext.apply(markerStyle, me.markerConfig);
47737         type = endMarkerStyle.type;
47738         delete endMarkerStyle.type;
47739         endLineStyle = Ext.apply(seriesStyle, me.style);
47740         
47741         
47742         if (!endLineStyle['stroke-width']) {
47743             endLineStyle['stroke-width'] = 0.5;
47744         }
47745         
47746         
47747         if (markerIndex && markerGroup && markerGroup.getCount()) {
47748             for (i = 0; i < markerIndex; i++) {
47749                 marker = markerGroup.getAt(i);
47750                 markerGroup.remove(marker);
47751                 markerGroup.add(marker);
47752                 markerAux = markerGroup.getAt(markerGroup.getCount() - 2);
47753                 marker.setAttributes({
47754                     x: 0,
47755                     y: 0,
47756                     translate: {
47757                         x: markerAux.attr.translation.x,
47758                         y: markerAux.attr.translation.y
47759                     }
47760                 }, true);
47761             }
47762         }
47763         
47764         me.unHighlightItem();
47765         me.cleanHighlights();
47766
47767         me.setBBox();
47768         bbox = me.bbox;
47769
47770         me.clipRect = [bbox.x, bbox.y, bbox.width, bbox.height];
47771
47772         chart.axes.each(function(axis) {
47773             
47774             
47775             
47776             
47777             if (axis.position == me.axis || axis.position != posHash[me.axis]) {
47778                 axisCount++;
47779                 if (axis.type != 'Numeric') {
47780                     numericAxis = false;
47781                     return;
47782                 }
47783                 numericAxis = (numericAxis && axis.type == 'Numeric');
47784                 if (axis) {
47785                     ends = axis.calcEnds();
47786                     if (axis.position == 'top' || axis.position == 'bottom') {
47787                         minX = ends.from;
47788                         maxX = ends.to;
47789                     }
47790                     else {
47791                         minY = ends.from;
47792                         maxY = ends.to;
47793                     }
47794                 }
47795             }
47796         });
47797         
47798         
47799         
47800         
47801         if (numericAxis && axisCount == 1) {
47802             numericAxis = false;
47803         }
47804         
47805         
47806         
47807         
47808         if (me.xField && !Ext.isNumber(minX)) {
47809             if (me.axis == 'bottom' || me.axis == 'top') {
47810                 axis = Ext.create('Ext.chart.axis.Axis', {
47811                     chart: chart,
47812                     fields: [].concat(me.xField)
47813                 }).calcEnds();
47814                 minX = axis.from;
47815                 maxX = axis.to;
47816             } else if (numericAxis) {
47817                 axis = Ext.create('Ext.chart.axis.Axis', {
47818                     chart: chart,
47819                     fields: [].concat(me.xField),
47820                     forceMinMax: true
47821                 }).calcEnds();
47822                 minX = axis.from;
47823                 maxX = axis.to;
47824             }
47825         }
47826         
47827         if (me.yField && !Ext.isNumber(minY)) {
47828             if (me.axis == 'right' || me.axis == 'left') {
47829                 axis = Ext.create('Ext.chart.axis.Axis', {
47830                     chart: chart,
47831                     fields: [].concat(me.yField)
47832                 }).calcEnds();
47833                 minY = axis.from;
47834                 maxY = axis.to;
47835             } else if (numericAxis) {
47836                 axis = Ext.create('Ext.chart.axis.Axis', {
47837                     chart: chart,
47838                     fields: [].concat(me.yField),
47839                     forceMinMax: true
47840                 }).calcEnds();
47841                 minY = axis.from;
47842                 maxY = axis.to;
47843             }
47844         }
47845         
47846         if (isNaN(minX)) {
47847             minX = 0;
47848             xScale = bbox.width / (store.getCount() - 1);
47849         }
47850         else {
47851             xScale = bbox.width / (maxX - minX);
47852         }
47853
47854         if (isNaN(minY)) {
47855             minY = 0;
47856             yScale = bbox.height / (store.getCount() - 1);
47857         } 
47858         else {
47859             yScale = bbox.height / (maxY - minY);
47860         }
47861         
47862         store.each(function(record, i) {
47863             xValue = record.get(me.xField);
47864             yValue = record.get(me.yField);
47865             
47866             if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
47867                 if (Ext.isDefined(Ext.global.console)) {
47868                     Ext.global.console.warn("[Ext.chart.series.Line]  Skipping a store element with an undefined value at ", record, xValue, yValue);
47869                 }
47870                 return;
47871             }
47872             
47873             if (typeof xValue == 'string' || typeof xValue == 'object'
47874                 
47875                 || (me.axis != 'top' && me.axis != 'bottom' && !numericAxis)) {
47876                 xValue = i;
47877             }
47878             if (typeof yValue == 'string' || typeof yValue == 'object'
47879                 
47880                 || (me.axis != 'left' && me.axis != 'right' && !numericAxis)) {
47881                 yValue = i;
47882             }
47883             xValues.push(xValue);
47884             yValues.push(yValue);
47885         }, me);
47886
47887         ln = xValues.length;
47888         if (ln > bbox.width) {
47889             coords = me.shrink(xValues, yValues, bbox.width);
47890             xValues = coords.x;
47891             yValues = coords.y;
47892         }
47893
47894         me.items = [];
47895
47896         count = 0;
47897         ln = xValues.length;
47898         for (i = 0; i < ln; i++) {
47899             xValue = xValues[i];
47900             yValue = yValues[i];
47901             if (yValue === false) {
47902                 if (path.length == 1) {
47903                     path = [];
47904                 }
47905                 onbreak = true;
47906                 me.items.push(false);
47907                 continue;
47908             } else {
47909                 x = (bbox.x + (xValue - minX) * xScale).toFixed(2);
47910                 y = ((bbox.y + bbox.height) - (yValue - minY) * yScale).toFixed(2);
47911                 if (onbreak) {
47912                     onbreak = false;
47913                     path.push('M');
47914                 } 
47915                 path = path.concat([x, y]);
47916             }
47917             if ((typeof firstY == 'undefined') && (typeof y != 'undefined')) {
47918                 firstY = y;
47919             }
47920             
47921             if (!me.line || chart.resizing) {
47922                 dummyPath = dummyPath.concat([x, bbox.y + bbox.height / 2]);
47923             }
47924
47925             
47926             if (chart.animate && chart.resizing && me.line) {
47927                 me.line.setAttributes({
47928                     path: dummyPath
47929                 }, true);
47930                 if (me.fillPath) {
47931                     me.fillPath.setAttributes({
47932                         path: dummyPath,
47933                         opacity: 0.2
47934                     }, true);
47935                 }
47936                 if (me.line.shadows) {
47937                     shadows = me.line.shadows;
47938                     for (j = 0, lnsh = shadows.length; j < lnsh; j++) {
47939                         shadow = shadows[j];
47940                         shadow.setAttributes({
47941                             path: dummyPath
47942                         }, true);
47943                     }
47944                 }
47945             }
47946             if (showMarkers) {
47947                 marker = markerGroup.getAt(count++);
47948                 if (!marker) {
47949                     marker = Ext.chart.Shape[type](surface, Ext.apply({
47950                         group: [group, markerGroup],
47951                         x: 0, y: 0,
47952                         translate: {
47953                             x: prevX || x, 
47954                             y: prevY || (bbox.y + bbox.height / 2)
47955                         },
47956                         value: '"' + xValue + ', ' + yValue + '"'
47957                     }, endMarkerStyle));
47958                     marker._to = {
47959                         translate: {
47960                             x: x,
47961                             y: y
47962                         }
47963                     };
47964                 } else {
47965                     marker.setAttributes({
47966                         value: '"' + xValue + ', ' + yValue + '"',
47967                         x: 0, y: 0,
47968                         hidden: false
47969                     }, true);
47970                     marker._to = {
47971                         translate: {
47972                             x: x, y: y
47973                         }
47974                     };
47975                 }
47976             }
47977             me.items.push({
47978                 series: me,
47979                 value: [xValue, yValue],
47980                 point: [x, y],
47981                 sprite: marker,
47982                 storeItem: store.getAt(i)
47983             });
47984             prevX = x;
47985             prevY = y;
47986         }
47987         
47988         if (path.length <= 1) {
47989             
47990             return;    
47991         }
47992         
47993         if (me.smooth) {
47994             path = Ext.draw.Draw.smooth(path, 6);
47995         }
47996         
47997         
47998         if (chart.markerIndex && me.previousPath) {
47999             fromPath = me.previousPath;
48000             fromPath.splice(1, 2);
48001         } else {
48002             fromPath = path;
48003         }
48004
48005         
48006         if (!me.line) {
48007             me.line = surface.add(Ext.apply({
48008                 type: 'path',
48009                 group: group,
48010                 path: dummyPath,
48011                 stroke: endLineStyle.stroke || endLineStyle.fill
48012             }, endLineStyle || {}));
48013             
48014             me.line.setAttributes({
48015                 fill: 'none'
48016             });
48017             if (!endLineStyle.stroke && colorArrayLength) {
48018                 me.line.setAttributes({
48019                     stroke: colorArrayStyle[seriesIdx % colorArrayLength]
48020                 }, true);
48021             }
48022             if (enableShadows) {
48023                 
48024                 shadows = me.line.shadows = [];                
48025                 for (shindex = 0; shindex < lnsh; shindex++) {
48026                     shadowBarAttr = shadowAttributes[shindex];
48027                     shadowBarAttr = Ext.apply({}, shadowBarAttr, { path: dummyPath });
48028                     shadow = chart.surface.add(Ext.apply({}, {
48029                         type: 'path',
48030                         group: shadowGroups[shindex]
48031                     }, shadowBarAttr));
48032                     shadows.push(shadow);
48033                 }
48034             }
48035         }
48036         if (me.fill) {
48037             fillPath = path.concat([
48038                 ["L", x, bbox.y + bbox.height],
48039                 ["L", bbox.x, bbox.y + bbox.height],
48040                 ["L", bbox.x, firstY]
48041             ]);
48042             if (!me.fillPath) {
48043                 me.fillPath = surface.add({
48044                     group: group,
48045                     type: 'path',
48046                     opacity: endLineStyle.opacity || 0.3,
48047                     fill: colorArrayStyle[seriesIdx % colorArrayLength] || endLineStyle.fill,
48048                     path: dummyPath
48049                 });
48050             }
48051         }
48052         markerCount = showMarkers && markerGroup.getCount();
48053         if (chart.animate) {
48054             fill = me.fill;
48055             line = me.line;
48056             
48057             rendererAttributes = me.renderer(line, false, { path: path }, i, store);
48058             Ext.apply(rendererAttributes, endLineStyle || {}, {
48059                 stroke: endLineStyle.stroke || endLineStyle.fill
48060             });
48061             
48062             delete rendererAttributes.fill;
48063             if (chart.markerIndex && me.previousPath) {
48064                 me.animation = animation = me.onAnimate(line, {
48065                     to: rendererAttributes,
48066                     from: {
48067                         path: fromPath
48068                     }
48069                 });
48070             } else {
48071                 me.animation = animation = me.onAnimate(line, {
48072                     to: rendererAttributes
48073                 });
48074             }
48075             
48076             if (enableShadows) {
48077                 shadows = line.shadows;
48078                 for(j = 0; j < lnsh; j++) {
48079                     if (chart.markerIndex && me.previousPath) {
48080                         me.onAnimate(shadows[j], {
48081                             to: { path: path },
48082                             from: { path: fromPath }
48083                         });
48084                     } else {
48085                         me.onAnimate(shadows[j], {
48086                             to: { path: path }
48087                         });
48088                     }
48089                 }
48090             }
48091             
48092             if (fill) {
48093                 me.onAnimate(me.fillPath, {
48094                     to: Ext.apply({}, {
48095                         path: fillPath,
48096                         fill: colorArrayStyle[seriesIdx % colorArrayLength] || endLineStyle.fill
48097                     }, endLineStyle || {})
48098                 });
48099             }
48100             
48101             if (showMarkers) {
48102                 count = 0;
48103                 for(i = 0; i < ln; i++) {
48104                     if (me.items[i]) {
48105                         item = markerGroup.getAt(count++);
48106                         if (item) {
48107                             rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
48108                             me.onAnimate(item, {
48109                                 to: Ext.apply(rendererAttributes, endMarkerStyle || {})
48110                             });
48111                         }
48112                     } 
48113                 }
48114                 for(; count < markerCount; count++) {
48115                     item = markerGroup.getAt(count);
48116                     item.hide(true);
48117                 }
48118             }
48119         } else {
48120             rendererAttributes = me.renderer(me.line, false, { path: path, hidden: false }, i, store);
48121             Ext.apply(rendererAttributes, endLineStyle || {}, {
48122                 stroke: endLineStyle.stroke || endLineStyle.fill
48123             });
48124             
48125             delete rendererAttributes.fill;
48126             me.line.setAttributes(rendererAttributes, true);
48127             
48128             if (enableShadows) {
48129                 shadows = me.line.shadows;
48130                 for(j = 0; j < lnsh; j++) {
48131                     shadows[j].setAttributes({
48132                         path: path
48133                     }, true);
48134                 }
48135             }
48136             if (me.fill) {
48137                 me.fillPath.setAttributes({
48138                     path: fillPath
48139                 }, true);
48140             }
48141             if (showMarkers) {
48142                 count = 0;
48143                 for(i = 0; i < ln; i++) {
48144                     if (me.items[i]) {
48145                         item = markerGroup.getAt(count++);
48146                         if (item) {
48147                             rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store);
48148                             item.setAttributes(Ext.apply(endMarkerStyle || {}, rendererAttributes || {}), true);
48149                         }
48150                     } 
48151                 }
48152                 for(; count < markerCount; count++) {
48153                     item = markerGroup.getAt(count);
48154                     item.hide(true);
48155                 }
48156             }
48157         }
48158
48159         if (chart.markerIndex) {
48160             path.splice(1, 0, path[1], path[2]);
48161             me.previousPath = path;
48162         }
48163         me.renderLabels();
48164         me.renderCallouts();
48165     },
48166     
48167     
48168     onCreateLabel: function(storeItem, item, i, display) {
48169         var me = this,
48170             group = me.labelsGroup,
48171             config = me.label,
48172             bbox = me.bbox,
48173             endLabelStyle = Ext.apply(config, me.seriesLabelStyle);
48174
48175         return me.chart.surface.add(Ext.apply({
48176             'type': 'text',
48177             'text-anchor': 'middle',
48178             'group': group,
48179             'x': item.point[0],
48180             'y': bbox.y + bbox.height / 2
48181         }, endLabelStyle || {}));
48182     },
48183     
48184     
48185     onPlaceLabel: function(label, storeItem, item, i, display, animate) {
48186         var me = this,
48187             chart = me.chart,
48188             resizing = chart.resizing,
48189             config = me.label,
48190             format = config.renderer,
48191             field = config.field,
48192             bbox = me.bbox,
48193             x = item.point[0],
48194             y = item.point[1],
48195             radius = item.sprite.attr.radius,
48196             bb, width, height;
48197         
48198         label.setAttributes({
48199             text: format(storeItem.get(field)),
48200             hidden: true
48201         }, true);
48202         
48203         if (display == 'rotate') {
48204             label.setAttributes({
48205                 'text-anchor': 'start',
48206                 'rotation': {
48207                     x: x,
48208                     y: y,
48209                     degrees: -45
48210                 }
48211             }, true);
48212             
48213             bb = label.getBBox();
48214             width = bb.width;
48215             height = bb.height;
48216             x = x < bbox.x? bbox.x : x;
48217             x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
48218             y = (y - height < bbox.y)? bbox.y + height : y;
48219         
48220         } else if (display == 'under' || display == 'over') {
48221             
48222             bb = item.sprite.getBBox();
48223             bb.width = bb.width || (radius * 2);
48224             bb.height = bb.height || (radius * 2);
48225             y = y + (display == 'over'? -bb.height : bb.height);
48226             
48227             bb = label.getBBox();
48228             width = bb.width/2;
48229             height = bb.height/2;
48230             x = x - width < bbox.x? bbox.x + width : x;
48231             x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
48232             y = y - height < bbox.y? bbox.y + height : y;
48233             y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
48234         }
48235         
48236         if (me.chart.animate && !me.chart.resizing) {
48237             label.show(true);
48238             me.onAnimate(label, {
48239                 to: {
48240                     x: x,
48241                     y: y
48242                 }
48243             });
48244         } else {
48245             label.setAttributes({
48246                 x: x,
48247                 y: y
48248             }, true);
48249             if (resizing) {
48250                 me.animation.on('afteranimate', function() {
48251                     label.show(true);
48252                 });
48253             } else {
48254                 label.show(true);
48255             }
48256         }
48257     },
48258
48259     //@private Overriding highlights.js highlightItem method.
48260
48261     highlightItem: function() {
48262         var me = this;
48263         me.callParent(arguments);
48264         if (this.line && !this.highlighted) {
48265             if (!('__strokeWidth' in this.line)) {
48266                 this.line.__strokeWidth = this.line.attr['stroke-width'] || 0;
48267             }
48268             if (this.line.__anim) {
48269                 this.line.__anim.paused = true;
48270             }
48271             this.line.__anim = Ext.create('Ext.fx.Anim', {
48272                 target: this.line,
48273                 to: {
48274                     'stroke-width': this.line.__strokeWidth + 3
48275                 }
48276             });
48277             this.highlighted = true;
48278         }
48279     },
48280
48281     //@private Overriding highlights.js unHighlightItem method.
48282
48283     unHighlightItem: function() {
48284         var me = this;
48285         me.callParent(arguments);
48286         if (this.line && this.highlighted) {
48287             this.line.__anim = Ext.create('Ext.fx.Anim', {
48288                 target: this.line,
48289                 to: {
48290                     'stroke-width': this.line.__strokeWidth
48291                 }
48292             });
48293             this.highlighted = false;
48294         }
48295     },
48296
48297     //@private called when a callout needs to be placed.
48298
48299     onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) {
48300         if (!display) {
48301             return;
48302         }
48303         
48304         var me = this,
48305             chart = me.chart,
48306             surface = chart.surface,
48307             resizing = chart.resizing,
48308             config = me.callouts,
48309             items = me.items,
48310             prev = i == 0? false : items[i -1].point,
48311             next = (i == items.length -1)? false : items[i +1].point,
48312             cur = [+item.point[0], +item.point[1]],
48313             dir, norm, normal, a, aprev, anext,
48314             offsetFromViz = config.offsetFromViz || 30,
48315             offsetToSide = config.offsetToSide || 10,
48316             offsetBox = config.offsetBox || 3,
48317             boxx, boxy, boxw, boxh,
48318             p, clipRect = me.clipRect,
48319             bbox = {
48320                 width: config.styles.width || 10,
48321                 height: config.styles.height || 10
48322             },
48323             x, y;
48324
48325         
48326         if (!prev) {
48327             prev = cur;
48328         }
48329         if (!next) {
48330             next = cur;
48331         }
48332         a = (next[1] - prev[1]) / (next[0] - prev[0]);
48333         aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]);
48334         anext = (next[1] - cur[1]) / (next[0] - cur[0]);
48335         
48336         norm = Math.sqrt(1 + a * a);
48337         dir = [1 / norm, a / norm];
48338         normal = [-dir[1], dir[0]];
48339         
48340         
48341         if (aprev > 0 && anext < 0 && normal[1] < 0
48342             || aprev < 0 && anext > 0 && normal[1] > 0) {
48343             normal[0] *= -1;
48344             normal[1] *= -1;
48345         } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0
48346                    || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) {
48347             normal[0] *= -1;
48348             normal[1] *= -1;
48349         }
48350         
48351         x = cur[0] + normal[0] * offsetFromViz;
48352         y = cur[1] + normal[1] * offsetFromViz;
48353
48354         
48355         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
48356         boxy = y - bbox.height /2 - offsetBox;
48357         boxw = bbox.width + 2 * offsetBox;
48358         boxh = bbox.height + 2 * offsetBox;
48359         
48360         
48361         
48362         if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
48363             normal[0] *= -1;
48364         }
48365         if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
48366             normal[1] *= -1;
48367         }
48368
48369         
48370         x = cur[0] + normal[0] * offsetFromViz;
48371         y = cur[1] + normal[1] * offsetFromViz;
48372         
48373         
48374         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
48375         boxy = y - bbox.height /2 - offsetBox;
48376         boxw = bbox.width + 2 * offsetBox;
48377         boxh = bbox.height + 2 * offsetBox;
48378         
48379         if (chart.animate) {
48380             
48381             me.onAnimate(callout.lines, {
48382                 to: {
48383                     path: ["M", cur[0], cur[1], "L", x, y, "Z"]
48384                 }
48385             });
48386             
48387             if (callout.panel) {
48388                 callout.panel.setPosition(boxx, boxy, true);
48389             }
48390         }
48391         else {
48392             
48393             callout.lines.setAttributes({
48394                 path: ["M", cur[0], cur[1], "L", x, y, "Z"]
48395             }, true);
48396             
48397             if (callout.panel) {
48398                 callout.panel.setPosition(boxx, boxy);
48399             }
48400         }
48401         for (p in callout) {
48402             callout[p].show(true);
48403         }
48404     },
48405     
48406     isItemInPoint: function(x, y, item, i) {
48407         var me = this,
48408             items = me.items,
48409             tolerance = me.selectionTolerance,
48410             result = null,
48411             prevItem,
48412             nextItem,
48413             prevPoint,
48414             nextPoint,
48415             ln,
48416             x1,
48417             y1,
48418             x2,
48419             y2,
48420             xIntersect,
48421             yIntersect,
48422             dist1, dist2, dist, midx, midy,
48423             sqrt = Math.sqrt, abs = Math.abs;
48424         
48425         nextItem = items[i];
48426         prevItem = i && items[i - 1];
48427         
48428         if (i >= ln) {
48429             prevItem = items[ln - 1];
48430         }
48431         prevPoint = prevItem && prevItem.point;
48432         nextPoint = nextItem && nextItem.point;
48433         x1 = prevItem ? prevPoint[0] : nextPoint[0] - tolerance;
48434         y1 = prevItem ? prevPoint[1] : nextPoint[1];
48435         x2 = nextItem ? nextPoint[0] : prevPoint[0] + tolerance;
48436         y2 = nextItem ? nextPoint[1] : prevPoint[1];
48437         dist1 = sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1));
48438         dist2 = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2));
48439         dist = Math.min(dist1, dist2);
48440         
48441         if (dist <= tolerance) {
48442             return dist == dist1? prevItem : nextItem;
48443         }
48444         return false;
48445     },
48446     
48447     
48448     toggleAll: function(show) {
48449         var me = this,
48450             i, ln, shadow, shadows;
48451         if (!show) {
48452             Ext.chart.series.Line.superclass.hideAll.call(me);
48453         }
48454         else {
48455             Ext.chart.series.Line.superclass.showAll.call(me);
48456         }
48457         if (me.line) {
48458             me.line.setAttributes({
48459                 hidden: !show
48460             }, true);
48461             
48462             if (me.line.shadows) {
48463                 for (i = 0, shadows = me.line.shadows, ln = shadows.length; i < ln; i++) {
48464                     shadow = shadows[i];
48465                     shadow.setAttributes({
48466                         hidden: !show
48467                     }, true);
48468                 }
48469             }
48470         }
48471         if (me.fillPath) {
48472             me.fillPath.setAttributes({
48473                 hidden: !show
48474             }, true);
48475         }
48476     },
48477     
48478     
48479     hideAll: function() {
48480         this.toggleAll(false);
48481     },
48482     
48483     
48484     showAll: function() {
48485         this.toggleAll(true);
48486     }
48487 });
48488
48489 Ext.define('Ext.chart.series.Pie', {
48490
48491     
48492
48493     alternateClassName: ['Ext.chart.PieSeries', 'Ext.chart.PieChart'],
48494
48495     extend: 'Ext.chart.series.Series',
48496
48497     
48498
48499     type: "pie",
48500     
48501     alias: 'series.pie',
48502
48503     rad: Math.PI / 180,
48504
48505     
48506     highlightDuration: 150,
48507
48508     
48509     angleField: false,
48510
48511     
48512     lengthField: false,
48513
48514     
48515     donut: false,
48516
48517     
48518     showInLegend: false,
48519
48520     
48521     
48522     
48523     style: {},
48524     
48525     constructor: function(config) {
48526         this.callParent(arguments);
48527         var me = this,
48528             chart = me.chart,
48529             surface = chart.surface,
48530             store = chart.store,
48531             shadow = chart.shadow, i, l, cfg;
48532         Ext.applyIf(me, {
48533             highlightCfg: {
48534                 segment: {
48535                     margin: 20
48536                 }
48537             }
48538         });
48539         Ext.apply(me, config, {            
48540             shadowAttributes: [{
48541                 "stroke-width": 6,
48542                 "stroke-opacity": 1,
48543                 stroke: 'rgb(200, 200, 200)',
48544                 translate: {
48545                     x: 1.2,
48546                     y: 2
48547                 }
48548             },
48549             {
48550                 "stroke-width": 4,
48551                 "stroke-opacity": 1,
48552                 stroke: 'rgb(150, 150, 150)',
48553                 translate: {
48554                     x: 0.9,
48555                     y: 1.5
48556                 }
48557             },
48558             {
48559                 "stroke-width": 2,
48560                 "stroke-opacity": 1,
48561                 stroke: 'rgb(100, 100, 100)',
48562                 translate: {
48563                     x: 0.6,
48564                     y: 1
48565                 }
48566             }]
48567         });
48568         me.group = surface.getGroup(me.seriesId);
48569         if (shadow) {
48570             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
48571                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
48572             }
48573         }
48574         surface.customAttributes.segment = function(opt) {
48575             return me.getSegment(opt);
48576         };
48577     },
48578     
48579     //@private updates some onbefore render parameters.
48580
48581     initialize: function() {
48582         var me = this,
48583             store = me.chart.substore || me.chart.store;
48584         
48585         me.yField = [];
48586         if (me.label.field) {
48587             store.each(function(rec) {
48588                 me.yField.push(rec.get(me.label.field));
48589             });
48590         }
48591     },
48592
48593     
48594     getSegment: function(opt) {
48595         var me = this,
48596             rad = me.rad,
48597             cos = Math.cos,
48598             sin = Math.sin,
48599             abs = Math.abs,
48600             x = me.centerX,
48601             y = me.centerY,
48602             x1 = 0, x2 = 0, x3 = 0, x4 = 0,
48603             y1 = 0, y2 = 0, y3 = 0, y4 = 0,
48604             delta = 1e-2,
48605             r = opt.endRho - opt.startRho,
48606             startAngle = opt.startAngle,
48607             endAngle = opt.endAngle,
48608             midAngle = (startAngle + endAngle) / 2 * rad,
48609             margin = opt.margin || 0,
48610             flag = abs(endAngle - startAngle) > 180,
48611             a1 = Math.min(startAngle, endAngle) * rad,
48612             a2 = Math.max(startAngle, endAngle) * rad,
48613             singleSlice = false;
48614
48615         x += margin * cos(midAngle);
48616         y += margin * sin(midAngle);
48617
48618         x1 = x + opt.startRho * cos(a1);
48619         y1 = y + opt.startRho * sin(a1);
48620
48621         x2 = x + opt.endRho * cos(a1);
48622         y2 = y + opt.endRho * sin(a1);
48623
48624         x3 = x + opt.startRho * cos(a2);
48625         y3 = y + opt.startRho * sin(a2);
48626
48627         x4 = x + opt.endRho * cos(a2);
48628         y4 = y + opt.endRho * sin(a2);
48629
48630         if (abs(x1 - x3) <= delta && abs(y1 - y3) <= delta) {
48631             singleSlice = true;
48632         }
48633         
48634         if (singleSlice) {
48635             return {
48636                 path: [
48637                 ["M", x1, y1],
48638                 ["L", x2, y2],
48639                 ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
48640                 ["Z"]]
48641             };
48642         } else {
48643             return {
48644                 path: [
48645                 ["M", x1, y1],
48646                 ["L", x2, y2],
48647                 ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
48648                 ["L", x3, y3],
48649                 ["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
48650                 ["Z"]]
48651             };
48652         }
48653     },
48654
48655     
48656     calcMiddle: function(item) {
48657         var me = this,
48658             rad = me.rad,
48659             slice = item.slice,
48660             x = me.centerX,
48661             y = me.centerY,
48662             startAngle = slice.startAngle,
48663             endAngle = slice.endAngle,
48664             donut = +me.donut,
48665             a1 = Math.min(startAngle, endAngle) * rad,
48666             a2 = Math.max(startAngle, endAngle) * rad,
48667             midAngle = -(a1 + (a2 - a1) / 2),
48668             xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle),
48669             ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle);
48670
48671         item.middle = {
48672             x: xm,
48673             y: ym
48674         };
48675     },
48676
48677     
48678     drawSeries: function() {
48679         var me = this,
48680             store = me.chart.substore || me.chart.store,
48681             group = me.group,
48682             animate = me.chart.animate,
48683             field = me.angleField || me.field || me.xField,
48684             lenField = [].concat(me.lengthField),
48685             totalLenField = 0,
48686             colors = me.colorSet,
48687             chart = me.chart,
48688             surface = chart.surface,
48689             chartBBox = chart.chartBBox,
48690             enableShadows = chart.shadow,
48691             shadowGroups = me.shadowGroups,
48692             shadowAttributes = me.shadowAttributes,
48693             lnsh = shadowGroups.length,
48694             rad = me.rad,
48695             layers = lenField.length,
48696             rhoAcum = 0,
48697             donut = +me.donut,
48698             layerTotals = [],
48699             values = {},
48700             fieldLength,
48701             items = [],
48702             passed = false,
48703             totalField = 0,
48704             maxLenField = 0,
48705             cut = 9,
48706             defcut = true,
48707             angle = 0,
48708             seriesStyle = me.seriesStyle,
48709             seriesLabelStyle = me.seriesLabelStyle,
48710             colorArrayStyle = me.colorArrayStyle,
48711             colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
48712             gutterX = chart.maxGutter[0],
48713             gutterY = chart.maxGutter[1],
48714             rendererAttributes,
48715             shadowGroup,
48716             shadowAttr,
48717             shadows,
48718             shadow,
48719             shindex,
48720             centerX,
48721             centerY,
48722             deltaRho,
48723             first = 0,
48724             slice,
48725             slices,
48726             sprite,
48727             value,
48728             item,
48729             lenValue,
48730             ln,
48731             record,
48732             i,
48733             j,
48734             startAngle,
48735             endAngle,
48736             middleAngle,
48737             sliceLength,
48738             path,
48739             p,
48740             spriteOptions, bbox;
48741         
48742         Ext.apply(seriesStyle, me.style || {});
48743
48744         me.setBBox();
48745         bbox = me.bbox;
48746
48747         
48748         if (me.colorSet) {
48749             colorArrayStyle = me.colorSet;
48750             colorArrayLength = colorArrayStyle.length;
48751         }
48752         
48753         
48754         if (!store || !store.getCount()) {
48755             return;
48756         }
48757         
48758         me.unHighlightItem();
48759         me.cleanHighlights();
48760
48761         centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
48762         centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
48763         me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
48764         me.slices = slices = [];
48765         me.items = items = [];
48766
48767         store.each(function(record, i) {
48768             if (this.__excludes && this.__excludes[i]) {
48769                 
48770                 return;
48771             }
48772             totalField += +record.get(field);
48773             if (lenField[0]) {
48774                 for (j = 0, totalLenField = 0; j < layers; j++) {
48775                     totalLenField += +record.get(lenField[j]);
48776                 }
48777                 layerTotals[i] = totalLenField;
48778                 maxLenField = Math.max(maxLenField, totalLenField);
48779             }
48780         }, this);
48781
48782         store.each(function(record, i) {
48783             if (this.__excludes && this.__excludes[i]) {
48784                 
48785                 return;
48786             } 
48787             value = record.get(field);
48788             middleAngle = angle - 360 * value / totalField / 2;
48789             
48790             if (isNaN(middleAngle)) {
48791                 middleAngle = 360;
48792                 value = 1;
48793                 totalField = 1;
48794             }
48795             
48796             if (!i || first == 0) {
48797                 angle = 360 - middleAngle;
48798                 me.firstAngle = angle;
48799                 middleAngle = angle - 360 * value / totalField / 2;
48800             }
48801             endAngle = angle - 360 * value / totalField;
48802             slice = {
48803                 series: me,
48804                 value: value,
48805                 startAngle: angle,
48806                 endAngle: endAngle,
48807                 storeItem: record
48808             };
48809             if (lenField[0]) {
48810                 lenValue = layerTotals[i];
48811                 slice.rho = me.radius * (lenValue / maxLenField);
48812             } else {
48813                 slice.rho = me.radius;
48814             }
48815             slices[i] = slice;
48816             if((slice.startAngle % 360) == (slice.endAngle % 360)) {
48817                 slice.startAngle -= 0.0001;
48818             }
48819             angle = endAngle;
48820             first++;
48821         }, me);
48822         
48823         
48824         if (enableShadows) {
48825             for (i = 0, ln = slices.length; i < ln; i++) {
48826                 if (this.__excludes && this.__excludes[i]) {
48827                     
48828                     continue;
48829                 }
48830                 slice = slices[i];
48831                 slice.shadowAttrs = [];
48832                 for (j = 0, rhoAcum = 0, shadows = []; j < layers; j++) {
48833                     sprite = group.getAt(i * layers + j);
48834                     deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho;
48835                     
48836                     rendererAttributes = {
48837                         segment: {
48838                             startAngle: slice.startAngle,
48839                             endAngle: slice.endAngle,
48840                             margin: 0,
48841                             rho: slice.rho,
48842                             startRho: rhoAcum + (deltaRho * donut / 100),
48843                             endRho: rhoAcum + deltaRho
48844                         }
48845                     };
48846                     
48847                     for (shindex = 0, shadows = []; shindex < lnsh; shindex++) {
48848                         shadowAttr = shadowAttributes[shindex];
48849                         shadow = shadowGroups[shindex].getAt(i);
48850                         if (!shadow) {
48851                             shadow = chart.surface.add(Ext.apply({}, {
48852                                 type: 'path',
48853                                 group: shadowGroups[shindex],
48854                                 strokeLinejoin: "round"
48855                             }, rendererAttributes, shadowAttr));
48856                         }
48857                         if (animate) {
48858                             shadowAttr = me.renderer(shadow, store.getAt(i), Ext.apply({}, rendererAttributes, shadowAttr), i, store);
48859                             me.onAnimate(shadow, {
48860                                 to: shadowAttr
48861                             });
48862                         } else {
48863                             shadowAttr = me.renderer(shadow, store.getAt(i), Ext.apply(shadowAttr, {
48864                                 hidden: false
48865                             }), i, store);
48866                             shadow.setAttributes(shadowAttr, true);
48867                         }
48868                         shadows.push(shadow);
48869                     }
48870                     slice.shadowAttrs[j] = shadows;
48871                 }
48872             }
48873         }
48874         
48875         for (i = 0, ln = slices.length; i < ln; i++) {
48876             if (this.__excludes && this.__excludes[i]) {
48877                 
48878                 continue;
48879             }
48880             slice = slices[i];
48881             for (j = 0, rhoAcum = 0; j < layers; j++) {
48882                 sprite = group.getAt(i * layers + j);
48883                 deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho;
48884                 
48885                 rendererAttributes = Ext.apply({
48886                     segment: {
48887                         startAngle: slice.startAngle,
48888                         endAngle: slice.endAngle,
48889                         margin: 0,
48890                         rho: slice.rho,
48891                         startRho: rhoAcum + (deltaRho * donut / 100),
48892                         endRho: rhoAcum + deltaRho
48893                     } 
48894                 }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {}));
48895                 item = Ext.apply({},
48896                 rendererAttributes.segment, {
48897                     slice: slice,
48898                     series: me,
48899                     storeItem: slice.storeItem,
48900                     index: i
48901                 });
48902                 me.calcMiddle(item);
48903                 if (enableShadows) {
48904                     item.shadows = slice.shadowAttrs[j];
48905                 }
48906                 items[i] = item;
48907                 
48908                 if (!sprite) {
48909                     spriteOptions = Ext.apply({
48910                         type: "path",
48911                         group: group,
48912                         middle: item.middle
48913                     }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {}));
48914                     sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
48915                 }
48916                 slice.sprite = slice.sprite || [];
48917                 item.sprite = sprite;
48918                 slice.sprite.push(sprite);
48919                 slice.point = [item.middle.x, item.middle.y];
48920                 if (animate) {
48921                     rendererAttributes = me.renderer(sprite, store.getAt(i), rendererAttributes, i, store);
48922                     sprite._to = rendererAttributes;
48923                     sprite._animating = true;
48924                     me.onAnimate(sprite, {
48925                         to: rendererAttributes,
48926                         listeners: {
48927                             afteranimate: {
48928                                 fn: function() {
48929                                     this._animating = false;
48930                                 },
48931                                 scope: sprite
48932                             }
48933                         }
48934                     });
48935                 } else {
48936                     rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(rendererAttributes, {
48937                         hidden: false
48938                     }), i, store);
48939                     sprite.setAttributes(rendererAttributes, true);
48940                 }
48941                 rhoAcum += deltaRho;
48942             }
48943         }
48944         
48945         
48946         ln = group.getCount();
48947         for (i = 0; i < ln; i++) {
48948             if (!slices[(i / layers) >> 0] && group.getAt(i)) {
48949                 group.getAt(i).hide(true);
48950             }
48951         }
48952         if (enableShadows) {
48953             lnsh = shadowGroups.length;
48954             for (shindex = 0; shindex < ln; shindex++) {
48955                 if (!slices[(shindex / layers) >> 0]) {
48956                     for (j = 0; j < lnsh; j++) {
48957                         if (shadowGroups[j].getAt(shindex)) {
48958                             shadowGroups[j].getAt(shindex).hide(true);
48959                         }
48960                     }
48961                 }
48962             }
48963         }
48964         me.renderLabels();
48965         me.renderCallouts();
48966     },
48967
48968     
48969     onCreateLabel: function(storeItem, item, i, display) {
48970         var me = this,
48971             group = me.labelsGroup,
48972             config = me.label,
48973             centerX = me.centerX,
48974             centerY = me.centerY,
48975             middle = item.middle,
48976             endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config || {});
48977         
48978         return me.chart.surface.add(Ext.apply({
48979             'type': 'text',
48980             'text-anchor': 'middle',
48981             'group': group,
48982             'x': middle.x,
48983             'y': middle.y
48984         }, endLabelStyle));
48985     },
48986
48987     
48988     onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {
48989         var me = this,
48990             chart = me.chart,
48991             resizing = chart.resizing,
48992             config = me.label,
48993             format = config.renderer,
48994             field = [].concat(config.field),
48995             centerX = me.centerX,
48996             centerY = me.centerY,
48997             middle = item.middle,
48998             opt = {
48999                 x: middle.x,
49000                 y: middle.y
49001             },
49002             x = middle.x - centerX,
49003             y = middle.y - centerY,
49004             from = {},
49005             rho = 1,
49006             theta = Math.atan2(y, x || 1),
49007             dg = theta * 180 / Math.PI,
49008             prevDg;
49009         
49010         function fixAngle(a) {
49011             if (a < 0) a += 360;
49012             return a % 360;
49013         }
49014
49015         label.setAttributes({
49016             text: format(storeItem.get(field[index]))
49017         }, true);
49018
49019         switch (display) {
49020         case 'outside':
49021             rho = Math.sqrt(x * x + y * y) * 2;
49022             
49023             opt.x = rho * Math.cos(theta) + centerX;
49024             opt.y = rho * Math.sin(theta) + centerY;
49025             break;
49026
49027         case 'rotate':
49028             dg = fixAngle(dg);
49029             dg = (dg > 90 && dg < 270) ? dg + 180: dg;
49030
49031             prevDg = label.attr.rotation.degrees;
49032             if (prevDg != null && Math.abs(prevDg - dg) > 180) {
49033                 if (dg > prevDg) {
49034                     dg -= 360;
49035                 } else {
49036                     dg += 360;
49037                 }
49038                 dg = dg % 360;
49039             } else {
49040                 dg = fixAngle(dg);
49041             }
49042             
49043             opt.rotate = {
49044                 degrees: dg,
49045                 x: opt.x,
49046                 y: opt.y
49047             };
49048             break;
49049
49050         default:
49051             break;
49052         }
49053         
49054         opt.translate = {
49055             x: 0, y: 0    
49056         };
49057         if (animate && !resizing && (display != 'rotate' || prevDg != null)) {
49058             me.onAnimate(label, {
49059                 to: opt
49060             });
49061         } else {
49062             label.setAttributes(opt, true);
49063         }
49064         label._from = from;
49065     },
49066
49067     
49068     onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
49069         var me = this,
49070             chart = me.chart,
49071             resizing = chart.resizing,
49072             config = me.callouts,
49073             centerX = me.centerX,
49074             centerY = me.centerY,
49075             middle = item.middle,
49076             opt = {
49077                 x: middle.x,
49078                 y: middle.y
49079             },
49080             x = middle.x - centerX,
49081             y = middle.y - centerY,
49082             rho = 1,
49083             rhoCenter,
49084             theta = Math.atan2(y, x || 1),
49085             bbox = callout.label.getBBox(),
49086             offsetFromViz = 20,
49087             offsetToSide = 10,
49088             offsetBox = 10,
49089             p;
49090
49091         
49092         rho = item.endRho + offsetFromViz;
49093         rhoCenter = (item.endRho + item.startRho) / 2 + (item.endRho - item.startRho) / 3;
49094         
49095         opt.x = rho * Math.cos(theta) + centerX;
49096         opt.y = rho * Math.sin(theta) + centerY;
49097
49098         x = rhoCenter * Math.cos(theta);
49099         y = rhoCenter * Math.sin(theta);
49100
49101         if (chart.animate) {
49102             
49103             me.onAnimate(callout.lines, {
49104                 to: {
49105                     path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"]
49106                 }
49107             });
49108             
49109             me.onAnimate(callout.box, {
49110                 to: {
49111                     x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)),
49112                     y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)),
49113                     width: bbox.width + 2 * offsetBox,
49114                     height: bbox.height + 2 * offsetBox
49115                 }
49116             });
49117             
49118             me.onAnimate(callout.label, {
49119                 to: {
49120                     x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)),
49121                     y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4)
49122                 }
49123             });
49124         } else {
49125             
49126             callout.lines.setAttributes({
49127                 path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"]
49128             },
49129             true);
49130             
49131             callout.box.setAttributes({
49132                 x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)),
49133                 y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)),
49134                 width: bbox.width + 2 * offsetBox,
49135                 height: bbox.height + 2 * offsetBox
49136             },
49137             true);
49138             
49139             callout.label.setAttributes({
49140                 x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)),
49141                 y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4)
49142             },
49143             true);
49144         }
49145         for (p in callout) {
49146             callout[p].show(true);
49147         }
49148     },
49149
49150     
49151     onAnimate: function(sprite, attr) {
49152         sprite.show();
49153         return this.callParent(arguments);
49154     },
49155
49156     isItemInPoint: function(x, y, item, i) {
49157         var me = this,
49158             cx = me.centerX,
49159             cy = me.centerY,
49160             abs = Math.abs,
49161             dx = abs(x - cx),
49162             dy = abs(y - cy),
49163             startAngle = item.startAngle,
49164             endAngle = item.endAngle,
49165             rho = Math.sqrt(dx * dx + dy * dy),
49166             angle = Math.atan2(y - cy, x - cx) / me.rad + 360;
49167         
49168         
49169         if (angle > me.firstAngle) {
49170             angle -= 360;
49171         }
49172         return (angle <= startAngle && angle > endAngle
49173                 && rho >= item.startRho && rho <= item.endRho);
49174     },
49175     
49176     
49177     hideAll: function() {
49178         var i, l, shadow, shadows, sh, lsh, sprite;
49179         if (!isNaN(this._index)) {
49180             this.__excludes = this.__excludes || [];
49181             this.__excludes[this._index] = true;
49182             sprite = this.slices[this._index].sprite;
49183             for (sh = 0, lsh = sprite.length; sh < lsh; sh++) {
49184                 sprite[sh].setAttributes({
49185                     hidden: true
49186                 }, true);
49187             }
49188             if (this.slices[this._index].shadowAttrs) {
49189                 for (i = 0, shadows = this.slices[this._index].shadowAttrs, l = shadows.length; i < l; i++) {
49190                     shadow = shadows[i];
49191                     for (sh = 0, lsh = shadow.length; sh < lsh; sh++) {
49192                         shadow[sh].setAttributes({
49193                             hidden: true
49194                         }, true);
49195                     }
49196                 }
49197             }
49198             this.drawSeries();
49199         }
49200     },
49201     
49202     
49203     showAll: function() {
49204         if (!isNaN(this._index)) {
49205             this.__excludes[this._index] = false;
49206             this.drawSeries();
49207         }
49208     },
49209
49210     
49211     highlightItem: function(item) {
49212         var me = this,
49213             rad = me.rad;
49214         item = item || this.items[this._index];
49215         
49216         
49217         
49218         
49219         
49220         this.unHighlightItem();
49221         
49222         if (!item || item.sprite && item.sprite._animating) {
49223             return;
49224         }
49225         me.callParent([item]);
49226         if (!me.highlight) {
49227             return;
49228         }
49229         if ('segment' in me.highlightCfg) {
49230             var highlightSegment = me.highlightCfg.segment,
49231                 animate = me.chart.animate,
49232                 attrs, i, shadows, shadow, ln, to, itemHighlightSegment, prop;
49233             
49234             if (me.labelsGroup) {
49235                 var group = me.labelsGroup,
49236                     display = me.label.display,
49237                     label = group.getAt(item.index),
49238                     middle = (item.startAngle + item.endAngle) / 2 * rad,
49239                     r = highlightSegment.margin || 0,
49240                     x = r * Math.cos(middle),
49241                     y = r * Math.sin(middle);
49242
49243                 
49244                 
49245                 
49246                 
49247                 
49248                 if (Math.abs(x) < 1e-10) {
49249                     x = 0;
49250                 }
49251                 if (Math.abs(y) < 1e-10) {
49252                     y = 0;
49253                 }
49254                 
49255                 if (animate) {
49256                     label.stopAnimation();
49257                     label.animate({
49258                         to: {
49259                             translate: {
49260                                 x: x,
49261                                 y: y
49262                             }
49263                         },
49264                         duration: me.highlightDuration
49265                     });
49266                 }
49267                 else {
49268                     label.setAttributes({
49269                         translate: {
49270                             x: x,
49271                             y: y
49272                         }
49273                     }, true);
49274                 }
49275             }
49276             
49277             if (me.chart.shadow && item.shadows) {
49278                 i = 0;
49279                 shadows = item.shadows;
49280                 ln = shadows.length;
49281                 for (; i < ln; i++) {
49282                     shadow = shadows[i];
49283                     to = {};
49284                     itemHighlightSegment = item.sprite._from.segment;
49285                     for (prop in itemHighlightSegment) {
49286                         if (! (prop in highlightSegment)) {
49287                             to[prop] = itemHighlightSegment[prop];
49288                         }
49289                     }
49290                     attrs = {
49291                         segment: Ext.applyIf(to, me.highlightCfg.segment)
49292                     };
49293                     if (animate) {
49294                         shadow.stopAnimation();
49295                         shadow.animate({
49296                             to: attrs,
49297                             duration: me.highlightDuration
49298                         });
49299                     }
49300                     else {
49301                         shadow.setAttributes(attrs, true);
49302                     }
49303                 }
49304             }
49305         }
49306     },
49307
49308     
49309     unHighlightItem: function() {
49310         var me = this;
49311         if (!me.highlight) {
49312             return;
49313         }
49314
49315         if (('segment' in me.highlightCfg) && me.items) {
49316             var items = me.items,
49317                 animate = me.chart.animate,
49318                 shadowsEnabled = !!me.chart.shadow,
49319                 group = me.labelsGroup,
49320                 len = items.length,
49321                 i = 0,
49322                 j = 0,
49323                 display = me.label.display,
49324                 shadowLen, p, to, ihs, hs, sprite, shadows, shadow, item, label, attrs;
49325
49326             for (; i < len; i++) {
49327                 item = items[i];
49328                 if (!item) {
49329                     continue;
49330                 }
49331                 sprite = item.sprite;
49332                 if (sprite && sprite._highlighted) {
49333                     
49334                     if (group) {
49335                         label = group.getAt(item.index);
49336                         attrs = Ext.apply({
49337                             translate: {
49338                                 x: 0,
49339                                 y: 0
49340                             }
49341                         },
49342                         display == 'rotate' ? {
49343                             rotate: {
49344                                 x: label.attr.x,
49345                                 y: label.attr.y,
49346                                 degrees: label.attr.rotation.degrees
49347                             }
49348                         }: {});
49349                         if (animate) {
49350                             label.stopAnimation();
49351                             label.animate({
49352                                 to: attrs,
49353                                 duration: me.highlightDuration
49354                             });
49355                         }
49356                         else {
49357                             label.setAttributes(attrs, true);
49358                         }
49359                     }
49360                     if (shadowsEnabled) {
49361                         shadows = item.shadows;
49362                         shadowLen = shadows.length;
49363                         for (; j < shadowLen; j++) {
49364                             to = {};
49365                             ihs = item.sprite._to.segment;
49366                             hs = item.sprite._from.segment;
49367                             Ext.apply(to, hs);
49368                             for (p in ihs) {
49369                                 if (! (p in hs)) {
49370                                     to[p] = ihs[p];
49371                                 }
49372                             }
49373                             shadow = shadows[j];
49374                             if (animate) {
49375                                 shadow.stopAnimation();
49376                                 shadow.animate({
49377                                     to: {
49378                                         segment: to
49379                                     },
49380                                     duration: me.highlightDuration
49381                                 });
49382                             }
49383                             else {
49384                                 shadow.setAttributes({ segment: to }, true);
49385                             }
49386                         }
49387                     }
49388                 }
49389             }
49390         }
49391         me.callParent(arguments);
49392     },
49393     
49394     
49395     getLegendColor: function(index) {
49396         var me = this;
49397         return me.colorArrayStyle[index % me.colorArrayStyle.length];
49398     }
49399 });
49400
49401
49402
49403 Ext.define('Ext.chart.series.Radar', {
49404
49405     
49406
49407     extend: 'Ext.chart.series.Series',
49408
49409     requires: ['Ext.chart.Shape', 'Ext.fx.Anim'],
49410
49411     
49412
49413     type: "radar",
49414     alias: 'series.radar',
49415
49416     
49417     rad: Math.PI / 180,
49418
49419     showInLegend: false,
49420
49421     
49422     style: {},
49423     
49424     constructor: function(config) {
49425         this.callParent(arguments);
49426         var me = this,
49427             surface = me.chart.surface, i, l;
49428         me.group = surface.getGroup(me.seriesId);
49429         if (me.showMarkers) {
49430             me.markerGroup = surface.getGroup(me.seriesId + '-markers');
49431         }
49432     },
49433
49434     
49435     drawSeries: function() {
49436         var me = this,
49437             store = me.chart.substore || me.chart.store,
49438             group = me.group,
49439             sprite,
49440             chart = me.chart,
49441             animate = chart.animate,
49442             field = me.field || me.yField,
49443             surface = chart.surface,
49444             chartBBox = chart.chartBBox,
49445             rendererAttributes,
49446             centerX, centerY,
49447             items,
49448             radius,
49449             maxValue = 0,
49450             fields = [],
49451             max = Math.max,
49452             cos = Math.cos,
49453             sin = Math.sin,
49454             pi2 = Math.PI * 2,
49455             l = store.getCount(),
49456             startPath, path, x, y, rho,
49457             i, nfields,
49458             seriesStyle = me.seriesStyle,
49459             seriesLabelStyle = me.seriesLabelStyle,
49460             first = chart.resizing || !me.radar,
49461             axis = chart.axes && chart.axes.get(0),
49462             aggregate = !(axis && axis.maximum);
49463         
49464         me.setBBox();
49465
49466         maxValue = aggregate? 0 : (axis.maximum || 0);
49467         
49468         Ext.apply(seriesStyle, me.style || {});
49469         
49470         
49471         if (!store || !store.getCount()) {
49472             return;
49473         }
49474         
49475         me.unHighlightItem();
49476         me.cleanHighlights();
49477
49478         centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
49479         centerY = me.centerY = chartBBox.y + (chartBBox.height / 2);
49480         me.radius = radius = Math.min(chartBBox.width, chartBBox.height) /2;
49481         me.items = items = [];
49482
49483         if (aggregate) {
49484             
49485             chart.series.each(function(series) {
49486                 fields.push(series.yField);
49487             });
49488             
49489             store.each(function(record, i) {
49490                 for (i = 0, nfields = fields.length; i < nfields; i++) {
49491                     maxValue = max(+record.get(fields[i]), maxValue);
49492                 }
49493             });
49494         }
49495         
49496         maxValue = maxValue || 1;
49497         
49498         startPath = []; path = [];
49499         store.each(function(record, i) {
49500             rho = radius * record.get(field) / maxValue;
49501             x = rho * cos(i / l * pi2);
49502             y = rho * sin(i / l * pi2);
49503             if (i == 0) {
49504                 path.push('M', x + centerX, y + centerY);
49505                 startPath.push('M', 0.01 * x + centerX, 0.01 * y + centerY);
49506             } else {
49507                 path.push('L', x + centerX, y + centerY);
49508                 startPath.push('L', 0.01 * x + centerX, 0.01 * y + centerY);
49509             }
49510             items.push({
49511                 sprite: false, 
49512                 point: [centerX + x, centerY + y],
49513                 series: me
49514             });
49515         });
49516         path.push('Z');
49517         
49518         if (!me.radar) {
49519             me.radar = surface.add(Ext.apply({
49520                 type: 'path',
49521                 group: group,
49522                 path: startPath
49523             }, seriesStyle || {}));
49524         }
49525         
49526         if (chart.resizing) {
49527             me.radar.setAttributes({
49528                 path: startPath
49529             }, true);
49530         }
49531         
49532         if (chart.animate) {
49533             me.onAnimate(me.radar, {
49534                 to: Ext.apply({
49535                     path: path
49536                 }, seriesStyle || {})
49537             });
49538         } else {
49539             me.radar.setAttributes(Ext.apply({
49540                 path: path
49541             }, seriesStyle || {}), true);
49542         }
49543         
49544         if (me.showMarkers) {
49545             me.drawMarkers();
49546         }
49547         me.renderLabels();
49548         me.renderCallouts();
49549     },
49550     
49551     
49552     drawMarkers: function() {
49553         var me = this,
49554             chart = me.chart,
49555             surface = chart.surface,
49556             markerStyle = Ext.apply({}, me.markerStyle || {}),
49557             endMarkerStyle = Ext.apply(markerStyle, me.markerConfig),
49558             items = me.items, 
49559             type = endMarkerStyle.type,
49560             markerGroup = me.markerGroup,
49561             centerX = me.centerX,
49562             centerY = me.centerY,
49563             item, i, l, marker;
49564         
49565         delete endMarkerStyle.type;
49566         
49567         for (i = 0, l = items.length; i < l; i++) {
49568             item = items[i];
49569             marker = markerGroup.getAt(i);
49570             if (!marker) {
49571                 marker = Ext.chart.Shape[type](surface, Ext.apply({
49572                     group: markerGroup,
49573                     x: 0,
49574                     y: 0,
49575                     translate: {
49576                         x: centerX,
49577                         y: centerY
49578                     }
49579                 }, endMarkerStyle));
49580             }
49581             else {
49582                 marker.show();
49583             }
49584             if (chart.resizing) {
49585                 marker.setAttributes({
49586                     x: 0,
49587                     y: 0,
49588                     translate: {
49589                         x: centerX,
49590                         y: centerY
49591                     }
49592                 }, true);
49593             }
49594             marker._to = {
49595                 translate: {
49596                     x: item.point[0],
49597                     y: item.point[1]
49598                 }
49599             };
49600             
49601             if (chart.animate) {
49602                 me.onAnimate(marker, {
49603                     to: marker._to
49604                 });
49605             }
49606             else {
49607                 marker.setAttributes(Ext.apply(marker._to, endMarkerStyle || {}), true);
49608             }
49609         }
49610     },
49611     
49612     isItemInPoint: function(x, y, item) {
49613         var point,
49614             tolerance = 10,
49615             abs = Math.abs;
49616         point = item.point;
49617         return (abs(point[0] - x) <= tolerance &&
49618                 abs(point[1] - y) <= tolerance);
49619     },
49620
49621     
49622     onCreateLabel: function(storeItem, item, i, display) {
49623         var me = this,
49624             group = me.labelsGroup,
49625             config = me.label,
49626             centerX = me.centerX,
49627             centerY = me.centerY,
49628             point = item.point,
49629             endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config);
49630         
49631         return me.chart.surface.add(Ext.apply({
49632             'type': 'text',
49633             'text-anchor': 'middle',
49634             'group': group,
49635             'x': centerX,
49636             'y': centerY
49637         }, config || {}));
49638     },
49639
49640     
49641     onPlaceLabel: function(label, storeItem, item, i, display, animate) {
49642         var me = this,
49643             chart = me.chart,
49644             resizing = chart.resizing,
49645             config = me.label,
49646             format = config.renderer,
49647             field = config.field,
49648             centerX = me.centerX,
49649             centerY = me.centerY,
49650             opt = {
49651                 x: item.point[0],
49652                 y: item.point[1]
49653             },
49654             x = opt.x - centerX,
49655             y = opt.y - centerY;
49656
49657         label.setAttributes({
49658             text: format(storeItem.get(field)),
49659             hidden: true
49660         },
49661         true);
49662         
49663         if (resizing) {
49664             label.setAttributes({
49665                 x: centerX,
49666                 y: centerY
49667             }, true);
49668         }
49669         
49670         if (animate) {
49671             label.show(true);
49672             me.onAnimate(label, {
49673                 to: opt
49674             });
49675         } else {
49676             label.setAttributes(opt, true);
49677             label.show(true);
49678         }
49679     },
49680
49681     
49682     toggleAll: function(show) {
49683         var me = this,
49684             i, ln, shadow, shadows;
49685         if (!show) {
49686             Ext.chart.series.Radar.superclass.hideAll.call(me);
49687         }
49688         else {
49689             Ext.chart.series.Radar.superclass.showAll.call(me);
49690         }
49691         if (me.radar) {
49692             me.radar.setAttributes({
49693                 hidden: !show
49694             }, true);
49695             
49696             if (me.radar.shadows) {
49697                 for (i = 0, shadows = me.radar.shadows, ln = shadows.length; i < ln; i++) {
49698                     shadow = shadows[i];
49699                     shadow.setAttributes({
49700                         hidden: !show
49701                     }, true);
49702                 }
49703             }
49704         }
49705     },
49706     
49707     
49708     hideAll: function() {
49709         this.toggleAll(false);
49710         this.hideMarkers(0);
49711     },
49712     
49713     
49714     showAll: function() {
49715         this.toggleAll(true);
49716     },
49717     
49718     
49719     hideMarkers: function(index) {
49720         var me = this,
49721             count = me.markerGroup && me.markerGroup.getCount() || 0,
49722             i = index || 0;
49723         for (; i < count; i++) {
49724             me.markerGroup.getAt(i).hide(true);
49725         }
49726     }
49727 });
49728
49729
49730
49731 Ext.define('Ext.chart.series.Scatter', {
49732
49733     
49734
49735     extend: 'Ext.chart.series.Cartesian',
49736
49737     requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.fx.Anim'],
49738
49739     
49740
49741     type: 'scatter',
49742     alias: 'series.scatter',
49743
49744     
49745     
49746     
49747
49748     constructor: function(config) {
49749         this.callParent(arguments);
49750         var me = this,
49751             shadow = me.chart.shadow,
49752             surface = me.chart.surface, i, l;
49753         Ext.apply(me, config, {
49754             style: {},
49755             markerConfig: {},
49756             shadowAttributes: [{
49757                 "stroke-width": 6,
49758                 "stroke-opacity": 0.05,
49759                 stroke: 'rgb(0, 0, 0)'
49760             }, {
49761                 "stroke-width": 4,
49762                 "stroke-opacity": 0.1,
49763                 stroke: 'rgb(0, 0, 0)'
49764             }, {
49765                 "stroke-width": 2,
49766                 "stroke-opacity": 0.15,
49767                 stroke: 'rgb(0, 0, 0)'
49768             }]
49769         });
49770         me.group = surface.getGroup(me.seriesId);
49771         if (shadow) {
49772             for (i = 0, l = me.shadowAttributes.length; i < l; i++) {
49773                 me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
49774             }
49775         }
49776     },
49777
49778     
49779     getBounds: function() {
49780         var me = this,
49781             chart = me.chart,
49782             store = chart.substore || chart.store,
49783             axes = [].concat(me.axis),
49784             bbox, xScale, yScale, ln, minX, minY, maxX, maxY, i, axis, ends;
49785
49786         me.setBBox();
49787         bbox = me.bbox;
49788
49789         for (i = 0, ln = axes.length; i < ln; i++) { 
49790             axis = chart.axes.get(axes[i]);
49791             if (axis) {
49792                 ends = axis.calcEnds();
49793                 if (axis.position == 'top' || axis.position == 'bottom') {
49794                     minX = ends.from;
49795                     maxX = ends.to;
49796                 }
49797                 else {
49798                     minY = ends.from;
49799                     maxY = ends.to;
49800                 }
49801             }
49802         }
49803         
49804         if (me.xField && !Ext.isNumber(minX)) {
49805             axis = Ext.create('Ext.chart.axis.Axis', {
49806                 chart: chart,
49807                 fields: [].concat(me.xField)
49808             }).calcEnds();
49809             minX = axis.from;
49810             maxX = axis.to;
49811         }
49812         if (me.yField && !Ext.isNumber(minY)) {
49813             axis = Ext.create('Ext.chart.axis.Axis', {
49814                 chart: chart,
49815                 fields: [].concat(me.yField)
49816             }).calcEnds();
49817             minY = axis.from;
49818             maxY = axis.to;
49819         }
49820
49821         if (isNaN(minX)) {
49822             minX = 0;
49823             maxX = store.getCount() - 1;
49824             xScale = bbox.width / (store.getCount() - 1);
49825         }
49826         else {
49827             xScale = bbox.width / (maxX - minX);
49828         }
49829
49830         if (isNaN(minY)) {
49831             minY = 0;
49832             maxY = store.getCount() - 1;
49833             yScale = bbox.height / (store.getCount() - 1);
49834         } 
49835         else {
49836             yScale = bbox.height / (maxY - minY);
49837         }
49838
49839         return {
49840             bbox: bbox,
49841             minX: minX,
49842             minY: minY,
49843             xScale: xScale,
49844             yScale: yScale
49845         };
49846     },
49847
49848     
49849     getPaths: function() {
49850         var me = this,
49851             chart = me.chart,
49852             enableShadows = chart.shadow,
49853             store = chart.substore || chart.store,
49854             group = me.group,
49855             bounds = me.bounds = me.getBounds(),
49856             bbox = me.bbox,
49857             xScale = bounds.xScale,
49858             yScale = bounds.yScale,
49859             minX = bounds.minX,
49860             minY = bounds.minY,
49861             boxX = bbox.x,
49862             boxY = bbox.y,
49863             boxHeight = bbox.height,
49864             items = me.items = [],
49865             attrs = [],
49866             x, y, xValue, yValue, sprite;
49867
49868         store.each(function(record, i) {
49869             xValue = record.get(me.xField);
49870             yValue = record.get(me.yField);
49871             
49872             if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
49873                 if (Ext.isDefined(Ext.global.console)) {
49874                     Ext.global.console.warn("[Ext.chart.series.Scatter]  Skipping a store element with an undefined value at ", record, xValue, yValue);
49875                 }
49876                 return;
49877             }
49878             
49879             if (typeof xValue == 'string' || typeof xValue == 'object') {
49880                 xValue = i;
49881             }
49882             if (typeof yValue == 'string' || typeof yValue == 'object') {
49883                 yValue = i;
49884             }
49885             x = boxX + (xValue - minX) * xScale;
49886             y = boxY + boxHeight - (yValue - minY) * yScale;
49887             attrs.push({
49888                 x: x,
49889                 y: y
49890             });
49891
49892             me.items.push({
49893                 series: me,
49894                 value: [xValue, yValue],
49895                 point: [x, y],
49896                 storeItem: record
49897             });
49898
49899             
49900             if (chart.animate && chart.resizing) {
49901                 sprite = group.getAt(i);
49902                 if (sprite) {
49903                     me.resetPoint(sprite);
49904                     if (enableShadows) {
49905                         me.resetShadow(sprite);
49906                     }
49907                 }
49908             }
49909         });
49910         return attrs;
49911     },
49912
49913     
49914     resetPoint: function(sprite) {
49915         var bbox = this.bbox;
49916         sprite.setAttributes({
49917             translate: {
49918                 x: (bbox.x + bbox.width) / 2,
49919                 y: (bbox.y + bbox.height) / 2
49920             }
49921         }, true);
49922     },
49923
49924     
49925     resetShadow: function(sprite) {
49926         var me = this,
49927             shadows = sprite.shadows,
49928             shadowAttributes = me.shadowAttributes,
49929             ln = me.shadowGroups.length,
49930             bbox = me.bbox,
49931             i, attr;
49932         for (i = 0; i < ln; i++) {
49933             attr = Ext.apply({}, shadowAttributes[i]);
49934             if (attr.translate) {
49935                 attr.translate.x += (bbox.x + bbox.width) / 2;
49936                 attr.translate.y += (bbox.y + bbox.height) / 2;
49937             }
49938             else {
49939                 attr.translate = {
49940                     x: (bbox.x + bbox.width) / 2,
49941                     y: (bbox.y + bbox.height) / 2
49942                 };
49943             }
49944             shadows[i].setAttributes(attr, true);
49945         }
49946     },
49947
49948     
49949     createPoint: function(attr, type) {
49950         var me = this,
49951             chart = me.chart,
49952             group = me.group,
49953             bbox = me.bbox;
49954
49955         return Ext.chart.Shape[type](chart.surface, Ext.apply({}, {
49956             x: 0,
49957             y: 0,
49958             group: group,
49959             translate: {
49960                 x: (bbox.x + bbox.width) / 2,
49961                 y: (bbox.y + bbox.height) / 2
49962             }
49963         }, attr));
49964     },
49965
49966     
49967     createShadow: function(sprite, endMarkerStyle, type) {
49968         var me = this,
49969             chart = me.chart,
49970             shadowGroups = me.shadowGroups,
49971             shadowAttributes = me.shadowAttributes,
49972             lnsh = shadowGroups.length,
49973             bbox = me.bbox,
49974             i, shadow, shadows, attr;
49975
49976         sprite.shadows = shadows = [];
49977
49978         for (i = 0; i < lnsh; i++) {
49979             attr = Ext.apply({}, shadowAttributes[i]);
49980             if (attr.translate) {
49981                 attr.translate.x += (bbox.x + bbox.width) / 2;
49982                 attr.translate.y += (bbox.y + bbox.height) / 2;
49983             }
49984             else {
49985                 Ext.apply(attr, {
49986                     translate: {
49987                         x: (bbox.x + bbox.width) / 2,
49988                         y: (bbox.y + bbox.height) / 2
49989                     }
49990                 });
49991             }
49992             Ext.apply(attr, endMarkerStyle);
49993             shadow = Ext.chart.Shape[type](chart.surface, Ext.apply({}, {
49994                 x: 0,
49995                 y: 0,
49996                 group: shadowGroups[i]
49997             }, attr));
49998             shadows.push(shadow);
49999         }
50000     },
50001
50002     
50003     drawSeries: function() {
50004         var me = this,
50005             chart = me.chart,
50006             store = chart.substore || chart.store,
50007             group = me.group,
50008             enableShadows = chart.shadow,
50009             shadowGroups = me.shadowGroups,
50010             shadowAttributes = me.shadowAttributes,
50011             lnsh = shadowGroups.length,
50012             sprite, attrs, attr, ln, i, endMarkerStyle, shindex, type, shadows,
50013             rendererAttributes, shadowAttribute;
50014
50015         endMarkerStyle = Ext.apply(me.markerStyle, me.markerConfig);
50016         type = endMarkerStyle.type;
50017         delete endMarkerStyle.type;
50018
50019         
50020         if (!store || !store.getCount()) {
50021             return;
50022         }
50023
50024         me.unHighlightItem();
50025         me.cleanHighlights();
50026
50027         attrs = me.getPaths();
50028         ln = attrs.length;
50029         for (i = 0; i < ln; i++) {
50030             attr = attrs[i];
50031             sprite = group.getAt(i);
50032             Ext.apply(attr, endMarkerStyle);
50033
50034             
50035             if (!sprite) {
50036                 sprite = me.createPoint(attr, type);
50037                 if (enableShadows) {
50038                     me.createShadow(sprite, endMarkerStyle, type);
50039                 }
50040             }
50041
50042             shadows = sprite.shadows;
50043             if (chart.animate) {
50044                 rendererAttributes = me.renderer(sprite, store.getAt(i), { translate: attr }, i, store);
50045                 sprite._to = rendererAttributes;
50046                 me.onAnimate(sprite, {
50047                     to: rendererAttributes
50048                 });
50049                 
50050                 for (shindex = 0; shindex < lnsh; shindex++) {
50051                     shadowAttribute = Ext.apply({}, shadowAttributes[shindex]);
50052                     rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({}, { 
50053                         translate: {
50054                             x: attr.x + (shadowAttribute.translate? shadowAttribute.translate.x : 0),
50055                             y: attr.y + (shadowAttribute.translate? shadowAttribute.translate.y : 0)
50056                         } 
50057                     }, shadowAttribute), i, store);
50058                     me.onAnimate(shadows[shindex], { to: rendererAttributes });
50059                 }
50060             }
50061             else {
50062                 rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply({ translate: attr }, { hidden: false }), i, store);
50063                 sprite.setAttributes(rendererAttributes, true);
50064                 
50065                 for (shindex = 0; shindex < lnsh; shindex++) {
50066                     shadowAttribute = shadowAttributes[shindex];
50067                     rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({ 
50068                         x: attr.x,
50069                         y: attr.y
50070                     }, shadowAttribute), i, store);
50071                     shadows[shindex].setAttributes(rendererAttributes, true);
50072                 }
50073             }
50074             me.items[i].sprite = sprite;
50075         }
50076
50077         
50078         ln = group.getCount();
50079         for (i = attrs.length; i < ln; i++) {
50080             group.getAt(i).hide(true);
50081         }
50082         me.renderLabels();
50083         me.renderCallouts();
50084     },
50085     
50086     
50087     onCreateLabel: function(storeItem, item, i, display) {
50088         var me = this,
50089             group = me.labelsGroup,
50090             config = me.label,
50091             endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle),
50092             bbox = me.bbox;
50093         
50094         return me.chart.surface.add(Ext.apply({
50095             type: 'text',
50096             group: group,
50097             x: item.point[0],
50098             y: bbox.y + bbox.height / 2
50099         }, endLabelStyle));
50100     },
50101     
50102     
50103     onPlaceLabel: function(label, storeItem, item, i, display, animate) {
50104         var me = this,
50105             chart = me.chart,
50106             resizing = chart.resizing,
50107             config = me.label,
50108             format = config.renderer,
50109             field = config.field,
50110             bbox = me.bbox,
50111             x = item.point[0],
50112             y = item.point[1],
50113             radius = item.sprite.attr.radius,
50114             bb, width, height, anim;
50115         
50116         label.setAttributes({
50117             text: format(storeItem.get(field)),
50118             hidden: true
50119         }, true);
50120         
50121         if (display == 'rotate') {
50122             label.setAttributes({
50123                 'text-anchor': 'start',
50124                 'rotation': {
50125                     x: x,
50126                     y: y,
50127                     degrees: -45
50128                 }
50129             }, true);
50130             
50131             bb = label.getBBox();
50132             width = bb.width;
50133             height = bb.height;
50134             x = x < bbox.x? bbox.x : x;
50135             x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
50136             y = (y - height < bbox.y)? bbox.y + height : y;
50137         
50138         } else if (display == 'under' || display == 'over') {
50139             
50140             bb = item.sprite.getBBox();
50141             bb.width = bb.width || (radius * 2);
50142             bb.height = bb.height || (radius * 2);
50143             y = y + (display == 'over'? -bb.height : bb.height);
50144             
50145             bb = label.getBBox();
50146             width = bb.width/2;
50147             height = bb.height/2;
50148             x = x - width < bbox.x ? bbox.x + width : x;
50149             x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
50150             y = y - height < bbox.y? bbox.y + height : y;
50151             y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
50152         }
50153
50154         if (!chart.animate) {
50155             label.setAttributes({
50156                 x: x,
50157                 y: y
50158             }, true);
50159             label.show(true);
50160         }
50161         else {
50162             if (resizing) {
50163                 anim = item.sprite.getActiveAnimation();
50164                 if (anim) {
50165                     anim.on('afteranimate', function() {
50166                         label.setAttributes({
50167                             x: x,
50168                             y: y
50169                         }, true);
50170                         label.show(true);
50171                     });   
50172                 }
50173                 else {
50174                     label.show(true);
50175                 }
50176             }
50177             else {
50178                 me.onAnimate(label, {
50179                     to: {
50180                         x: x,
50181                         y: y
50182                     }
50183                 });
50184             }
50185         }
50186     },
50187     
50188     
50189     onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
50190         var me = this,
50191             chart = me.chart,
50192             surface = chart.surface,
50193             resizing = chart.resizing,
50194             config = me.callouts,
50195             items = me.items,
50196             cur = item.point,
50197             normal,
50198             bbox = callout.label.getBBox(),
50199             offsetFromViz = 30,
50200             offsetToSide = 10,
50201             offsetBox = 3,
50202             boxx, boxy, boxw, boxh,
50203             p, clipRect = me.bbox,
50204             x, y;
50205     
50206         
50207         normal = [Math.cos(Math.PI /4), -Math.sin(Math.PI /4)];
50208         x = cur[0] + normal[0] * offsetFromViz;
50209         y = cur[1] + normal[1] * offsetFromViz;
50210         
50211         
50212         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
50213         boxy = y - bbox.height /2 - offsetBox;
50214         boxw = bbox.width + 2 * offsetBox;
50215         boxh = bbox.height + 2 * offsetBox;
50216         
50217         
50218         
50219         if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) {
50220             normal[0] *= -1;
50221         }
50222         if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) {
50223             normal[1] *= -1;
50224         }
50225     
50226         
50227         x = cur[0] + normal[0] * offsetFromViz;
50228         y = cur[1] + normal[1] * offsetFromViz;
50229         
50230         
50231         boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox));
50232         boxy = y - bbox.height /2 - offsetBox;
50233         boxw = bbox.width + 2 * offsetBox;
50234         boxh = bbox.height + 2 * offsetBox;
50235         
50236         if (chart.animate) {
50237             
50238             me.onAnimate(callout.lines, {
50239                 to: {
50240                     path: ["M", cur[0], cur[1], "L", x, y, "Z"]
50241                 }
50242             }, true);
50243             
50244             me.onAnimate(callout.box, {
50245                 to: {
50246                     x: boxx,
50247                     y: boxy,
50248                     width: boxw,
50249                     height: boxh
50250                 }
50251             }, true);
50252             
50253             me.onAnimate(callout.label, {
50254                 to: {
50255                     x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
50256                     y: y
50257                 }
50258             }, true);
50259         } else {
50260             
50261             callout.lines.setAttributes({
50262                 path: ["M", cur[0], cur[1], "L", x, y, "Z"]
50263             }, true);
50264             
50265             callout.box.setAttributes({
50266                 x: boxx,
50267                 y: boxy,
50268                 width: boxw,
50269                 height: boxh
50270             }, true);
50271             
50272             callout.label.setAttributes({
50273                 x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)),
50274                 y: y
50275             }, true);
50276         }
50277         for (p in callout) {
50278             callout[p].show(true);
50279         }
50280     },
50281
50282     
50283     onAnimate: function(sprite, attr) {
50284         sprite.show();
50285         return this.callParent(arguments);
50286     },
50287
50288     isItemInPoint: function(x, y, item) {
50289         var point,
50290             tolerance = 10,
50291             abs = Math.abs;
50292
50293         function dist(point) {
50294             var dx = abs(point[0] - x),
50295                 dy = abs(point[1] - y);
50296             return Math.sqrt(dx * dx + dy * dy);
50297         }
50298         point = item.point;
50299         return (point[0] - tolerance <= x && point[0] + tolerance >= x &&
50300             point[1] - tolerance <= y && point[1] + tolerance >= y);
50301     }
50302 });
50303
50304
50305
50306 Ext.define('Ext.chart.theme.Base', {
50307
50308     
50309
50310     requires: ['Ext.chart.theme.Theme'],
50311
50312     
50313
50314     constructor: function(config) {
50315         Ext.chart.theme.call(this, config, {
50316             background: false,
50317             axis: {
50318                 stroke: '#444',
50319                 'stroke-width': 1
50320             },
50321             axisLabelTop: {
50322                 fill: '#444',
50323                 font: '12px Arial, Helvetica, sans-serif',
50324                 spacing: 2,
50325                 padding: 5,
50326                 renderer: function(v) { return v; }
50327             },
50328             axisLabelRight: {
50329                 fill: '#444',
50330                 font: '12px Arial, Helvetica, sans-serif',
50331                 spacing: 2,
50332                 padding: 5,
50333                 renderer: function(v) { return v; }
50334             },
50335             axisLabelBottom: {
50336                 fill: '#444',
50337                 font: '12px Arial, Helvetica, sans-serif',
50338                 spacing: 2,
50339                 padding: 5,
50340                 renderer: function(v) { return v; }
50341             },
50342             axisLabelLeft: {
50343                 fill: '#444',
50344                 font: '12px Arial, Helvetica, sans-serif',
50345                 spacing: 2,
50346                 padding: 5,
50347                 renderer: function(v) { return v; }
50348             },
50349             axisTitleTop: {
50350                 font: 'bold 18px Arial',
50351                 fill: '#444'
50352             },
50353             axisTitleRight: {
50354                 font: 'bold 18px Arial',
50355                 fill: '#444',
50356                 rotate: {
50357                     x:0, y:0,
50358                     degrees: 270
50359                 }
50360             },
50361             axisTitleBottom: {
50362                 font: 'bold 18px Arial',
50363                 fill: '#444'
50364             },
50365             axisTitleLeft: {
50366                 font: 'bold 18px Arial',
50367                 fill: '#444',
50368                 rotate: {
50369                     x:0, y:0,
50370                     degrees: 270
50371                 }
50372             },
50373             series: {
50374                 'stroke-width': 0
50375             },
50376             seriesLabel: {
50377                 font: '12px Arial',
50378                 fill: '#333'
50379             },
50380             marker: {
50381                 stroke: '#555',
50382                 fill: '#000',
50383                 radius: 3,
50384                 size: 3
50385             },
50386             colors: [ "#94ae0a", "#115fa6","#a61120", "#ff8809", "#ffd13e", "#a61187", "#24ad9a", "#7c7474", "#a66111"],
50387             seriesThemes: [{
50388                 fill: "#115fa6"
50389             }, {
50390                 fill: "#94ae0a"
50391             }, {
50392                 fill: "#a61120"
50393             }, {
50394                 fill: "#ff8809"
50395             }, {
50396                 fill: "#ffd13e"
50397             }, {
50398                 fill: "#a61187"
50399             }, {
50400                 fill: "#24ad9a"
50401             }, {
50402                 fill: "#7c7474"
50403             }, {
50404                 fill: "#a66111"
50405             }],
50406             markerThemes: [{
50407                 fill: "#115fa6",
50408                 type: 'circle' 
50409             }, {
50410                 fill: "#94ae0a",
50411                 type: 'cross'
50412             }, {
50413                 fill: "#a61120",
50414                 type: 'plus'
50415             }]
50416         });
50417     }
50418 }, function() {
50419     var palette = ['#b1da5a', '#4ce0e7', '#e84b67', '#da5abd', '#4d7fe6', '#fec935'],
50420         names = ['Green', 'Sky', 'Red', 'Purple', 'Blue', 'Yellow'],
50421         i = 0, j = 0, l = palette.length, themes = Ext.chart.theme,
50422         categories = [['#f0a50a', '#c20024', '#2044ba', '#810065', '#7eae29'],
50423                       ['#6d9824', '#87146e', '#2a9196', '#d39006', '#1e40ac'],
50424                       ['#fbbc29', '#ce2e4e', '#7e0062', '#158b90', '#57880e'],
50425                       ['#ef5773', '#fcbd2a', '#4f770d', '#1d3eaa', '#9b001f'],
50426                       ['#7eae29', '#fdbe2a', '#910019', '#27b4bc', '#d74dbc'],
50427                       ['#44dce1', '#0b2592', '#996e05', '#7fb325', '#b821a1']],
50428         cats = categories.length;
50429     
50430     
50431     for (; i < l; i++) {
50432         themes[names[i]] = (function(color) {
50433             return Ext.extend(themes.Base, {
50434                 constructor: function(config) {
50435                     themes.Base.prototype.constructor.call(this, Ext.apply({
50436                         baseColor: color
50437                     }, config));
50438                 }
50439             });
50440         })(palette[i]);
50441     }
50442     
50443     
50444     for (i = 0; i < cats; i++) {
50445         themes['Category' + (i + 1)] = (function(category) {
50446             return Ext.extend(themes.Base, {
50447                 constructor: function(config) {
50448                     themes.Base.prototype.constructor.call(this, Ext.apply({
50449                         colors: category
50450                     }, config));
50451                 }
50452             });
50453         })(categories[i]);
50454     }
50455 });
50456
50457
50458 Ext.define('Ext.data.ArrayStore', {
50459     extend: 'Ext.data.Store',
50460     alias: 'store.array',
50461     uses: ['Ext.data.reader.Array'],
50462
50463     
50464     constructor: function(config) {
50465         config = config || {};
50466
50467         Ext.applyIf(config, {
50468             proxy: {
50469                 type: 'memory',
50470                 reader: 'array'
50471             }
50472         });
50473
50474         this.callParent([config]);
50475     },
50476
50477     loadData: function(data, append) {
50478         if (this.expandData === true) {
50479             var r = [],
50480                 i = 0,
50481                 ln = data.length;
50482
50483             for (; i < ln; i++) {
50484                 r[r.length] = [data[i]];
50485             }
50486
50487             data = r;
50488         }
50489
50490         this.callParent([data, append]);
50491     }
50492 }, function() {
50493     
50494     Ext.data.SimpleStore = Ext.data.ArrayStore;
50495     
50496 });
50497
50498
50499 Ext.define('Ext.data.Batch', {
50500     mixins: {
50501         observable: 'Ext.util.Observable'
50502     },
50503     
50504     
50505     autoStart: false,
50506     
50507     
50508     current: -1,
50509     
50510     
50511     total: 0,
50512     
50513     
50514     isRunning: false,
50515     
50516     
50517     isComplete: false,
50518     
50519     
50520     hasException: false,
50521     
50522     
50523     pauseOnException: true,
50524     
50525     constructor: function(config) {   
50526         var me = this;
50527                      
50528         me.addEvents(
50529           
50530           'complete',
50531           
50532           
50533           'exception',
50534           
50535           
50536           'operationcomplete'
50537         );
50538         
50539         me.mixins.observable.constructor.call(me, config);
50540         
50541         
50542         me.operations = [];
50543     },
50544     
50545     
50546     add: function(operation) {
50547         this.total++;
50548         
50549         operation.setBatch(this);
50550         
50551         this.operations.push(operation);
50552     },
50553     
50554     
50555     start: function() {
50556         this.hasException = false;
50557         this.isRunning = true;
50558         
50559         this.runNextOperation();
50560     },
50561     
50562     
50563     runNextOperation: function() {
50564         this.runOperation(this.current + 1);
50565     },
50566     
50567     
50568     pause: function() {
50569         this.isRunning = false;
50570     },
50571     
50572     
50573     runOperation: function(index) {
50574         var me = this,
50575             operations = me.operations,
50576             operation  = operations[index],
50577             onProxyReturn;
50578         
50579         if (operation === undefined) {
50580             me.isRunning  = false;
50581             me.isComplete = true;
50582             me.fireEvent('complete', me, operations[operations.length - 1]);
50583         } else {
50584             me.current = index;
50585             
50586             onProxyReturn = function(operation) {
50587                 var hasException = operation.hasException();
50588                 
50589                 if (hasException) {
50590                     me.hasException = true;
50591                     me.fireEvent('exception', me, operation);
50592                 } else {
50593                     me.fireEvent('operationcomplete', me, operation);
50594                 }
50595
50596                 if (hasException && me.pauseOnException) {
50597                     me.pause();
50598                 } else {
50599                     operation.setCompleted();
50600                     me.runNextOperation();
50601                 }
50602             };
50603             
50604             operation.setStarted();
50605             
50606             me.proxy[operation.action](operation, onProxyReturn, me);
50607         }
50608     }
50609 });
50610
50611 Ext.define('Ext.data.BelongsToAssociation', {
50612     extend: 'Ext.data.Association',
50613
50614     alias: 'association.belongsto',
50615
50616     
50617
50618     
50619
50620     
50621     
50622     
50623
50624     constructor: function(config) {
50625         this.callParent(arguments);
50626
50627         var me             = this,
50628             ownerProto     = me.ownerModel.prototype,
50629             associatedName = me.associatedName,
50630             getterName     = me.getterName || 'get' + associatedName,
50631             setterName     = me.setterName || 'set' + associatedName;
50632
50633         Ext.applyIf(me, {
50634             name        : associatedName,
50635             foreignKey  : associatedName.toLowerCase() + "_id",
50636             instanceName: associatedName + 'BelongsToInstance',
50637             associationKey: associatedName.toLowerCase()
50638         });
50639
50640         ownerProto[getterName] = me.createGetter();
50641         ownerProto[setterName] = me.createSetter();
50642     },
50643
50644     
50645     createSetter: function() {
50646         var me              = this,
50647             ownerModel      = me.ownerModel,
50648             associatedModel = me.associatedModel,
50649             foreignKey      = me.foreignKey,
50650             primaryKey      = me.primaryKey;
50651
50652         
50653         return function(value, options, scope) {
50654             this.set(foreignKey, value);
50655
50656             if (typeof options == 'function') {
50657                 options = {
50658                     callback: options,
50659                     scope: scope || this
50660                 };
50661             }
50662
50663             if (Ext.isObject(options)) {
50664                 return this.save(options);
50665             }
50666         };
50667     },
50668
50669     
50670     createGetter: function() {
50671         var me              = this,
50672             ownerModel      = me.ownerModel,
50673             associatedName  = me.associatedName,
50674             associatedModel = me.associatedModel,
50675             foreignKey      = me.foreignKey,
50676             primaryKey      = me.primaryKey,
50677             instanceName    = me.instanceName;
50678
50679         
50680         return function(options, scope) {
50681             options = options || {};
50682
50683             var foreignKeyId = this.get(foreignKey),
50684                 instance, callbackFn;
50685
50686             if (this[instanceName] === undefined) {
50687                 instance = Ext.ModelManager.create({}, associatedName);
50688                 instance.set(primaryKey, foreignKeyId);
50689
50690                 if (typeof options == 'function') {
50691                     options = {
50692                         callback: options,
50693                         scope: scope || this
50694                     };
50695                 }
50696
50697                 associatedModel.load(foreignKeyId, options);
50698             } else {
50699                 instance = this[instanceName];
50700
50701                 
50702                 
50703                 
50704                 if (typeof options == 'function') {
50705                     options.call(scope || this, instance);
50706                 }
50707
50708                 if (options.success) {
50709                     options.success.call(scope || this, instance);
50710                 }
50711
50712                 if (options.callback) {
50713                     options.callback.call(scope || this, instance);
50714                 }
50715
50716                 return instance;
50717             }
50718         };
50719     },
50720
50721     
50722     read: function(record, reader, associationData){
50723         record[this.instanceName] = reader.read([associationData]).records[0];
50724     }
50725 });
50726
50727
50728 Ext.define('Ext.data.BufferStore', {
50729     extend: 'Ext.data.Store',
50730     alias: 'store.buffer',
50731     sortOnLoad: false,
50732     filterOnLoad: false,
50733     
50734     constructor: function() {
50735         Ext.Error.raise('The BufferStore class has been deprecated. Instead, specify the buffered config option on Ext.data.Store');
50736     }
50737 });
50738
50739
50740 Ext.define('Ext.direct.Manager', {
50741     
50742     
50743     singleton: true,
50744    
50745     mixins: {
50746         observable: 'Ext.util.Observable'
50747     },
50748     
50749     requires: ['Ext.util.MixedCollection'],
50750     
50751     statics: {
50752         exceptions: {
50753             TRANSPORT: 'xhr',
50754             PARSE: 'parse',
50755             LOGIN: 'login',
50756             SERVER: 'exception'
50757         }
50758     },
50759     
50760     
50761    
50762     constructor: function(){
50763         var me = this;
50764        
50765         me.addEvents(
50766             
50767             'event',
50768             
50769             'exception'
50770         );
50771         me.transactions = Ext.create('Ext.util.MixedCollection');
50772         me.providers = Ext.create('Ext.util.MixedCollection');
50773         
50774         me.mixins.observable.constructor.call(me);
50775     },
50776     
50777     
50778     addProvider : function(provider){
50779         var me = this,
50780             args = arguments,
50781             i = 0,
50782             len;
50783             
50784         if (args.length > 1) {
50785             for (len = args.length; i < len; ++i) {
50786                 me.addProvider(args[i]);
50787             }
50788             return;
50789         }
50790
50791         
50792         if (!provider.isProvider) {
50793             provider = Ext.create('direct.' + provider.type + 'provider', provider);
50794         }
50795         me.providers.add(provider);
50796         provider.on('data', me.onProviderData, me);
50797
50798
50799         if (!provider.isConnected()) {
50800             provider.connect();
50801         }
50802
50803         return provider;
50804     },
50805     
50806     
50807     getProvider : function(id){
50808         return id.isProvider ? id : this.providers.get(id);
50809     },
50810     
50811     
50812     removeProvider : function(provider){
50813         var me = this,
50814             providers = me.providers,
50815             provider = provider.isProvider ? provider : providers.get(provider);
50816             
50817         if (provider) {
50818             provider.un('data', me.onProviderData, me);
50819             providers.remove(provider);
50820             return provider;
50821         }
50822         return null;
50823     },
50824     
50825     
50826     addTransaction: function(transaction){
50827         this.transactions.add(transaction);
50828         return transaction;
50829     },
50830
50831     
50832     removeTransaction: function(transaction){
50833         transaction = this.getTransaction(transaction);
50834         this.transactions.remove(transaction);
50835         return transaction;
50836     },
50837
50838     
50839     getTransaction: function(transaction){
50840         return transaction.isTransaction ? transaction : this.transactions.get(transaction);
50841     },
50842     
50843     onProviderData : function(provider, event){
50844         var me = this,
50845             i = 0,
50846             len;
50847             
50848         if (Ext.isArray(event)) {
50849             for (len = event.length; i < len; ++i) {
50850                 me.onProviderData(provider, event[i]);
50851             }
50852             return;
50853         }
50854         if (event.name && event.name != 'event' && event.name != 'exception') {
50855             me.fireEvent(event.name, event);
50856         } else if (event.type == 'exception') {
50857             me.fireEvent('exception', event);
50858         }
50859         me.fireEvent('event', event, provider);
50860     }
50861 }, function(){
50862     
50863     Ext.Direct = Ext.direct.Manager;
50864 });
50865
50866
50867 Ext.define('Ext.data.proxy.Direct', {
50868     
50869     
50870     extend: 'Ext.data.proxy.Server',
50871     alternateClassName: 'Ext.data.DirectProxy',
50872     
50873     alias: 'proxy.direct',
50874     
50875     requires: ['Ext.direct.Manager'],
50876     
50877     
50878    
50879    
50880     paramOrder: undefined,
50881
50882     
50883     paramsAsHash: true,
50884
50885     
50886     directFn : undefined,
50887     
50888     
50889     
50890     
50891     
50892     
50893     paramOrderRe: /[\s,|]/,
50894     
50895     constructor: function(config){
50896         var me = this;
50897         
50898         Ext.apply(me, config);
50899         if (Ext.isString(me.paramOrder)) {
50900             me.paramOrder = me.paramOrder.split(me.paramOrderRe);
50901         }
50902         me.callParent(arguments);
50903     },
50904     
50905     doRequest: function(operation, callback, scope) {
50906         var me = this,
50907             writer = me.getWriter(),
50908             request = me.buildRequest(operation, callback, scope),
50909             fn = me.api[request.action]  || me.directFn,
50910             args = [],
50911             params = request.params,
50912             paramOrder = me.paramOrder,
50913             method,
50914             i = 0,
50915             len;
50916             
50917         if (!fn) {
50918             Ext.Error.raise('No direct function specified for this proxy');
50919         }
50920             
50921         if (operation.allowWrite()) {
50922             request = writer.write(request);
50923         }
50924         
50925         if (operation.action == 'read') {
50926             
50927             method = fn.directCfg.method;
50928             
50929             if (method.ordered) {
50930                 if (method.len > 0) {
50931                     if (paramOrder) {
50932                         for (len = paramOrder.length; i < len; ++i) {
50933                             args.push(params[paramOrder[i]]);
50934                         }
50935                     } else if (me.paramsAsHash) {
50936                         args.push(params);
50937                     }
50938                 }
50939             } else {
50940                 args.push(params);
50941             }
50942         } else {
50943             args.push(request.jsonData);
50944         }
50945         
50946         Ext.apply(request, {
50947             args: args,
50948             directFn: fn
50949         });
50950         args.push(me.createRequestCallback(request, operation, callback, scope), me);
50951         fn.apply(window, args);
50952     },
50953     
50954     
50955     applyEncoding: function(value){
50956         return value;
50957     },
50958     
50959     createRequestCallback: function(request, operation, callback, scope){
50960         var me = this;
50961         
50962         return function(data, event){
50963             me.processResponse(event.status, operation, request, event, callback, scope);
50964         };
50965     },
50966     
50967     
50968     extractResponseData: function(response){
50969         return Ext.isDefined(response.result) ? response.result : response.data;
50970     },
50971     
50972     
50973     setException: function(operation, response) {
50974         operation.setException(response.message);
50975     },
50976     
50977     
50978     buildUrl: function(){
50979         return '';
50980     }
50981 });
50982
50983
50984
50985 Ext.define('Ext.data.DirectStore', {
50986     
50987     
50988     extend: 'Ext.data.Store',
50989     
50990     alias: 'store.direct',
50991     
50992     requires: ['Ext.data.proxy.Direct'],
50993    
50994     
50995    
50996    constructor : function(config){
50997         config = Ext.apply({}, config);
50998         if (!config.proxy) {
50999             var proxy = {
51000                 type: 'direct',
51001                 reader: {
51002                     type: 'json'
51003                 }
51004             };
51005             Ext.copyTo(proxy, config, 'paramOrder,paramsAsHash,directFn,api,simpleSortMode');
51006             Ext.copyTo(proxy.reader, config, 'totalProperty,root,idProperty');
51007             config.proxy = proxy;
51008         }
51009         this.callParent([config]);
51010     }    
51011 });
51012
51013
51014
51015 Ext.define('Ext.util.Inflector', {
51016
51017     
51018
51019     singleton: true,
51020
51021     
51022
51023     
51024     plurals: [
51025         [(/(quiz)$/i),                "$1zes"  ],
51026         [(/^(ox)$/i),                 "$1en"   ],
51027         [(/([m|l])ouse$/i),           "$1ice"  ],
51028         [(/(matr|vert|ind)ix|ex$/i),  "$1ices" ],
51029         [(/(x|ch|ss|sh)$/i),          "$1es"   ],
51030         [(/([^aeiouy]|qu)y$/i),       "$1ies"  ],
51031         [(/(hive)$/i),                "$1s"    ],
51032         [(/(?:([^f])fe|([lr])f)$/i),  "$1$2ves"],
51033         [(/sis$/i),                   "ses"    ],
51034         [(/([ti])um$/i),              "$1a"    ],
51035         [(/(buffal|tomat|potat)o$/i), "$1oes"  ],
51036         [(/(bu)s$/i),                 "$1ses"  ],
51037         [(/(alias|status|sex)$/i),    "$1es"   ],
51038         [(/(octop|vir)us$/i),         "$1i"    ],
51039         [(/(ax|test)is$/i),           "$1es"   ],
51040         [(/^person$/),                "people" ],
51041         [(/^man$/),                   "men"    ],
51042         [(/^(child)$/),               "$1ren"  ],
51043         [(/s$/i),                     "s"      ],
51044         [(/$/),                       "s"      ]
51045     ],
51046     
51047     
51048     singulars: [
51049       [(/(quiz)zes$/i),                                                    "$1"     ],
51050       [(/(matr)ices$/i),                                                   "$1ix"   ],
51051       [(/(vert|ind)ices$/i),                                               "$1ex"   ],
51052       [(/^(ox)en/i),                                                       "$1"     ],
51053       [(/(alias|status)es$/i),                                             "$1"     ],
51054       [(/(octop|vir)i$/i),                                                 "$1us"   ],
51055       [(/(cris|ax|test)es$/i),                                             "$1is"   ],
51056       [(/(shoe)s$/i),                                                      "$1"     ],
51057       [(/(o)es$/i),                                                        "$1"     ],
51058       [(/(bus)es$/i),                                                      "$1"     ],
51059       [(/([m|l])ice$/i),                                                   "$1ouse" ],
51060       [(/(x|ch|ss|sh)es$/i),                                               "$1"     ],
51061       [(/(m)ovies$/i),                                                     "$1ovie" ],
51062       [(/(s)eries$/i),                                                     "$1eries"],
51063       [(/([^aeiouy]|qu)ies$/i),                                            "$1y"    ],
51064       [(/([lr])ves$/i),                                                    "$1f"    ],
51065       [(/(tive)s$/i),                                                      "$1"     ],
51066       [(/(hive)s$/i),                                                      "$1"     ],
51067       [(/([^f])ves$/i),                                                    "$1fe"   ],
51068       [(/(^analy)ses$/i),                                                  "$1sis"  ],
51069       [(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i), "$1$2sis"],
51070       [(/([ti])a$/i),                                                      "$1um"   ],
51071       [(/(n)ews$/i),                                                       "$1ews"  ],
51072       [(/people$/i),                                                       "person" ],
51073       [(/s$/i),                                                            ""       ]
51074     ],
51075     
51076     
51077      uncountable: [
51078         "sheep",
51079         "fish",
51080         "series",
51081         "species",
51082         "money",
51083         "rice",
51084         "information",
51085         "equipment",
51086         "grass",
51087         "mud",
51088         "offspring",
51089         "deer",
51090         "means"
51091     ],
51092     
51093     
51094     singular: function(matcher, replacer) {
51095         this.singulars.unshift([matcher, replacer]);
51096     },
51097     
51098     
51099     plural: function(matcher, replacer) {
51100         this.plurals.unshift([matcher, replacer]);
51101     },
51102     
51103     
51104     clearSingulars: function() {
51105         this.singulars = [];
51106     },
51107     
51108     
51109     clearPlurals: function() {
51110         this.plurals = [];
51111     },
51112     
51113     
51114     isTransnumeral: function(word) {
51115         return Ext.Array.indexOf(this.uncountable, word) != -1;
51116     },
51117
51118     
51119     pluralize: function(word) {
51120         if (this.isTransnumeral(word)) {
51121             return word;
51122         }
51123
51124         var plurals = this.plurals,
51125             length  = plurals.length,
51126             tuple, regex, i;
51127         
51128         for (i = 0; i < length; i++) {
51129             tuple = plurals[i];
51130             regex = tuple[0];
51131             
51132             if (regex == word || (regex.test && regex.test(word))) {
51133                 return word.replace(regex, tuple[1]);
51134             }
51135         }
51136         
51137         return word;
51138     },
51139     
51140     
51141     singularize: function(word) {
51142         if (this.isTransnumeral(word)) {
51143             return word;
51144         }
51145
51146         var singulars = this.singulars,
51147             length    = singulars.length,
51148             tuple, regex, i;
51149         
51150         for (i = 0; i < length; i++) {
51151             tuple = singulars[i];
51152             regex = tuple[0];
51153             
51154             if (regex == word || (regex.test && regex.test(word))) {
51155                 return word.replace(regex, tuple[1]);
51156             }
51157         }
51158         
51159         return word;
51160     },
51161     
51162     
51163     classify: function(word) {
51164         return Ext.String.capitalize(this.singularize(word));
51165     },
51166     
51167     
51168     ordinalize: function(number) {
51169         var parsed = parseInt(number, 10),
51170             mod10  = parsed % 10,
51171             mod100 = parsed % 100;
51172         
51173         
51174         if (11 <= mod100 && mod100 <= 13) {
51175             return number + "th";
51176         } else {
51177             switch(mod10) {
51178                 case 1 : return number + "st";
51179                 case 2 : return number + "nd";
51180                 case 3 : return number + "rd";
51181                 default: return number + "th";
51182             }
51183         }
51184     }
51185 }, function() {
51186     
51187     var irregulars = {
51188             alumnus: 'alumni',
51189             cactus : 'cacti',
51190             focus  : 'foci',
51191             nucleus: 'nuclei',
51192             radius: 'radii',
51193             stimulus: 'stimuli',
51194             ellipsis: 'ellipses',
51195             paralysis: 'paralyses',
51196             oasis: 'oases',
51197             appendix: 'appendices',
51198             index: 'indexes',
51199             beau: 'beaux',
51200             bureau: 'bureaux',
51201             tableau: 'tableaux',
51202             woman: 'women',
51203             child: 'children',
51204             man: 'men',
51205             corpus:     'corpora',
51206             criterion: 'criteria',
51207             curriculum: 'curricula',
51208             genus: 'genera',
51209             memorandum: 'memoranda',
51210             phenomenon: 'phenomena',
51211             foot: 'feet',
51212             goose: 'geese',
51213             tooth: 'teeth',
51214             antenna: 'antennae',
51215             formula: 'formulae',
51216             nebula: 'nebulae',
51217             vertebra: 'vertebrae',
51218             vita: 'vitae'
51219         },
51220         singular;
51221     
51222     for (singular in irregulars) {
51223         this.plural(singular, irregulars[singular]);
51224         this.singular(irregulars[singular], singular);
51225     }
51226 });
51227
51228 Ext.define('Ext.data.HasManyAssociation', {
51229     extend: 'Ext.data.Association',
51230     requires: ['Ext.util.Inflector'],
51231
51232     alias: 'association.hasmany',
51233
51234     
51235     
51236     
51237     
51238     
51239     
51240     
51241     
51242     
51243     
51244     
51245     
51246     constructor: function(config) {
51247         var me = this,
51248             ownerProto,
51249             name;
51250             
51251         me.callParent(arguments);
51252         
51253         me.name = me.name || Ext.util.Inflector.pluralize(me.associatedName.toLowerCase());
51254         
51255         ownerProto = me.ownerModel.prototype;
51256         name = me.name;
51257         
51258         Ext.applyIf(me, {
51259             storeName : name + "Store",
51260             foreignKey: me.ownerName.toLowerCase() + "_id"
51261         });
51262         
51263         ownerProto[name] = me.createStore();
51264     },
51265     
51266     
51267     createStore: function() {
51268         var that            = this,
51269             associatedModel = that.associatedModel,
51270             storeName       = that.storeName,
51271             foreignKey      = that.foreignKey,
51272             primaryKey      = that.primaryKey,
51273             filterProperty  = that.filterProperty,
51274             autoLoad        = that.autoLoad,
51275             storeConfig     = that.storeConfig || {};
51276         
51277         return function() {
51278             var me = this,
51279                 config, filter,
51280                 modelDefaults = {};
51281                 
51282             if (me[storeName] === undefined) {
51283                 if (filterProperty) {
51284                     filter = {
51285                         property  : filterProperty,
51286                         value     : me.get(filterProperty),
51287                         exactMatch: true
51288                     };
51289                 } else {
51290                     filter = {
51291                         property  : foreignKey,
51292                         value     : me.get(primaryKey),
51293                         exactMatch: true
51294                     };
51295                 }
51296                 
51297                 modelDefaults[foreignKey] = me.get(primaryKey);
51298                 
51299                 config = Ext.apply({}, storeConfig, {
51300                     model        : associatedModel,
51301                     filters      : [filter],
51302                     remoteFilter : false,
51303                     modelDefaults: modelDefaults
51304                 });
51305                 
51306                 me[storeName] = Ext.create('Ext.data.Store', config);
51307                 if (autoLoad) {
51308                     me[storeName].load();
51309                 }
51310             }
51311             
51312             return me[storeName];
51313         };
51314     },
51315     
51316     
51317     read: function(record, reader, associationData){
51318         var store = record[this.name](),
51319             inverse;
51320     
51321         store.add(reader.read(associationData).records);
51322     
51323         
51324         
51325         inverse = this.associatedModel.prototype.associations.findBy(function(assoc){
51326             return assoc.type === 'belongsTo' && assoc.associatedName === record.$className;
51327         });
51328     
51329         
51330         if (inverse) {
51331             store.data.each(function(associatedRecord){
51332                 associatedRecord[inverse.instanceName] = record;
51333             });
51334         }
51335     }
51336 });
51337
51338 Ext.define('Ext.data.JsonP', {
51339     
51340     
51341     
51342     singleton: true,
51343     
51344     statics: {
51345         requestCount: 0,
51346         requests: {}
51347     },
51348     
51349     
51350     
51351     
51352     timeout: 30000,
51353     
51354     
51355     disableCaching: true,
51356    
51357     
51358     disableCachingParam: '_dc',
51359    
51360     
51361     callbackKey: 'callback',
51362    
51363     
51364     request: function(options){
51365         options = Ext.apply({}, options);
51366        
51367         if (!options.url) {
51368             Ext.Error.raise('A url must be specified for a JSONP request.');
51369         }
51370         
51371         var me = this, 
51372             disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching, 
51373             cacheParam = options.disableCachingParam || me.disableCachingParam, 
51374             id = ++me.statics().requestCount, 
51375             callbackName = options.callbackName || 'callback' + id, 
51376             callbackKey = options.callbackKey || me.callbackKey, 
51377             timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout, 
51378             params = Ext.apply({}, options.params), 
51379             url = options.url,
51380             request, 
51381             script;
51382             
51383         params[callbackKey] = 'Ext.data.JsonP.' + callbackName;
51384         if (disableCaching) {
51385             params[cacheParam] = new Date().getTime();
51386         }
51387         
51388         script = me.createScript(url, params);
51389         
51390         me.statics().requests[id] = request = {
51391             url: url,
51392             params: params,
51393             script: script,
51394             id: id,
51395             scope: options.scope,
51396             success: options.success,
51397             failure: options.failure,
51398             callback: options.callback,
51399             callbackName: callbackName
51400         };
51401         
51402         if (timeout > 0) {
51403             request.timeout = setTimeout(Ext.bind(me.handleTimeout, me, [request]), timeout);
51404         }
51405         
51406         me.setupErrorHandling(request);
51407         me[callbackName] = Ext.bind(me.handleResponse, me, [request], true);
51408         Ext.getHead().appendChild(script);
51409         return request;
51410     },
51411     
51412     
51413     abort: function(request){
51414         var requests = this.statics().requests,
51415             key;
51416             
51417         if (request) {
51418             if (!request.id) {
51419                 request = requests[request];
51420             }
51421             this.abort(request);
51422         } else {
51423             for (key in requests) {
51424                 if (requests.hasOwnProperty(key)) {
51425                     this.abort(requests[key]);
51426                 }
51427             }
51428         }
51429     },
51430     
51431     
51432     setupErrorHandling: function(request){
51433         request.script.onerror = Ext.bind(this.handleError, this, [request]);
51434     },
51435     
51436     
51437     handleAbort: function(request){
51438         request.errorType = 'abort';
51439         this.handleResponse(null, request);
51440     },
51441     
51442     
51443     handleError: function(request){
51444         request.errorType = 'error';
51445         this.handleResponse(null, request);
51446     },
51447  
51448     
51449     cleanupErrorHandling: function(request){
51450         request.script.onerror = null;
51451     },
51452  
51453     
51454     handleTimeout: function(request){
51455         request.errorType = 'timeout';
51456         this.handleResponse(null, request);
51457     },
51458  
51459     
51460     handleResponse: function(result, request){
51461  
51462         var success = true;
51463  
51464         if (request.timeout) {
51465             clearTimeout(request.timeout);
51466         }
51467         delete this[request.callbackName];
51468         delete this.statics()[request.id];
51469         this.cleanupErrorHandling(request);
51470         Ext.fly(request.script).remove();
51471  
51472         if (request.errorType) {
51473             success = false;
51474             Ext.callback(request.failure, request.scope, [request.errorType]);
51475         } else {
51476             Ext.callback(request.success, request.scope, [result]);
51477         }
51478         Ext.callback(request.callback, request.scope, [success, result, request.errorType]);
51479     },
51480     
51481     
51482     createScript: function(url, params) {
51483         var script = document.createElement('script');
51484         script.setAttribute("src", Ext.urlAppend(url, Ext.Object.toQueryString(params)));
51485         script.setAttribute("async", true);
51486         script.setAttribute("type", "text/javascript");
51487         return script;
51488     }
51489 });
51490
51491
51492 Ext.define('Ext.data.JsonPStore', {
51493     extend: 'Ext.data.Store',
51494     alias : 'store.jsonp',
51495
51496     
51497     constructor: function(config) {
51498         this.callParent(Ext.apply(config, {
51499             reader: Ext.create('Ext.data.reader.Json', config),
51500             proxy : Ext.create('Ext.data.proxy.JsonP', config)
51501         }));
51502     }
51503 });
51504
51505
51506 Ext.define('Ext.data.NodeInterface', {
51507     requires: ['Ext.data.Field'],
51508     
51509     statics: {
51510         
51511         decorate: function(record) {
51512             if (!record.isNode) {
51513                 
51514                 
51515                 var mgr = Ext.ModelManager,
51516                     modelName = record.modelName,
51517                     modelClass = mgr.getModel(modelName),
51518                     idName = modelClass.prototype.idProperty,
51519                     instances = Ext.Array.filter(mgr.all.getArray(), function(item) {
51520                         return item.modelName == modelName;
51521                     }),
51522                     iln = instances.length,
51523                     newFields = [],
51524                     i, instance, jln, j, newField;
51525
51526                 
51527                 modelClass.override(this.getPrototypeBody());
51528                 newFields = this.applyFields(modelClass, [
51529                     {name: idName,      type: 'string',  defaultValue: null},
51530                     {name: 'parentId',  type: 'string',  defaultValue: null},
51531                     {name: 'index',     type: 'int',     defaultValue: null},
51532                     {name: 'depth',     type: 'int',     defaultValue: 0}, 
51533                     {name: 'expanded',  type: 'bool',    defaultValue: false, persist: false},
51534                     {name: 'checked',   type: 'auto',    defaultValue: null},
51535                     {name: 'leaf',      type: 'bool',    defaultValue: false, persist: false},
51536                     {name: 'cls',       type: 'string',  defaultValue: null, persist: false},
51537                     {name: 'iconCls',   type: 'string',  defaultValue: null, persist: false},
51538                     {name: 'root',      type: 'boolean', defaultValue: false, persist: false},
51539                     {name: 'isLast',    type: 'boolean', defaultValue: false, persist: false},
51540                     {name: 'isFirst',   type: 'boolean', defaultValue: false, persist: false},
51541                     {name: 'allowDrop', type: 'boolean', defaultValue: true, persist: false},
51542                     {name: 'allowDrag', type: 'boolean', defaultValue: true, persist: false},
51543                     {name: 'loaded',    type: 'boolean', defaultValue: false, persist: false},
51544                     {name: 'loading',   type: 'boolean', defaultValue: false, persist: false},
51545                     {name: 'href',      type: 'string',  defaultValue: null, persist: false},
51546                     {name: 'hrefTarget',type: 'string',  defaultValue: null, persist: false},
51547                     {name: 'qtip',      type: 'string',  defaultValue: null, persist: false},
51548                     {name: 'qtitle',    type: 'string',  defaultValue: null, persist: false}
51549                 ]);
51550
51551                 jln = newFields.length;
51552                 
51553                 for (i = 0; i < iln; i++) {
51554                     instance = instances[i];
51555                     for (j = 0; j < jln; j++) {
51556                         newField = newFields[j];
51557                         if (instance.get(newField.name) === undefined) {
51558                             instance.data[newField.name] = newField.defaultValue;
51559                         }
51560                     }
51561                 }
51562             }
51563             
51564             Ext.applyIf(record, {
51565                 firstChild: null,
51566                 lastChild: null,
51567                 parentNode: null,
51568                 previousSibling: null,
51569                 nextSibling: null,
51570                 childNodes: []
51571             });
51572             
51573             record.commit(true);
51574             
51575             record.enableBubble([
51576                 
51577                 "append",
51578
51579                 
51580                 "remove",
51581
51582                 
51583                 "move",
51584
51585                 
51586                 "insert",
51587
51588                 
51589                 "beforeappend",
51590
51591                 
51592                 "beforeremove",
51593
51594                 
51595                 "beforemove",
51596
51597                  
51598                 "beforeinsert",
51599                 
51600                 
51601                 "expand",
51602                 
51603                 
51604                 "collapse",
51605                 
51606                 
51607                 "beforeexpand",
51608                 
51609                 
51610                 "beforecollapse",
51611                 
51612                 
51613                 "sort"
51614             ]);
51615             
51616             return record;
51617         },
51618         
51619         applyFields: function(modelClass, addFields) {
51620             var modelPrototype = modelClass.prototype,
51621                 fields = modelPrototype.fields,
51622                 keys = fields.keys,
51623                 ln = addFields.length,
51624                 addField, i, name,
51625                 newFields = [];
51626                 
51627             for (i = 0; i < ln; i++) {
51628                 addField = addFields[i];
51629                 if (!Ext.Array.contains(keys, addField.name)) {
51630                     addField = Ext.create('data.field', addField);
51631                     
51632                     newFields.push(addField);
51633                     fields.add(addField);
51634                 }
51635             }
51636             
51637             return newFields;
51638         },
51639         
51640         getPrototypeBody: function() {
51641             return {
51642                 isNode: true,
51643
51644                 
51645                 createNode: function(node) {
51646                     if (Ext.isObject(node) && !node.isModel) {
51647                         node = Ext.ModelManager.create(node, this.modelName);
51648                     }
51649                     
51650                     return Ext.data.NodeInterface.decorate(node);
51651                 },
51652                 
51653                 
51654                 isLeaf : function() {
51655                     return this.get('leaf') === true;
51656                 },
51657
51658                 
51659                 setFirstChild : function(node) {
51660                     this.firstChild = node;
51661                 },
51662
51663                 
51664                 setLastChild : function(node) {
51665                     this.lastChild = node;
51666                 },
51667
51668                 
51669                 updateInfo: function(silent) {
51670                     var me = this,
51671                         isRoot = me.isRoot(),
51672                         parentNode = me.parentNode,
51673                         isFirst = (!parentNode ? true : parentNode.firstChild == me),
51674                         isLast = (!parentNode ? true : parentNode.lastChild == me),
51675                         depth = 0,
51676                         parent = me,
51677                         children = me.childNodes,
51678                         len = children.length,
51679                         i = 0;
51680
51681                     while (parent.parentNode) {
51682                         ++depth;
51683                         parent = parent.parentNode;
51684                     }                                            
51685                     
51686                     me.beginEdit();
51687                     me.set({
51688                         isFirst: isFirst,
51689                         isLast: isLast,
51690                         depth: depth,
51691                         index: parentNode ? parentNode.indexOf(me) : 0,
51692                         parentId: parentNode ? parentNode.getId() : null
51693                     });
51694                     me.endEdit(silent);
51695                     if (silent) {
51696                         me.commit();
51697                     }
51698                     
51699                     for (i = 0; i < len; i++) {
51700                         children[i].updateInfo(silent);
51701                     }
51702                 },
51703
51704                 
51705                 isLast : function() {
51706                    return this.get('isLast');
51707                 },
51708
51709                 
51710                 isFirst : function() {
51711                    return this.get('isFirst');
51712                 },
51713
51714                 
51715                 hasChildNodes : function() {
51716                     return !this.isLeaf() && this.childNodes.length > 0;
51717                 },
51718
51719                 
51720                 isExpandable : function() {
51721                     return this.get('expandable') || this.hasChildNodes();
51722                 },
51723
51724                 
51725                 appendChild : function(node, suppressEvents, suppressNodeUpdate) {
51726                     var me = this,
51727                         i, ln,
51728                         index,
51729                         oldParent,
51730                         ps;
51731
51732                     
51733                     if (Ext.isArray(node)) {
51734                         for (i = 0, ln = node.length; i < ln; i++) {
51735                             me.appendChild(node[i]);
51736                         }
51737                     } else {
51738                         
51739                         node = me.createNode(node);
51740                         
51741                         if (suppressEvents !== true && me.fireEvent("beforeappend", me, node) === false) {
51742                             return false;                         
51743                         }
51744
51745                         index = me.childNodes.length;
51746                         oldParent = node.parentNode;
51747
51748                         
51749                         if (oldParent) {
51750                             if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index) === false) {
51751                                 return false;
51752                             }
51753                             oldParent.removeChild(node, null, false, true);
51754                         }
51755
51756                         index = me.childNodes.length;
51757                         if (index === 0) {
51758                             me.setFirstChild(node);
51759                         }
51760
51761                         me.childNodes.push(node);
51762                         node.parentNode = me;
51763                         node.nextSibling = null;
51764
51765                         me.setLastChild(node);
51766                                                 
51767                         ps = me.childNodes[index - 1];
51768                         if (ps) {
51769                             node.previousSibling = ps;
51770                             ps.nextSibling = node;
51771                             ps.updateInfo(suppressNodeUpdate);
51772                         } else {
51773                             node.previousSibling = null;
51774                         }
51775
51776                         node.updateInfo(suppressNodeUpdate);
51777                         
51778                         
51779                         if (!me.isLoaded()) {
51780                             me.set('loaded', true);                            
51781                         }
51782                         
51783                         else if (me.childNodes.length === 1) {
51784                             me.set('loaded', me.isLoaded());
51785                         }
51786                         
51787                         if (suppressEvents !== true) {
51788                             me.fireEvent("append", me, node, index);
51789
51790                             if (oldParent) {
51791                                 node.fireEvent("move", node, oldParent, me, index);
51792                             }                            
51793                         }
51794
51795                         return node;
51796                     }
51797                 },
51798                 
51799                 
51800                 getBubbleTarget: function() {
51801                     return this.parentNode;
51802                 },
51803
51804                 
51805                 removeChild : function(node, destroy, suppressEvents, suppressNodeUpdate) {
51806                     var me = this,
51807                         index = me.indexOf(node);
51808                     
51809                     if (index == -1 || (suppressEvents !== true && me.fireEvent("beforeremove", me, node) === false)) {
51810                         return false;
51811                     }
51812
51813                     
51814                     me.childNodes.splice(index, 1);
51815
51816                     
51817                     if (me.firstChild == node) {
51818                         me.setFirstChild(node.nextSibling);
51819                     }
51820                     if (me.lastChild == node) {
51821                         me.setLastChild(node.previousSibling);
51822                     }
51823                     
51824                     
51825                     if (node.previousSibling) {
51826                         node.previousSibling.nextSibling = node.nextSibling;
51827                         node.previousSibling.updateInfo(suppressNodeUpdate);
51828                     }
51829                     if (node.nextSibling) {
51830                         node.nextSibling.previousSibling = node.previousSibling;
51831                         node.nextSibling.updateInfo(suppressNodeUpdate);
51832                     }
51833
51834                     if (suppressEvents !== true) {
51835                         me.fireEvent("remove", me, node);
51836                     }
51837                     
51838                     
51839                     
51840                     if (!me.childNodes.length) {
51841                         me.set('loaded', me.isLoaded());
51842                     }
51843                     
51844                     if (destroy) {
51845                         node.destroy(true);
51846                     } else {
51847                         node.clear();
51848                     }
51849
51850                     return node;
51851                 },
51852
51853                 
51854                 copy: function(newId, deep) {
51855                     var me = this,
51856                         result = me.callOverridden(arguments),
51857                         len = me.childNodes ? me.childNodes.length : 0,
51858                         i;
51859
51860                     
51861                     if (deep) {
51862                         for (i = 0; i < len; i++) {
51863                             result.appendChild(me.childNodes[i].copy(true));
51864                         }
51865                     }
51866                     return result;
51867                 },
51868
51869                 
51870                 clear : function(destroy) {
51871                     var me = this;
51872                     
51873                     
51874                     me.parentNode = me.previousSibling = me.nextSibling = null;
51875                     if (destroy) {
51876                         me.firstChild = me.lastChild = null;
51877                     }
51878                 },
51879
51880                 
51881                 destroy : function(silent) {
51882                     
51883                     var me = this,
51884                         options = me.destroyOptions;
51885                     
51886                     if (silent === true) {
51887                         me.clear(true);
51888                         Ext.each(me.childNodes, function(n) {
51889                             n.destroy(true);
51890                         });
51891                         me.childNodes = null;
51892                         delete me.destroyOptions;
51893                         me.callOverridden([options]);
51894                     } else {
51895                         me.destroyOptions = silent;
51896                         
51897                         me.remove(true);
51898                     }
51899                 },
51900
51901                 
51902                 insertBefore : function(node, refNode, suppressEvents) {
51903                     var me = this,
51904                         index     = me.indexOf(refNode),
51905                         oldParent = node.parentNode,
51906                         refIndex  = index,
51907                         ps;
51908                     
51909                     if (!refNode) { 
51910                         return me.appendChild(node);
51911                     }
51912                     
51913                     
51914                     if (node == refNode) {
51915                         return false;
51916                     }
51917
51918                     
51919                     node = me.createNode(node);
51920                     
51921                     if (suppressEvents !== true && me.fireEvent("beforeinsert", me, node, refNode) === false) {
51922                         return false;
51923                     }
51924                     
51925                     
51926                     if (oldParent == me && me.indexOf(node) < index) {
51927                         refIndex--;
51928                     }
51929
51930                     
51931                     if (oldParent) {
51932                         if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index, refNode) === false) {
51933                             return false;
51934                         }
51935                         oldParent.removeChild(node);
51936                     }
51937
51938                     if (refIndex === 0) {
51939                         me.setFirstChild(node);
51940                     }
51941
51942                     me.childNodes.splice(refIndex, 0, node);
51943                     node.parentNode = me;
51944                     
51945                     node.nextSibling = refNode;
51946                     refNode.previousSibling = node;
51947                     
51948                     ps = me.childNodes[refIndex - 1];
51949                     if (ps) {
51950                         node.previousSibling = ps;
51951                         ps.nextSibling = node;
51952                         ps.updateInfo();
51953                     } else {
51954                         node.previousSibling = null;
51955                     }
51956                     
51957                     node.updateInfo();
51958                     
51959                     if (!me.isLoaded()) {
51960                         me.set('loaded', true);                            
51961                     }    
51962                     
51963                     else if (me.childNodes.length === 1) {
51964                         me.set('loaded', me.isLoaded());
51965                     }
51966
51967                     if (suppressEvents !== true) {
51968                         me.fireEvent("insert", me, node, refNode);
51969
51970                         if (oldParent) {
51971                             node.fireEvent("move", node, oldParent, me, refIndex, refNode);
51972                         }                        
51973                     }
51974
51975                     return node;
51976                 },
51977                 
51978                     
51979                 insertChild: function(index, node) {
51980                     var sibling = this.childNodes[index];
51981                     if (sibling) {
51982                         return this.insertBefore(node, sibling);
51983                     }
51984                     else {
51985                         return this.appendChild(node);
51986                     }
51987                 },
51988
51989                 
51990                 remove : function(destroy, suppressEvents) {
51991                     var parentNode = this.parentNode;
51992
51993                     if (parentNode) {
51994                         parentNode.removeChild(this, destroy, suppressEvents, true);
51995                     }
51996                     return this;
51997                 },
51998
51999                 
52000                 removeAll : function(destroy, suppressEvents) {
52001                     var cn = this.childNodes,
52002                         n;
52003
52004                     while ((n = cn[0])) {
52005                         this.removeChild(n, destroy, suppressEvents);
52006                     }
52007                     return this;
52008                 },
52009
52010                 
52011                 getChildAt : function(index) {
52012                     return this.childNodes[index];
52013                 },
52014
52015                 
52016                 replaceChild : function(newChild, oldChild, suppressEvents) {
52017                     var s = oldChild ? oldChild.nextSibling : null;
52018                     
52019                     this.removeChild(oldChild, suppressEvents);
52020                     this.insertBefore(newChild, s, suppressEvents);
52021                     return oldChild;
52022                 },
52023
52024                 
52025                 indexOf : function(child) {
52026                     return Ext.Array.indexOf(this.childNodes, child);
52027                 },
52028
52029                 
52030                 getDepth : function() {
52031                     return this.get('depth');
52032                 },
52033
52034                 
52035                 bubble : function(fn, scope, args) {
52036                     var p = this;
52037                     while (p) {
52038                         if (fn.apply(scope || p, args || [p]) === false) {
52039                             break;
52040                         }
52041                         p = p.parentNode;
52042                     }
52043                 },
52044
52045                 cascade: function() {
52046                     if (Ext.isDefined(Ext.global.console)) {
52047                         Ext.global.console.warn('Ext.data.Node: cascade has been deprecated. Please use cascadeBy instead.');
52048                     }
52049                     return this.cascadeBy.apply(this, arguments);
52050                 },
52051
52052                 
52053                 cascadeBy : function(fn, scope, args) {
52054                     if (fn.apply(scope || this, args || [this]) !== false) {
52055                         var childNodes = this.childNodes,
52056                             length     = childNodes.length,
52057                             i;
52058
52059                         for (i = 0; i < length; i++) {
52060                             childNodes[i].cascadeBy(fn, scope, args);
52061                         }
52062                     }
52063                 },
52064
52065                 
52066                 eachChild : function(fn, scope, args) {
52067                     var childNodes = this.childNodes,
52068                         length     = childNodes.length,
52069                         i;
52070
52071                     for (i = 0; i < length; i++) {
52072                         if (fn.apply(scope || this, args || [childNodes[i]]) === false) {
52073                             break;
52074                         }
52075                     }
52076                 },
52077
52078                 
52079                 findChild : function(attribute, value, deep) {
52080                     return this.findChildBy(function() {
52081                         return this.get(attribute) == value;
52082                     }, null, deep);
52083                 },
52084
52085                 
52086                 findChildBy : function(fn, scope, deep) {
52087                     var cs = this.childNodes,
52088                         len = cs.length,
52089                         i = 0, n, res;
52090
52091                     for (; i < len; i++) {
52092                         n = cs[i];
52093                         if (fn.call(scope || n, n) === true) {
52094                             return n;
52095                         }
52096                         else if (deep) {
52097                             res = n.findChildBy(fn, scope, deep);
52098                             if (res !== null) {
52099                                 return res;
52100                             }
52101                         }
52102                     }
52103
52104                     return null;
52105                 },
52106
52107                 
52108                 contains : function(node) {
52109                     return node.isAncestor(this);
52110                 },
52111
52112                 
52113                 isAncestor : function(node) {
52114                     var p = this.parentNode;
52115                     while (p) {
52116                         if (p == node) {
52117                             return true;
52118                         }
52119                         p = p.parentNode;
52120                     }
52121                     return false;
52122                 },
52123
52124                 
52125                 sort : function(sortFn, recursive, suppressEvent) {
52126                     var cs  = this.childNodes,
52127                         ln = cs.length,
52128                         i, n;
52129                     
52130                     if (ln > 0) {
52131                         Ext.Array.sort(cs, sortFn);
52132                         for (i = 0; i < ln; i++) {
52133                             n = cs[i];
52134                             n.previousSibling = cs[i-1];
52135                             n.nextSibling = cs[i+1];
52136                         
52137                             if (i === 0) {
52138                                 this.setFirstChild(n);
52139                                 n.updateInfo();
52140                             }
52141                             if (i == ln - 1) {
52142                                 this.setLastChild(n);
52143                                 n.updateInfo();
52144                             }
52145                             if (recursive && !n.isLeaf()) {
52146                                 n.sort(sortFn, true, true);
52147                             }
52148                         }
52149                         
52150                         if (suppressEvent !== true) {
52151                             this.fireEvent('sort', this, cs);
52152                         }
52153                     }
52154                 },
52155                         
52156                         
52157                 isExpanded: function() {
52158                     return this.get('expanded');
52159                 },
52160                 
52161                  
52162                 isLoaded: function() {
52163                     return this.get('loaded');
52164                 },
52165
52166                  
52167                 isLoading: function() {
52168                     return this.get('loading');
52169                 },
52170                                 
52171                  
52172                 isRoot: function() {
52173                     return !this.parentNode;
52174                 },
52175                 
52176                  
52177                 isVisible: function() {
52178                     var parent = this.parentNode;
52179                     while (parent) {
52180                         if (!parent.isExpanded()) {
52181                             return false;
52182                         }
52183                         parent = parent.parentNode;
52184                     }
52185                     return true;
52186                 },
52187                 
52188                 
52189                 expand: function(recursive, callback, scope) {
52190                     var me = this;
52191
52192                     
52193                     
52194
52195                     
52196                     if (!me.isLeaf()) {
52197                         
52198                         if (!me.isLoading() && !me.isExpanded()) {
52199                             
52200                             
52201                             
52202                             
52203                             me.fireEvent('beforeexpand', me, function(records) {
52204                                 me.set('expanded', true); 
52205                                 me.fireEvent('expand', me, me.childNodes, false);
52206                                 
52207                                 
52208                                 if (recursive) {
52209                                     me.expandChildren(true, callback, scope);
52210                                 }
52211                                 else {
52212                                     Ext.callback(callback, scope || me, [me.childNodes]);                                
52213                                 }
52214                             }, me);                            
52215                         }
52216                         
52217                         else if (recursive) {
52218                             me.expandChildren(true, callback, scope);
52219                         }
52220                         else {
52221                             Ext.callback(callback, scope || me, [me.childNodes]);
52222                         }
52223
52224                         
52225                         
52226                         
52227                     }
52228                     
52229                     else {
52230                         Ext.callback(callback, scope || me); 
52231                     }
52232                 },
52233                 
52234                 
52235                 expandChildren: function(recursive, callback, scope) {
52236                     var me = this,
52237                         i = 0,
52238                         nodes = me.childNodes,
52239                         ln = nodes.length,
52240                         node,
52241                         expanding = 0;
52242
52243                     for (; i < ln; ++i) {
52244                         node = nodes[i];
52245                         if (!node.isLeaf() && !node.isExpanded()) {
52246                             expanding++;
52247                             nodes[i].expand(recursive, function () {
52248                                 expanding--;
52249                                 if (callback && !expanding) {
52250                                     Ext.callback(callback, scope || me, me.childNodes); 
52251                                 }
52252                             });                            
52253                         }
52254                     }
52255                     
52256                     if (!expanding && callback) {
52257                         Ext.callback(callback, scope || me, me.childNodes);
52258                     }
52259                 },
52260
52261                 
52262                 collapse: function(recursive, callback, scope) {
52263                     var me = this;
52264
52265                     
52266                     if (!me.isLeaf()) {
52267                         
52268                         if (!me.collapsing && me.isExpanded()) {
52269                             me.fireEvent('beforecollapse', me, function(records) {
52270                                 me.set('expanded', false); 
52271                                 me.fireEvent('collapse', me, me.childNodes, false);
52272                                 
52273                                 
52274                                 if (recursive) {
52275                                     me.collapseChildren(true, callback, scope);
52276                                 }
52277                                 else {
52278                                     Ext.callback(callback, scope || me, [me.childNodes]);                                
52279                                 }
52280                             }, me);                            
52281                         }
52282                         
52283                         else if (recursive) {
52284                             me.collapseChildren(true, callback, scope);
52285                         }
52286                     }
52287                     
52288                     else {
52289                         Ext.callback(callback, scope || me, me.childNodes); 
52290                     }
52291                 },
52292                 
52293                 
52294                 collapseChildren: function(recursive, callback, scope) {
52295                     var me = this,
52296                         i = 0,
52297                         nodes = me.childNodes,
52298                         ln = nodes.length,
52299                         node,
52300                         collapsing = 0;
52301
52302                     for (; i < ln; ++i) {
52303                         node = nodes[i];
52304                         if (!node.isLeaf() && node.isExpanded()) {
52305                             collapsing++;
52306                             nodes[i].collapse(recursive, function () {
52307                                 collapsing--;
52308                                 if (callback && !collapsing) {
52309                                     Ext.callback(callback, scope || me, me.childNodes); 
52310                                 }
52311                             });                            
52312                         }
52313                     }
52314                     
52315                     if (!collapsing && callback) {
52316                         Ext.callback(callback, scope || me, me.childNodes);
52317                     }
52318                 }
52319             };
52320         }
52321     }
52322 });
52323
52324 Ext.define('Ext.data.NodeStore', {
52325     extend: 'Ext.data.Store',
52326     alias: 'store.node',
52327     requires: ['Ext.data.NodeInterface'],
52328     
52329     
52330     node: null,
52331     
52332     
52333     recursive: false,
52334     
52335         
52336     rootVisible: false,
52337     
52338     constructor: function(config) {
52339         var me = this,
52340             node;
52341             
52342         config = config || {};
52343         Ext.apply(me, config);
52344         
52345         if (Ext.isDefined(me.proxy)) {
52346             Ext.Error.raise("A NodeStore cannot be bound to a proxy. Instead bind it to a record " +
52347                             "decorated with the NodeInterface by setting the node config.");
52348         }
52349
52350         config.proxy = {type: 'proxy'};
52351         me.callParent([config]);
52352
52353         me.addEvents('expand', 'collapse', 'beforeexpand', 'beforecollapse');
52354         
52355         node = me.node;
52356         if (node) {
52357             me.node = null;
52358             me.setNode(node);
52359         }
52360     },
52361     
52362     setNode: function(node) {
52363         var me = this;
52364         
52365         if (me.node && me.node != node) {
52366             
52367             me.mun(me.node, {
52368                 expand: me.onNodeExpand,
52369                 collapse: me.onNodeCollapse,
52370                 append: me.onNodeAppend,
52371                 insert: me.onNodeInsert,
52372                 remove: me.onNodeRemove,
52373                 sort: me.onNodeSort,
52374                 scope: me
52375             });
52376             me.node = null;
52377         }
52378         
52379         if (node) {
52380             Ext.data.NodeInterface.decorate(node);
52381             me.removeAll();
52382             if (me.rootVisible) {
52383                 me.add(node);
52384             }
52385             me.mon(node, {
52386                 expand: me.onNodeExpand,
52387                 collapse: me.onNodeCollapse,
52388                 append: me.onNodeAppend,
52389                 insert: me.onNodeInsert,
52390                 remove: me.onNodeRemove,
52391                 sort: me.onNodeSort,
52392                 scope: me
52393             });
52394             me.node = node;
52395             if (node.isExpanded() && node.isLoaded()) {
52396                 me.onNodeExpand(node, node.childNodes, true);
52397             }
52398         }
52399     },
52400     
52401     onNodeSort: function(node, childNodes) {
52402         var me = this;
52403         
52404         if ((me.indexOf(node) !== -1 || (node === me.node && !me.rootVisible) && node.isExpanded())) {
52405             me.onNodeCollapse(node, childNodes, true);
52406             me.onNodeExpand(node, childNodes, true);
52407         }
52408     },
52409     
52410     onNodeExpand: function(parent, records, suppressEvent) {
52411         var me = this,
52412             insertIndex = me.indexOf(parent) + 1,
52413             ln = records ? records.length : 0,
52414             i, record;
52415             
52416         if (!me.recursive && parent !== me.node) {
52417             return;
52418         }
52419         
52420         if (!me.isVisible(parent)) {
52421             return;
52422         }
52423
52424         if (!suppressEvent && me.fireEvent('beforeexpand', parent, records, insertIndex) === false) {
52425             return;
52426         }
52427         
52428         if (ln) {
52429             me.insert(insertIndex, records);
52430             for (i = 0; i < ln; i++) {
52431                 record = records[i];
52432                 if (record.isExpanded()) {
52433                     if (record.isLoaded()) {
52434                         
52435                         me.onNodeExpand(record, record.childNodes, true);
52436                     }
52437                     else {
52438                         record.set('expanded', false);
52439                         record.expand();
52440                     }
52441                 }
52442             }
52443         }
52444
52445         if (!suppressEvent) {
52446             me.fireEvent('expand', parent, records);
52447         }
52448     },
52449
52450     onNodeCollapse: function(parent, records, suppressEvent) {
52451         var me = this,
52452             ln = records.length,
52453             collapseIndex = me.indexOf(parent) + 1,
52454             i, record;
52455             
52456         if (!me.recursive && parent !== me.node) {
52457             return;
52458         }
52459         
52460         if (!suppressEvent && me.fireEvent('beforecollapse', parent, records, collapseIndex) === false) {
52461             return;
52462         }
52463
52464         for (i = 0; i < ln; i++) {
52465             record = records[i];
52466             me.remove(record);
52467             if (record.isExpanded()) {
52468                 me.onNodeCollapse(record, record.childNodes, true);
52469             }
52470         }
52471         
52472         if (!suppressEvent) {
52473             me.fireEvent('collapse', parent, records, collapseIndex);
52474         }
52475     },
52476     
52477     onNodeAppend: function(parent, node, index) {
52478         var me = this,
52479             refNode, sibling;
52480
52481         if (me.isVisible(node)) {
52482             if (index === 0) {
52483                 refNode = parent;
52484             } else {
52485                 sibling = node.previousSibling;
52486                 while (sibling.isExpanded() && sibling.lastChild) {
52487                     sibling = sibling.lastChild;
52488                 }
52489                 refNode = sibling;
52490             }
52491             me.insert(me.indexOf(refNode) + 1, node);
52492             if (!node.isLeaf() && node.isExpanded()) {
52493                 if (node.isLoaded()) {
52494                     
52495                     me.onNodeExpand(node, node.childNodes, true);
52496                 }
52497                 else {
52498                     node.set('expanded', false);
52499                     node.expand();
52500                 }
52501             }
52502         } 
52503     },
52504     
52505     onNodeInsert: function(parent, node, refNode) {
52506         var me = this,
52507             index = this.indexOf(refNode);
52508             
52509         if (index != -1 && me.isVisible(node)) {
52510             me.insert(index, node);
52511             if (!node.isLeaf() && node.isExpanded()) {
52512                 if (node.isLoaded()) {
52513                     
52514                     me.onNodeExpand(node, node.childNodes, true);
52515                 }
52516                 else {
52517                     node.set('expanded', false);
52518                     node.expand();
52519                 }
52520             }
52521         }
52522     },
52523     
52524     onNodeRemove: function(parent, node, index) {
52525         var me = this;
52526         if (me.indexOf(node) != -1) {
52527             if (!node.isLeaf() && node.isExpanded()) {
52528                 me.onNodeCollapse(node, node.childNodes, true);
52529             }            
52530             me.remove(node);
52531         }
52532     },
52533     
52534     isVisible: function(node) {
52535         var parent = node.parentNode;
52536         while (parent) {
52537             if (parent === this.node && !this.rootVisible && parent.isExpanded()) {
52538                 return true;
52539             }
52540             
52541             if (this.indexOf(parent) === -1 || !parent.isExpanded()) {
52542                 return false;
52543             }
52544             
52545             parent = parent.parentNode;
52546         }
52547         return true;
52548     }
52549 });
52550
52551 Ext.define('Ext.data.Request', {
52552     
52553     action: undefined,
52554     
52555     
52556     params: undefined,
52557     
52558     
52559     method: 'GET',
52560     
52561     
52562     url: undefined,
52563
52564     constructor: function(config) {
52565         Ext.apply(this, config);
52566     }
52567 });
52568
52569 Ext.define('Ext.data.Tree', {
52570     alias: 'data.tree',
52571     
52572     mixins: {
52573         observable: "Ext.util.Observable"
52574     },
52575
52576     
52577     root: null,
52578         
52579     constructor: function(root) {
52580         var me = this;
52581         
52582         me.nodeHash = {};
52583
52584         me.mixins.observable.constructor.call(me);
52585                         
52586         if (root) {
52587             me.setRootNode(root);
52588         }
52589     },
52590
52591     
52592     getRootNode : function() {
52593         return this.root;
52594     },
52595
52596     
52597     setRootNode : function(node) {
52598         var me = this;
52599         
52600         me.root = node;
52601         Ext.data.NodeInterface.decorate(node);
52602         
52603         if (me.fireEvent('beforeappend', null, node) !== false) {
52604             node.set('root', true);
52605             node.updateInfo();
52606             
52607             me.relayEvents(node, [
52608                 
52609                 "append",
52610
52611                 
52612                 "remove",
52613
52614                 
52615                 "move",
52616
52617                 
52618                 "insert",
52619
52620                 
52621                 "beforeappend",
52622
52623                 
52624                 "beforeremove",
52625
52626                 
52627                 "beforemove",
52628
52629                 
52630                 "beforeinsert",
52631
52632                  
52633                  "expand",
52634
52635                  
52636                  "collapse",
52637
52638                  
52639                  "beforeexpand",
52640
52641                  
52642                  "beforecollapse" ,
52643
52644                  
52645                  "rootchange"
52646             ]);
52647             
52648             node.on({
52649                 scope: me,
52650                 insert: me.onNodeInsert,
52651                 append: me.onNodeAppend,
52652                 remove: me.onNodeRemove
52653             });
52654
52655             me.registerNode(node);        
52656             me.fireEvent('append', null, node);
52657             me.fireEvent('rootchange', node);
52658         }
52659             
52660         return node;
52661     },
52662     
52663     
52664     flatten: function(){
52665         var nodes = [],
52666             hash = this.nodeHash,
52667             key;
52668             
52669         for (key in hash) {
52670             if (hash.hasOwnProperty(key)) {
52671                 nodes.push(hash[key]);
52672             }
52673         }
52674         return nodes;
52675     },
52676     
52677     
52678     onNodeInsert: function(parent, node) {
52679         this.registerNode(node);
52680     },
52681     
52682     
52683     onNodeAppend: function(parent, node) {
52684         this.registerNode(node);
52685     },
52686     
52687     
52688     onNodeRemove: function(parent, node) {
52689         this.unregisterNode(node);
52690     },
52691
52692     
52693     getNodeById : function(id) {
52694         return this.nodeHash[id];
52695     },
52696
52697     
52698     registerNode : function(node) {
52699         this.nodeHash[node.getId() || node.internalId] = node;
52700     },
52701
52702     
52703     unregisterNode : function(node) {
52704         delete this.nodeHash[node.getId() || node.internalId];
52705     },
52706     
52707     
52708     sort: function(sorterFn, recursive) {
52709         this.getRootNode().sort(sorterFn, recursive);
52710     },
52711     
52712      
52713     filter: function(filters, recursive) {
52714         this.getRootNode().filter(filters, recursive);
52715     }
52716 });
52717
52718 Ext.define('Ext.data.TreeStore', {
52719     extend: 'Ext.data.AbstractStore',
52720     alias: 'store.tree',
52721     requires: ['Ext.data.Tree', 'Ext.data.NodeInterface', 'Ext.data.NodeStore'],
52722
52723     
52724     clearOnLoad : true,
52725
52726     
52727     nodeParam: 'node',
52728
52729     
52730     defaultRootId: 'root',
52731     
52732     
52733     defaultRootProperty: 'children',
52734
52735     
52736     folderSort: false,
52737     
52738     constructor: function(config) {
52739         var me = this, 
52740             root,
52741             fields;
52742             
52743         
52744         config = Ext.apply({}, config);
52745         
52746         
52747         fields = config.fields || me.fields;
52748         if (!fields) {
52749             config.fields = [{name: 'text', type: 'string'}];
52750         }
52751
52752         me.callParent([config]);
52753         
52754         
52755         me.tree = Ext.create('Ext.data.Tree');
52756         
52757         me.tree.on({
52758             scope: me,
52759             remove: me.onNodeRemove,
52760             beforeexpand: me.onBeforeNodeExpand,
52761             beforecollapse: me.onBeforeNodeCollapse,
52762             append: me.onNodeAdded,
52763             insert: me.onNodeAdded
52764         });
52765
52766         me.onBeforeSort();
52767                 
52768         root = me.root;
52769         if (root) {
52770             delete me.root;
52771             me.setRootNode(root);            
52772         }
52773
52774         me.relayEvents(me.tree, [
52775             
52776             "append",
52777             
52778             
52779             "remove",
52780             
52781             
52782             "move",
52783             
52784             
52785             "insert",
52786             
52787             
52788             "beforeappend",
52789             
52790             
52791             "beforeremove",
52792             
52793             
52794             "beforemove",
52795             
52796             
52797             "beforeinsert",
52798              
52799              
52800              "expand",
52801              
52802              
52803              "collapse",
52804              
52805              
52806              "beforeexpand",
52807              
52808              
52809              "beforecollapse",
52810
52811                           
52812              "sort",
52813              
52814              
52815              "rootchange"
52816         ]);
52817         
52818         me.addEvents(
52819             
52820             'rootchange'
52821         );
52822         
52823         if (Ext.isDefined(me.nodeParameter)) {
52824             if (Ext.isDefined(Ext.global.console)) {
52825                 Ext.global.console.warn('Ext.data.TreeStore: nodeParameter has been deprecated. Please use nodeParam instead.');
52826             }
52827             me.nodeParam = me.nodeParameter;
52828             delete me.nodeParameter;
52829         }
52830     },
52831     
52832     
52833     setProxy: function(proxy) {
52834         var reader,
52835             needsRoot;
52836         
52837         if (proxy instanceof Ext.data.proxy.Proxy) {
52838             
52839             needsRoot = Ext.isEmpty(proxy.getReader().root);
52840         } else if (Ext.isString(proxy)) {
52841             
52842             needsRoot = true;
52843         } else {
52844             
52845             reader = proxy.reader;
52846             needsRoot = !(reader && !Ext.isEmpty(reader.root));
52847         }
52848         proxy = this.callParent(arguments);
52849         if (needsRoot) {
52850             reader = proxy.getReader();
52851             reader.root = this.defaultRootProperty;
52852             
52853             reader.buildExtractors(true);
52854         }
52855     },
52856     
52857     
52858     onBeforeSort: function() {
52859         if (this.folderSort) {
52860             this.sort({
52861                 property: 'leaf',
52862                 direction: 'ASC'
52863             }, 'prepend', false);    
52864         }
52865     },
52866     
52867     
52868     onBeforeNodeExpand: function(node, callback, scope) {
52869         if (node.isLoaded()) {
52870             Ext.callback(callback, scope || node, [node.childNodes]);
52871         }
52872         else if (node.isLoading()) {
52873             this.on('load', function() {
52874                 Ext.callback(callback, scope || node, [node.childNodes]);
52875             }, this, {single: true});
52876         }
52877         else {
52878             this.read({
52879                 node: node,
52880                 callback: function() {
52881                     Ext.callback(callback, scope || node, [node.childNodes]);
52882                 }
52883             });            
52884         }
52885     },
52886     
52887     
52888     getNewRecords: function() {
52889         return Ext.Array.filter(this.tree.flatten(), this.filterNew);
52890     },
52891
52892     
52893     getUpdatedRecords: function() {
52894         return Ext.Array.filter(this.tree.flatten(), this.filterUpdated);
52895     },
52896     
52897     
52898     onBeforeNodeCollapse: function(node, callback, scope) {
52899         callback.call(scope || node, node.childNodes);
52900     },
52901     
52902     onNodeRemove: function(parent, node) {
52903         var removed = this.removed;
52904         
52905         if (!node.isReplace && Ext.Array.indexOf(removed, node) == -1) {
52906             removed.push(node);
52907         }
52908     },
52909     
52910     onNodeAdded: function(parent, node) {
52911         var proxy = this.getProxy(),
52912             reader = proxy.getReader(),
52913             data = node.raw || node.data,
52914             dataRoot, children;
52915             
52916         Ext.Array.remove(this.removed, node); 
52917         
52918         if (!node.isLeaf() && !node.isLoaded()) {
52919             dataRoot = reader.getRoot(data);
52920             if (dataRoot) {
52921                 this.fillNode(node, reader.extractData(dataRoot));
52922                 delete data[reader.root];
52923             }
52924         }
52925     },
52926         
52927     
52928     setRootNode: function(root) {
52929         var me = this;
52930
52931         root = root || {};        
52932         if (!root.isNode) {
52933             
52934             Ext.applyIf(root, {
52935                 id: me.defaultRootId,
52936                 text: 'Root',
52937                 allowDrag: false
52938             });
52939             root = Ext.ModelManager.create(root, me.model);
52940         }
52941         Ext.data.NodeInterface.decorate(root);
52942
52943         
52944         
52945         me.getProxy().getReader().buildExtractors(true);
52946         
52947         
52948         me.tree.setRootNode(root);
52949         
52950         
52951         if (!root.isLoaded() && root.isExpanded()) {
52952             me.load({
52953                 node: root
52954             });
52955         }
52956         
52957         return root;
52958     },
52959         
52960     
52961     getRootNode: function() {
52962         return this.tree.getRootNode();
52963     },
52964
52965     
52966     getNodeById: function(id) {
52967         return this.tree.getNodeById(id);
52968     },
52969
52970     
52971     load: function(options) {
52972         options = options || {};
52973         options.params = options.params || {};
52974         
52975         var me = this,
52976             node = options.node || me.tree.getRootNode(),
52977             root;
52978             
52979         
52980         
52981         if (!node) {
52982             node = me.setRootNode({
52983                 expanded: true
52984             });
52985         }
52986         
52987         if (me.clearOnLoad) {
52988             node.removeAll();
52989         }
52990         
52991         Ext.applyIf(options, {
52992             node: node
52993         });
52994         options.params[me.nodeParam] = node ? node.getId() : 'root';
52995         
52996         if (node) {
52997             node.set('loading', true);
52998         }
52999         
53000         return me.callParent([options]);
53001     },
53002         
53003
53004     
53005     fillNode: function(node, records) {
53006         var me = this,
53007             ln = records ? records.length : 0,
53008             i = 0, sortCollection;
53009
53010         if (ln && me.sortOnLoad && !me.remoteSort && me.sorters && me.sorters.items) {
53011             sortCollection = Ext.create('Ext.util.MixedCollection');
53012             sortCollection.addAll(records);
53013             sortCollection.sort(me.sorters.items);
53014             records = sortCollection.items;
53015         }
53016         
53017         node.set('loaded', true);
53018         for (; i < ln; i++) {
53019             node.appendChild(records[i], undefined, true);
53020         }
53021         
53022         return records;
53023     },
53024
53025     
53026     onProxyLoad: function(operation) {
53027         var me = this,
53028             successful = operation.wasSuccessful(),
53029             records = operation.getRecords(),
53030             node = operation.node;
53031
53032         node.set('loading', false);
53033         if (successful) {
53034             records = me.fillNode(node, records);
53035         }
53036         
53037         me.fireEvent('read', me, operation.node, records, successful);
53038         me.fireEvent('load', me, operation.node, records, successful);
53039         
53040         Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
53041     },
53042     
53043     
53044     onCreateRecords: function(records, operation, success) {
53045         if (success) {
53046             var i = 0,
53047                 length = records.length,
53048                 originalRecords = operation.records,
53049                 parentNode,
53050                 record,
53051                 original,
53052                 index;
53053
53054             
53055             for (; i < length; ++i) {
53056                 record = records[i];
53057                 original = originalRecords[i];
53058                 if (original) {
53059                     parentNode = original.parentNode;
53060                     if (parentNode) {
53061                         
53062                         original.isReplace = true;
53063                         parentNode.replaceChild(record, original);
53064                         delete original.isReplace;
53065                     }
53066                     record.phantom = false;
53067                 }
53068             }
53069         }
53070     },
53071
53072     
53073     onUpdateRecords: function(records, operation, success){
53074         if (success) {
53075             var me = this,
53076                 i = 0,
53077                 length = records.length,
53078                 data = me.data,
53079                 original,
53080                 parentNode,
53081                 record;
53082
53083             for (; i < length; ++i) {
53084                 record = records[i];
53085                 original = me.tree.getNodeById(record.getId());
53086                 parentNode = original.parentNode;
53087                 if (parentNode) {
53088                     
53089                     original.isReplace = true;
53090                     parentNode.replaceChild(record, original);
53091                     original.isReplace = false;
53092                 }
53093             }
53094         }
53095     },
53096
53097     
53098     onDestroyRecords: function(records, operation, success){
53099         if (success) {
53100             this.removed = [];
53101         }
53102     },
53103
53104     
53105     removeAll: function() {
53106         this.getRootNode().destroy(true);
53107         this.fireEvent('clear', this);
53108     },
53109
53110     
53111     doSort: function(sorterFn) {
53112         var me = this;
53113         if (me.remoteSort) {
53114             
53115             me.load();
53116         } else {
53117             me.tree.sort(sorterFn, true);
53118             me.fireEvent('datachanged', me);
53119         }   
53120         me.fireEvent('sort', me);
53121     }
53122 });
53123
53124 Ext.define('Ext.data.XmlStore', {
53125     extend: 'Ext.data.Store',
53126     alternateClassName: 'Ext.data.XmlStore',
53127     alias: 'store.xml',
53128
53129     
53130     constructor: function(config){
53131         config = config || {};
53132         config = config || {};
53133
53134         Ext.applyIf(config, {
53135             proxy: {
53136                 type: 'ajax',
53137                 reader: 'xml',
53138                 writer: 'xml'
53139             }
53140         });
53141
53142         this.callParent([config]);
53143     }
53144 });
53145
53146
53147 Ext.define('Ext.data.proxy.Client', {
53148     extend: 'Ext.data.proxy.Proxy',
53149     alternateClassName: 'Ext.data.ClientProxy',
53150     
53151     
53152     clear: function() {
53153         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.");
53154     }
53155 });
53156
53157 Ext.define('Ext.data.proxy.JsonP', {
53158     extend: 'Ext.data.proxy.Server',
53159     alternateClassName: 'Ext.data.ScriptTagProxy',
53160     alias: ['proxy.jsonp', 'proxy.scripttag'],
53161     requires: ['Ext.data.JsonP'],
53162
53163     defaultWriterType: 'base',
53164
53165     
53166     callbackKey : 'callback',
53167
53168     
53169     recordParam: 'records',
53170
53171     
53172     autoAppendParams: true,
53173
53174     constructor: function(){
53175         this.addEvents(
53176             
53177             'exception'
53178         );
53179         this.callParent(arguments);
53180     },
53181
53182     
53183     doRequest: function(operation, callback, scope) {
53184         
53185         var me      = this,
53186             writer  = me.getWriter(),
53187             request = me.buildRequest(operation),
53188             params = request.params;
53189
53190         if (operation.allowWrite()) {
53191             request = writer.write(request);
53192         }
53193
53194         
53195         Ext.apply(request, {
53196             callbackKey: me.callbackKey,
53197             timeout: me.timeout,
53198             scope: me,
53199             disableCaching: false, 
53200             callback: me.createRequestCallback(request, operation, callback, scope)
53201         });
53202         
53203         
53204         if (me.autoAppendParams) {
53205             request.params = {};
53206         }
53207         
53208         request.jsonp = Ext.data.JsonP.request(request);
53209         
53210         request.params = params;
53211         operation.setStarted();
53212         me.lastRequest = request;
53213
53214         return request;
53215     },
53216
53217     
53218     createRequestCallback: function(request, operation, callback, scope) {
53219         var me = this;
53220
53221         return function(success, response, errorType) {
53222             delete me.lastRequest;
53223             me.processResponse(success, operation, request, response, callback, scope);
53224         };
53225     },
53226     
53227     
53228     setException: function(operation, response) {
53229         operation.setException(operation.request.jsonp.errorType);
53230     },
53231
53232
53233     
53234     buildUrl: function(request) {
53235         var me      = this,
53236             url     = me.callParent(arguments),
53237             params  = Ext.apply({}, request.params),
53238             filters = params.filters,
53239             records,
53240             filter, i;
53241
53242         delete params.filters;
53243  
53244         if (me.autoAppendParams) {
53245             url = Ext.urlAppend(url, Ext.Object.toQueryString(params));
53246         }
53247
53248         if (filters && filters.length) {
53249             for (i = 0; i < filters.length; i++) {
53250                 filter = filters[i];
53251
53252                 if (filter.value) {
53253                     url = Ext.urlAppend(url, filter.property + "=" + filter.value);
53254                 }
53255             }
53256         }
53257
53258         
53259         records = request.records;
53260
53261         if (Ext.isArray(records) && records.length > 0) {
53262             url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.recordParam, me.encodeRecords(records)));
53263         }
53264
53265         return url;
53266     },
53267
53268     
53269     destroy: function() {
53270         this.abort();
53271         this.callParent();
53272     },
53273
53274     
53275     abort: function() {
53276         var lastRequest = this.lastRequest;
53277         if (lastRequest) {
53278             Ext.data.JsonP.abort(lastRequest.jsonp);
53279         }
53280     },
53281
53282     
53283     encodeRecords: function(records) {
53284         var encoded = "",
53285             i = 0,
53286             len = records.length;
53287
53288         for (; i < len; i++) {
53289             encoded += Ext.Object.toQueryString(records[i].data);
53290         }
53291
53292         return encoded;
53293     }
53294 });
53295
53296
53297 Ext.define('Ext.data.proxy.WebStorage', {
53298     extend: 'Ext.data.proxy.Client',
53299     alternateClassName: 'Ext.data.WebStorageProxy',
53300     
53301     
53302     id: undefined,
53303
53304     
53305     constructor: function(config) {
53306         this.callParent(arguments);
53307         
53308         
53309         this.cache = {};
53310
53311         if (this.getStorageObject() === undefined) {
53312             Ext.Error.raise("Local Storage is not supported in this browser, please use another type of data proxy");
53313         }
53314
53315         
53316         this.id = this.id || (this.store ? this.store.storeId : undefined);
53317
53318         if (this.id === undefined) {
53319             Ext.Error.raise("No unique id was provided to the local storage proxy. See Ext.data.proxy.LocalStorage documentation for details");
53320         }
53321
53322         this.initialize();
53323     },
53324
53325     
53326     create: function(operation, callback, scope) {
53327         var records = operation.records,
53328             length  = records.length,
53329             ids     = this.getIds(),
53330             id, record, i;
53331         
53332         operation.setStarted();
53333
53334         for (i = 0; i < length; i++) {
53335             record = records[i];
53336
53337             if (record.phantom) {
53338                 record.phantom = false;
53339                 id = this.getNextId();
53340             } else {
53341                 id = record.getId();
53342             }
53343
53344             this.setRecord(record, id);
53345             ids.push(id);
53346         }
53347
53348         this.setIds(ids);
53349
53350         operation.setCompleted();
53351         operation.setSuccessful();
53352
53353         if (typeof callback == 'function') {
53354             callback.call(scope || this, operation);
53355         }
53356     },
53357
53358     
53359     read: function(operation, callback, scope) {
53360         
53361
53362         var records = [],
53363             ids     = this.getIds(),
53364             length  = ids.length,
53365             i, recordData, record;
53366         
53367         
53368         if (operation.id) {
53369             record = this.getRecord(operation.id);
53370             
53371             if (record) {
53372                 records.push(record);
53373                 operation.setSuccessful();
53374             }
53375         } else {
53376             for (i = 0; i < length; i++) {
53377                 records.push(this.getRecord(ids[i]));
53378             }
53379             operation.setSuccessful();
53380         }
53381         
53382         operation.setCompleted();
53383
53384         operation.resultSet = Ext.create('Ext.data.ResultSet', {
53385             records: records,
53386             total  : records.length,
53387             loaded : true
53388         });
53389
53390         if (typeof callback == 'function') {
53391             callback.call(scope || this, operation);
53392         }
53393     },
53394
53395     
53396     update: function(operation, callback, scope) {
53397         var records = operation.records,
53398             length  = records.length,
53399             ids     = this.getIds(),
53400             record, id, i;
53401
53402         operation.setStarted();
53403
53404         for (i = 0; i < length; i++) {
53405             record = records[i];
53406             this.setRecord(record);
53407             
53408             
53409             
53410             id = record.getId();
53411             if (id !== undefined && Ext.Array.indexOf(ids, id) == -1) {
53412                 ids.push(id);
53413             }
53414         }
53415         this.setIds(ids);
53416
53417         operation.setCompleted();
53418         operation.setSuccessful();
53419
53420         if (typeof callback == 'function') {
53421             callback.call(scope || this, operation);
53422         }
53423     },
53424
53425     
53426     destroy: function(operation, callback, scope) {
53427         var records = operation.records,
53428             length  = records.length,
53429             ids     = this.getIds(),
53430
53431             
53432             newIds  = [].concat(ids),
53433             i;
53434
53435         for (i = 0; i < length; i++) {
53436             Ext.Array.remove(newIds, records[i].getId());
53437             this.removeRecord(records[i], false);
53438         }
53439
53440         this.setIds(newIds);
53441         
53442         operation.setCompleted();
53443         operation.setSuccessful();
53444
53445         if (typeof callback == 'function') {
53446             callback.call(scope || this, operation);
53447         }
53448     },
53449
53450     
53451     getRecord: function(id) {
53452         if (this.cache[id] === undefined) {
53453             var rawData = Ext.decode(this.getStorageObject().getItem(this.getRecordKey(id))),
53454                 data    = {},
53455                 Model   = this.model,
53456                 fields  = Model.prototype.fields.items,
53457                 length  = fields.length,
53458                 i, field, name, record;
53459
53460             for (i = 0; i < length; i++) {
53461                 field = fields[i];
53462                 name  = field.name;
53463
53464                 if (typeof field.decode == 'function') {
53465                     data[name] = field.decode(rawData[name]);
53466                 } else {
53467                     data[name] = rawData[name];
53468                 }
53469             }
53470
53471             record = new Model(data, id);
53472             record.phantom = false;
53473
53474             this.cache[id] = record;
53475         }
53476         
53477         return this.cache[id];
53478     },
53479
53480     
53481     setRecord: function(record, id) {
53482         if (id) {
53483             record.setId(id);
53484         } else {
53485             id = record.getId();
53486         }
53487
53488         var me = this,
53489             rawData = record.data,
53490             data    = {},
53491             model   = me.model,
53492             fields  = model.prototype.fields.items,
53493             length  = fields.length,
53494             i = 0,
53495             field, name, obj, key;
53496
53497         for (; i < length; i++) {
53498             field = fields[i];
53499             name  = field.name;
53500
53501             if (typeof field.encode == 'function') {
53502                 data[name] = field.encode(rawData[name], record);
53503             } else {
53504                 data[name] = rawData[name];
53505             }
53506         }
53507
53508         obj = me.getStorageObject();
53509         key = me.getRecordKey(id);
53510         
53511         
53512         me.cache[id] = record;
53513         
53514         
53515         obj.removeItem(key);
53516         obj.setItem(key, Ext.encode(data));
53517     },
53518
53519     
53520     removeRecord: function(id, updateIds) {
53521         var me = this,
53522             ids;
53523             
53524         if (id.isModel) {
53525             id = id.getId();
53526         }
53527
53528         if (updateIds !== false) {
53529             ids = me.getIds();
53530             Ext.Array.remove(ids, id);
53531             me.setIds(ids);
53532         }
53533
53534         me.getStorageObject().removeItem(me.getRecordKey(id));
53535     },
53536
53537     
53538     getRecordKey: function(id) {
53539         if (id.isModel) {
53540             id = id.getId();
53541         }
53542
53543         return Ext.String.format("{0}-{1}", this.id, id);
53544     },
53545
53546     
53547     getRecordCounterKey: function() {
53548         return Ext.String.format("{0}-counter", this.id);
53549     },
53550
53551     
53552     getIds: function() {
53553         var ids    = (this.getStorageObject().getItem(this.id) || "").split(","),
53554             length = ids.length,
53555             i;
53556
53557         if (length == 1 && ids[0] === "") {
53558             ids = [];
53559         } else {
53560             for (i = 0; i < length; i++) {
53561                 ids[i] = parseInt(ids[i], 10);
53562             }
53563         }
53564
53565         return ids;
53566     },
53567
53568     
53569     setIds: function(ids) {
53570         var obj = this.getStorageObject(),
53571             str = ids.join(",");
53572         
53573         obj.removeItem(this.id);
53574         
53575         if (!Ext.isEmpty(str)) {
53576             obj.setItem(this.id, str);
53577         }
53578     },
53579
53580     
53581     getNextId: function() {
53582         var obj  = this.getStorageObject(),
53583             key  = this.getRecordCounterKey(),
53584             last = obj.getItem(key),
53585             ids, id;
53586         
53587         if (last === null) {
53588             ids = this.getIds();
53589             last = ids[ids.length - 1] || 0;
53590         }
53591         
53592         id = parseInt(last, 10) + 1;
53593         obj.setItem(key, id);
53594         
53595         return id;
53596     },
53597
53598     
53599     initialize: function() {
53600         var storageObject = this.getStorageObject();
53601         storageObject.setItem(this.id, storageObject.getItem(this.id) || "");
53602     },
53603
53604     
53605     clear: function() {
53606         var obj = this.getStorageObject(),
53607             ids = this.getIds(),
53608             len = ids.length,
53609             i;
53610
53611         
53612         for (i = 0; i < len; i++) {
53613             this.removeRecord(ids[i]);
53614         }
53615
53616         
53617         obj.removeItem(this.getRecordCounterKey());
53618         obj.removeItem(this.id);
53619     },
53620
53621     
53622     getStorageObject: function() {
53623         Ext.Error.raise("The getStorageObject function has not been defined in your Ext.data.proxy.WebStorage subclass");
53624     }
53625 });
53626
53627 Ext.define('Ext.data.proxy.LocalStorage', {
53628     extend: 'Ext.data.proxy.WebStorage',
53629     alias: 'proxy.localstorage',
53630     alternateClassName: 'Ext.data.LocalStorageProxy',
53631     
53632     
53633     getStorageObject: function() {
53634         return window.localStorage;
53635     }
53636 });
53637
53638 Ext.define('Ext.data.proxy.Memory', {
53639     extend: 'Ext.data.proxy.Client',
53640     alias: 'proxy.memory',
53641     alternateClassName: 'Ext.data.MemoryProxy',
53642
53643     
53644
53645     constructor: function(config) {
53646         this.callParent([config]);
53647
53648         
53649         this.setReader(this.reader);
53650     },
53651
53652     
53653     read: function(operation, callback, scope) {
53654         var me     = this,
53655             reader = me.getReader(),
53656             result = reader.read(me.data);
53657
53658         Ext.apply(operation, {
53659             resultSet: result
53660         });
53661
53662         operation.setCompleted();
53663         operation.setSuccessful();
53664         Ext.callback(callback, scope || me, [operation]);
53665     },
53666
53667     clear: Ext.emptyFn
53668 });
53669
53670
53671 Ext.define('Ext.data.proxy.Rest', {
53672     extend: 'Ext.data.proxy.Ajax',
53673     alternateClassName: 'Ext.data.RestProxy',
53674     alias : 'proxy.rest',
53675     
53676     
53677     appendId: true,
53678     
53679     
53680     
53681     
53682     batchActions: false,
53683     
53684     
53685     buildUrl: function(request) {
53686         var me        = this,
53687             operation = request.operation,
53688             records   = operation.records || [],
53689             record    = records[0],
53690             format    = me.format,
53691             url       = me.getUrl(request),
53692             id        = record ? record.getId() : operation.id;
53693         
53694         if (me.appendId && id) {
53695             if (!url.match(/\/$/)) {
53696                 url += '/';
53697             }
53698             
53699             url += id;
53700         }
53701         
53702         if (format) {
53703             if (!url.match(/\.$/)) {
53704                 url += '.';
53705             }
53706             
53707             url += format;
53708         }
53709         
53710         request.url = url;
53711         
53712         return me.callParent(arguments);
53713     }
53714 }, function() {
53715     Ext.apply(this.prototype, {
53716         
53717         actionMethods: {
53718             create : 'POST',
53719             read   : 'GET',
53720             update : 'PUT',
53721             destroy: 'DELETE'
53722         }
53723     });
53724 });
53725
53726
53727 Ext.define('Ext.data.proxy.SessionStorage', {
53728     extend: 'Ext.data.proxy.WebStorage',
53729     alias: 'proxy.sessionstorage',
53730     alternateClassName: 'Ext.data.SessionStorageProxy',
53731     
53732     
53733     getStorageObject: function() {
53734         return window.sessionStorage;
53735     }
53736 });
53737
53738
53739 Ext.define('Ext.data.reader.Array', {
53740     extend: 'Ext.data.reader.Json',
53741     alternateClassName: 'Ext.data.ArrayReader',
53742     alias : 'reader.array',
53743
53744     
53745     buildExtractors: function() {
53746         this.callParent(arguments);
53747         
53748         var fields = this.model.prototype.fields.items,
53749             length = fields.length,
53750             extractorFunctions = [],
53751             i;
53752         
53753         for (i = 0; i < length; i++) {
53754             extractorFunctions.push(function(index) {
53755                 return function(data) {
53756                     return data[index];
53757                 };
53758             }(fields[i].mapping || i));
53759         }
53760         
53761         this.extractorFunctions = extractorFunctions;
53762     }
53763 });
53764
53765
53766 Ext.define('Ext.data.reader.Xml', {
53767     extend: 'Ext.data.reader.Reader',
53768     alternateClassName: 'Ext.data.XmlReader',
53769     alias : 'reader.xml',
53770     
53771     
53772
53773     
53774     createAccessor: function(expr) {
53775         var me = this;
53776         
53777         if (Ext.isEmpty(expr)) {
53778             return Ext.emptyFn;
53779         }
53780         
53781         if (Ext.isFunction(expr)) {
53782             return expr;
53783         }
53784         
53785         return function(root) {
53786             var node = Ext.DomQuery.selectNode(expr, root),
53787                 val = me.getNodeValue(node);
53788                 
53789             return Ext.isEmpty(val) ? null : val;
53790         };
53791     },
53792     
53793     getNodeValue: function(node) {
53794         var val;
53795         if (node && node.firstChild) {
53796             val = node.firstChild.nodeValue;
53797         }
53798         return val || null;
53799     },
53800
53801     
53802     getResponseData: function(response) {
53803         var xml = response.responseXML;
53804
53805         if (!xml) {
53806             Ext.Error.raise({
53807                 response: response,
53808                 msg: 'XML data not found in the response'
53809             });
53810         }
53811
53812         return xml;
53813     },
53814
53815     
53816     getData: function(data) {
53817         return data.documentElement || data;
53818     },
53819
53820     
53821     getRoot: function(data) {
53822         var nodeName = data.nodeName,
53823             root     = this.root;
53824         
53825         if (!root || (nodeName && nodeName == root)) {
53826             return data;
53827         } else if (Ext.DomQuery.isXml(data)) {
53828             
53829             
53830             
53831             return Ext.DomQuery.selectNode(root, data);
53832         }
53833     },
53834
53835     
53836     extractData: function(root) {
53837         var recordName = this.record;
53838         
53839         if (!recordName) {
53840             Ext.Error.raise('Record is a required parameter');
53841         }
53842         
53843         if (recordName != root.nodeName) {
53844             root = Ext.DomQuery.select(recordName, root);
53845         } else {
53846             root = [root];
53847         }
53848         return this.callParent([root]);
53849     },
53850     
53851     
53852     getAssociatedDataRoot: function(data, associationName) {
53853         return Ext.DomQuery.select(associationName, data)[0];
53854     },
53855
53856     
53857     readRecords: function(doc) {
53858         
53859         if (Ext.isArray(doc)) {
53860             doc = doc[0];
53861         }
53862         
53863         
53864         this.xmlData = doc;
53865         return this.callParent([doc]);
53866     }
53867 });
53868
53869
53870 Ext.define('Ext.data.writer.Xml', {
53871     
53872     
53873     
53874     extend: 'Ext.data.writer.Writer',
53875     alternateClassName: 'Ext.data.XmlWriter',
53876     
53877     alias: 'writer.xml',
53878     
53879     
53880     
53881     
53882     documentRoot: 'xmlData',
53883     
53884     
53885     defaultDocumentRoot: 'xmlData',
53886
53887     
53888     header: '',
53889
53890     
53891     record: 'record',
53892
53893     
53894     writeRecords: function(request, data) {
53895         var me = this,
53896             xml = [],
53897             i = 0,
53898             len = data.length,
53899             root = me.documentRoot,
53900             record = me.record,
53901             needsRoot = data.length !== 1,
53902             item,
53903             key;
53904             
53905         
53906         xml.push(me.header || '');
53907         
53908         if (!root && needsRoot) {
53909             root = me.defaultDocumentRoot;
53910         }
53911         
53912         if (root) {
53913             xml.push('<', root, '>');
53914         }
53915             
53916         for (; i < len; ++i) {
53917             item = data[i];
53918             xml.push('<', record, '>');
53919             for (key in item) {
53920                 if (item.hasOwnProperty(key)) {
53921                     xml.push('<', key, '>', item[key], '</', key, '>');
53922                 }
53923             }
53924             xml.push('</', record, '>');
53925         }
53926         
53927         if (root) {
53928             xml.push('</', root, '>');
53929         }
53930             
53931         request.xmlData = xml.join('');
53932         return request;
53933     }
53934 });
53935
53936
53937 Ext.define('Ext.direct.Event', {
53938     
53939     
53940    
53941     alias: 'direct.event',
53942     
53943     requires: ['Ext.direct.Manager'],
53944     
53945     
53946    
53947     status: true,
53948     
53949     constructor: function(config) {
53950         Ext.apply(this, config);
53951     },
53952     
53953     
53954     getData: function(){
53955         return this.data;
53956     }
53957 });
53958
53959
53960 Ext.define('Ext.direct.RemotingEvent', {
53961     
53962     
53963    
53964     extend: 'Ext.direct.Event',
53965     
53966     alias: 'direct.rpc',
53967     
53968     
53969     
53970     
53971     getTransaction: function(){
53972         return this.transaction || Ext.direct.Manager.getTransaction(this.tid);
53973     }
53974 });
53975
53976
53977 Ext.define('Ext.direct.ExceptionEvent', {
53978     
53979     
53980    
53981     extend: 'Ext.direct.RemotingEvent',
53982     
53983     alias: 'direct.exception',
53984     
53985     
53986    
53987    status: false
53988 });
53989
53990
53991 Ext.define('Ext.direct.Provider', {
53992     
53993     
53994    
53995    alias: 'direct.provider',
53996    
53997     mixins: {
53998         observable: 'Ext.util.Observable'   
53999     },
54000    
54001     
54002    
54003    
54004     
54005     constructor : function(config){
54006         var me = this;
54007         
54008         Ext.apply(me, config);
54009         me.addEvents(
54010                         
54011             'connect',
54012                         
54013             'disconnect',
54014                         
54015             'data',
54016                                     
54017             'exception'
54018         );
54019         me.mixins.observable.constructor.call(me, config);
54020     },
54021     
54022     
54023     isConnected: function(){
54024         return false;
54025     },
54026
54027     
54028     connect: Ext.emptyFn,
54029     
54030     
54031     disconnect: Ext.emptyFn
54032 });
54033
54034
54035
54036 Ext.define('Ext.direct.JsonProvider', {
54037     
54038     
54039     
54040     extend: 'Ext.direct.Provider',
54041     
54042     alias: 'direct.jsonprovider',
54043     
54044     uses: ['Ext.direct.ExceptionEvent'],
54045     
54046     
54047    
54048    
54049    parseResponse: function(response){
54050         if (!Ext.isEmpty(response.responseText)) {
54051             if (Ext.isObject(response.responseText)) {
54052                 return response.responseText;
54053             }
54054             return Ext.decode(response.responseText);
54055         }
54056         return null;
54057     },
54058
54059     
54060     createEvents: function(response){
54061         var data = null,
54062             events = [],
54063             event,
54064             i = 0,
54065             len;
54066             
54067         try{
54068             data = this.parseResponse(response);
54069         } catch(e) {
54070             event = Ext.create('Ext.direct.ExceptionEvent', {
54071                 data: e,
54072                 xhr: response,
54073                 code: Ext.direct.Manager.self.exceptions.PARSE,
54074                 message: 'Error parsing json response: \n\n ' + data
54075             });
54076             return [event];
54077         }
54078         
54079         if (Ext.isArray(data)) {
54080             for (len = data.length; i < len; ++i) {
54081                 events.push(this.createEvent(data[i]));
54082             }
54083         } else {
54084             events.push(this.createEvent(data));
54085         }
54086         return events;
54087     },
54088     
54089     
54090     createEvent: function(response){
54091         return Ext.create('direct.' + response.type, response);
54092     }
54093 });
54094
54095 Ext.define('Ext.direct.PollingProvider', {
54096     
54097     
54098     
54099     extend: 'Ext.direct.JsonProvider',
54100     
54101     alias: 'direct.pollingprovider',
54102     
54103     uses: ['Ext.direct.ExceptionEvent'],
54104     
54105     requires: ['Ext.Ajax', 'Ext.util.DelayedTask'],
54106     
54107     
54108     
54109     
54110     interval: 3000,
54111
54112     
54113     
54114     
54115
54116     
54117     constructor : function(config){
54118         this.callParent(arguments);
54119         this.addEvents(
54120             
54121             'beforepoll',            
54122             
54123             'poll'
54124         );
54125     },
54126
54127     
54128     isConnected: function(){
54129         return !!this.pollTask;
54130     },
54131
54132     
54133     connect: function(){
54134         var me = this, url = me.url;
54135         
54136         if (url && !me.pollTask) {
54137             me.pollTask = Ext.TaskManager.start({
54138                 run: function(){
54139                     if (me.fireEvent('beforepoll', me) !== false) {
54140                         if (Ext.isFunction(url)) {
54141                             url(me.baseParams);
54142                         } else {
54143                             Ext.Ajax.request({
54144                                 url: url,
54145                                 callback: me.onData,
54146                                 scope: me,
54147                                 params: me.baseParams
54148                             });
54149                         }
54150                     }
54151                 },
54152                 interval: me.interval,
54153                 scope: me
54154             });
54155             me.fireEvent('connect', me);
54156         } else if (!url) {
54157             Ext.Error.raise('Error initializing PollingProvider, no url configured.');
54158         }
54159     },
54160
54161     
54162     disconnect: function(){
54163         var me = this;
54164         
54165         if (me.pollTask) {
54166             Ext.TaskManager.stop(me.pollTask);
54167             delete me.pollTask;
54168             me.fireEvent('disconnect', me);
54169         }
54170     },
54171
54172     
54173     onData: function(opt, success, response){
54174         var me = this, 
54175             i = 0, 
54176             len,
54177             events;
54178         
54179         if (success) {
54180             events = me.createEvents(response);
54181             for (len = events.length; i < len; ++i) {
54182                 me.fireEvent('data', me, events[i]);
54183             }
54184         } else {
54185             me.fireEvent('data', me, Ext.create('Ext.direct.ExceptionEvent', {
54186                 data: null,
54187                 code: Ext.direct.Manager.self.exceptions.TRANSPORT,
54188                 message: 'Unable to connect to the server.',
54189                 xhr: response
54190             }));
54191         }
54192     }
54193 });
54194
54195 Ext.define('Ext.direct.RemotingMethod', {
54196     
54197     constructor: function(config){
54198         var me = this,
54199             params = Ext.isDefined(config.params) ? config.params : config.len,
54200             name;
54201             
54202         me.name = config.name;
54203         me.formHandler = config.formHandler;
54204         if (Ext.isNumber(params)) {
54205             
54206             me.len = params;
54207             me.ordered = true;
54208         } else {
54209             
54210             me.params = [];
54211             Ext.each(params, function(param){
54212                 name = Ext.isObject(param) ? param.name : param;
54213                 me.params.push(name);
54214             });
54215         }
54216     },
54217     
54218     
54219     getCallData: function(args){
54220         var me = this,
54221             data = null,
54222             len  = me.len,
54223             params = me.params,
54224             callback,
54225             scope,
54226             name;
54227             
54228         if (me.ordered) {
54229             callback = args[len];
54230             scope = args[len + 1];
54231             if (len !== 0) {
54232                 data = args.slice(0, len);
54233             }
54234         } else {
54235             data = Ext.apply({}, args[0]);
54236             callback = args[1];
54237             scope = args[2];
54238             
54239             
54240             for (name in data) {
54241                 if (data.hasOwnProperty(name)) {
54242                     if (!Ext.Array.contains(params, name)) {
54243                         delete data[name];
54244                     }
54245                 }
54246             }
54247         }
54248         
54249         return {
54250             data: data,
54251             callback: callback,
54252             scope: scope    
54253         };
54254     }
54255 });
54256
54257
54258 Ext.define('Ext.direct.Transaction', {
54259     
54260     
54261    
54262     alias: 'direct.transaction',
54263     alternateClassName: 'Ext.Direct.Transaction',
54264    
54265     statics: {
54266         TRANSACTION_ID: 0
54267     },
54268    
54269     
54270    
54271     constructor: function(config){
54272         var me = this;
54273         
54274         Ext.apply(me, config);
54275         me.id = ++me.self.TRANSACTION_ID;
54276         me.retryCount = 0;
54277     },
54278    
54279     send: function(){
54280          this.provider.queueTransaction(this);
54281     },
54282
54283     retry: function(){
54284         this.retryCount++;
54285         this.send();
54286     },
54287
54288     getProvider: function(){
54289         return this.provider;
54290     }
54291 });
54292
54293
54294 Ext.define('Ext.direct.RemotingProvider', {
54295     
54296     
54297    
54298     alias: 'direct.remotingprovider',
54299     
54300     extend: 'Ext.direct.JsonProvider', 
54301     
54302     requires: [
54303         'Ext.util.MixedCollection', 
54304         'Ext.util.DelayedTask', 
54305         'Ext.direct.Transaction',
54306         'Ext.direct.RemotingMethod'
54307     ],
54308    
54309     
54310    
54311    
54312     
54313     
54314     
54315     
54316     
54317     
54318     
54319     
54320     enableBuffer: 10,
54321     
54322     
54323     maxRetries: 1,
54324     
54325     
54326     timeout: undefined,
54327     
54328     constructor : function(config){
54329         var me = this;
54330         me.callParent(arguments);
54331         me.addEvents(
54332                         
54333             'beforecall',            
54334                         
54335             'call'
54336         );
54337         me.namespace = (Ext.isString(me.namespace)) ? Ext.ns(me.namespace) : me.namespace || window;
54338         me.transactions = Ext.create('Ext.util.MixedCollection');
54339         me.callBuffer = [];
54340     },
54341     
54342     
54343     initAPI : function(){
54344         var actions = this.actions,
54345             namespace = this.namespace,
54346             action,
54347             cls,
54348             methods,
54349             i,
54350             len,
54351             method;
54352             
54353         for (action in actions) {
54354             cls = namespace[action];
54355             if (!cls) {
54356                 cls = namespace[action] = {};
54357             }
54358             methods = actions[action];
54359             
54360             for (i = 0, len = methods.length; i < len; ++i) {
54361                 method = Ext.create('Ext.direct.RemotingMethod', methods[i]);
54362                 cls[method.name] = this.createHandler(action, method);
54363             }
54364         }
54365     },
54366     
54367     
54368     createHandler : function(action, method){
54369         var me = this,
54370             handler;
54371         
54372         if (!method.formHandler) {
54373             handler = function(){
54374                 me.configureRequest(action, method, Array.prototype.slice.call(arguments, 0));
54375             };
54376         } else {
54377             handler = function(form, callback, scope){
54378                 me.configureFormRequest(action, method, form, callback, scope);
54379             };
54380         }
54381         handler.directCfg = {
54382             action: action,
54383             method: method
54384         };
54385         return handler;
54386     },
54387     
54388     
54389     isConnected: function(){
54390         return !!this.connected;
54391     },
54392
54393     
54394     connect: function(){
54395         var me = this;
54396         
54397         if (me.url) {
54398             me.initAPI();
54399             me.connected = true;
54400             me.fireEvent('connect', me);
54401         } else if(!me.url) {
54402             Ext.Error.raise('Error initializing RemotingProvider, no url configured.');
54403         }
54404     },
54405
54406     
54407     disconnect: function(){
54408         var me = this;
54409         
54410         if (me.connected) {
54411             me.connected = false;
54412             me.fireEvent('disconnect', me);
54413         }
54414     },
54415     
54416     
54417     runCallback: function(transaction, event){
54418         var funcName = event.status ? 'success' : 'failure',
54419             callback,
54420             result;
54421         
54422         if (transaction && transaction.callback) {
54423             callback = transaction.callback;
54424             result = Ext.isDefined(event.result) ? event.result : event.data;
54425         
54426             if (Ext.isFunction(callback)) {
54427                 callback(result, event);
54428             } else {
54429                 Ext.callback(callback[funcName], callback.scope, [result, event]);
54430                 Ext.callback(callback.callback, callback.scope, [result, event]);
54431             }
54432         }
54433     },
54434     
54435     
54436     onData: function(options, success, response){
54437         var me = this,
54438             i = 0,
54439             len,
54440             events,
54441             event,
54442             transaction,
54443             transactions;
54444             
54445         if (success) {
54446             events = me.createEvents(response);
54447             for (len = events.length; i < len; ++i) {
54448                 event = events[i];
54449                 transaction = me.getTransaction(event);
54450                 me.fireEvent('data', me, event);
54451                 if (transaction) {
54452                     me.runCallback(transaction, event, true);
54453                     Ext.direct.Manager.removeTransaction(transaction);
54454                 }
54455             }
54456         } else {
54457             transactions = [].concat(options.transaction);
54458             for (len = transactions.length; i < len; ++i) {
54459                 transaction = me.getTransaction(transactions[i]);
54460                 if (transaction && transaction.retryCount < me.maxRetries) {
54461                     transaction.retry();
54462                 } else {
54463                     event = Ext.create('Ext.direct.ExceptionEvent', {
54464                         data: null,
54465                         transaction: transaction,
54466                         code: Ext.direct.Manager.self.exceptions.TRANSPORT,
54467                         message: 'Unable to connect to the server.',
54468                         xhr: response
54469                     });
54470                     me.fireEvent('data', me, event);
54471                     if (transaction) {
54472                         me.runCallback(transaction, event, false);
54473                         Ext.direct.Manager.removeTransaction(transaction);
54474                     }
54475                 }
54476             }
54477         }
54478     },
54479     
54480     
54481     getTransaction: function(options){
54482         return options && options.tid ? Ext.direct.Manager.getTransaction(options.tid) : null;
54483     },
54484     
54485     
54486     configureRequest: function(action, method, args){
54487         var me = this,
54488             callData = method.getCallData(args),
54489             data = callData.data, 
54490             callback = callData.callback, 
54491             scope = callData.scope,
54492             transaction;
54493
54494         transaction = Ext.create('Ext.direct.Transaction', {
54495             provider: me,
54496             args: args,
54497             action: action,
54498             method: method.name,
54499             data: data,
54500             callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback
54501         });
54502
54503         if (me.fireEvent('beforecall', me, transaction, method) !== false) {
54504             Ext.direct.Manager.addTransaction(transaction);
54505             me.queueTransaction(transaction);
54506             me.fireEvent('call', me, transaction, method);
54507         }
54508     },
54509     
54510     
54511     getCallData: function(transaction){
54512         return {
54513             action: transaction.action,
54514             method: transaction.method,
54515             data: transaction.data,
54516             type: 'rpc',
54517             tid: transaction.id
54518         };
54519     },
54520     
54521     
54522     sendRequest : function(data){
54523         var me = this,
54524             request = {
54525                 url: me.url,
54526                 callback: me.onData,
54527                 scope: me,
54528                 transaction: data,
54529                 timeout: me.timeout
54530             }, callData,
54531             enableUrlEncode = me.enableUrlEncode,
54532             i = 0,
54533             len,
54534             params;
54535             
54536
54537         if (Ext.isArray(data)) {
54538             callData = [];
54539             for (len = data.length; i < len; ++i) {
54540                 callData.push(me.getCallData(data[i]));
54541             }
54542         } else {
54543             callData = me.getCallData(data);
54544         }
54545
54546         if (enableUrlEncode) {
54547             params = {};
54548             params[Ext.isString(enableUrlEncode) ? enableUrlEncode : 'data'] = Ext.encode(callData);
54549             request.params = params;
54550         } else {
54551             request.jsonData = callData;
54552         }
54553         Ext.Ajax.request(request);
54554     },
54555     
54556     
54557     queueTransaction: function(transaction){
54558         var me = this,
54559             enableBuffer = me.enableBuffer;
54560         
54561         if (transaction.form) {
54562             me.sendFormRequest(transaction);
54563             return;
54564         }
54565         
54566         me.callBuffer.push(transaction);
54567         if (enableBuffer) {
54568             if (!me.callTask) {
54569                 me.callTask = Ext.create('Ext.util.DelayedTask', me.combineAndSend, me);
54570             }
54571             me.callTask.delay(Ext.isNumber(enableBuffer) ? enableBuffer : 10);
54572         } else {
54573             me.combineAndSend();
54574         }
54575     },
54576     
54577     
54578     combineAndSend : function(){
54579         var buffer = this.callBuffer,
54580             len = buffer.length;
54581             
54582         if (len > 0) {
54583             this.sendRequest(len == 1 ? buffer[0] : buffer);
54584             this.callBuffer = [];
54585         }
54586     },
54587     
54588     
54589     configureFormRequest : function(action, method, form, callback, scope){
54590         var me = this,
54591             transaction = Ext.create('Ext.direct.Transaction', {
54592                 provider: me,
54593                 action: action,
54594                 method: method.name,
54595                 args: [form, callback, scope],
54596                 callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback,
54597                 isForm: true
54598             }),
54599             isUpload,
54600             params;
54601
54602         if (me.fireEvent('beforecall', me, transaction, method) !== false) {
54603             Ext.direct.Manager.addTransaction(transaction);
54604             isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data';
54605             
54606             params = {
54607                 extTID: transaction.id,
54608                 extAction: action,
54609                 extMethod: method.name,
54610                 extType: 'rpc',
54611                 extUpload: String(isUpload)
54612             };
54613             
54614             
54615             
54616             Ext.apply(transaction, {
54617                 form: Ext.getDom(form),
54618                 isUpload: isUpload,
54619                 params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params
54620             });
54621             me.fireEvent('call', me, transaction, method);
54622             me.sendFormRequest(transaction);
54623         }
54624     },
54625     
54626     
54627     sendFormRequest: function(transaction){
54628         Ext.Ajax.request({
54629             url: this.url,
54630             params: transaction.params,
54631             callback: this.onData,
54632             scope: this,
54633             form: transaction.form,
54634             isUpload: transaction.isUpload,
54635             transaction: transaction
54636         });
54637     }
54638     
54639 });
54640
54641
54642 Ext.define('Ext.draw.Matrix', {
54643
54644     
54645
54646     requires: ['Ext.draw.Draw'],
54647
54648     
54649
54650     constructor: function(a, b, c, d, e, f) {
54651         if (a != null) {
54652             this.matrix = [[a, c, e], [b, d, f], [0, 0, 1]];
54653         }
54654         else {
54655             this.matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
54656         }
54657     },
54658
54659     add: function(a, b, c, d, e, f) {
54660         var me = this,
54661             out = [[], [], []],
54662             matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
54663             x,
54664             y,
54665             z,
54666             res;
54667
54668         for (x = 0; x < 3; x++) {
54669             for (y = 0; y < 3; y++) {
54670                 res = 0;
54671                 for (z = 0; z < 3; z++) {
54672                     res += me.matrix[x][z] * matrix[z][y];
54673                 }
54674                 out[x][y] = res;
54675             }
54676         }
54677         me.matrix = out;
54678     },
54679
54680     prepend: function(a, b, c, d, e, f) {
54681         var me = this,
54682             out = [[], [], []],
54683             matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
54684             x,
54685             y,
54686             z,
54687             res;
54688
54689         for (x = 0; x < 3; x++) {
54690             for (y = 0; y < 3; y++) {
54691                 res = 0;
54692                 for (z = 0; z < 3; z++) {
54693                     res += matrix[x][z] * me.matrix[z][y];
54694                 }
54695                 out[x][y] = res;
54696             }
54697         }
54698         me.matrix = out;
54699     },
54700
54701     invert: function() {
54702         var matrix = this.matrix,
54703             a = matrix[0][0],
54704             b = matrix[1][0],
54705             c = matrix[0][1],
54706             d = matrix[1][1],
54707             e = matrix[0][2],
54708             f = matrix[1][2],
54709             x = a * d - b * c;
54710         return new Ext.draw.Matrix(d / x, -b / x, -c / x, a / x, (c * f - d * e) / x, (b * e - a * f) / x);
54711     },
54712
54713     clone: function() {
54714         var matrix = this.matrix,
54715             a = matrix[0][0],
54716             b = matrix[1][0],
54717             c = matrix[0][1],
54718             d = matrix[1][1],
54719             e = matrix[0][2],
54720             f = matrix[1][2];
54721         return new Ext.draw.Matrix(a, b, c, d, e, f);
54722     },
54723
54724     translate: function(x, y) {
54725         this.prepend(1, 0, 0, 1, x, y);
54726     },
54727
54728     scale: function(x, y, cx, cy) {
54729         var me = this;
54730         if (y == null) {
54731             y = x;
54732         }
54733         me.add(1, 0, 0, 1, cx, cy);
54734         me.add(x, 0, 0, y, 0, 0);
54735         me.add(1, 0, 0, 1, -cx, -cy);
54736     },
54737
54738     rotate: function(a, x, y) {
54739         a = Ext.draw.Draw.rad(a);
54740         var me = this,
54741             cos = +Math.cos(a).toFixed(9),
54742             sin = +Math.sin(a).toFixed(9);
54743         me.add(cos, sin, -sin, cos, x, y);
54744         me.add(1, 0, 0, 1, -x, -y);
54745     },
54746
54747     x: function(x, y) {
54748         var matrix = this.matrix;
54749         return x * matrix[0][0] + y * matrix[0][1] + matrix[0][2];
54750     },
54751
54752     y: function(x, y) {
54753         var matrix = this.matrix;
54754         return x * matrix[1][0] + y * matrix[1][1] + matrix[1][2];
54755     },
54756
54757     get: function(i, j) {
54758         return + this.matrix[i][j].toFixed(4);
54759     },
54760
54761     toString: function() {
54762         var me = this;
54763         return [me.get(0, 0), me.get(0, 1), me.get(1, 0), me.get(1, 1), 0, 0].join();
54764     },
54765
54766     toSvg: function() {
54767         var me = this;
54768         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() + ")";
54769     },
54770
54771     toFilter: function() {
54772         var me = this;
54773         return "progid:DXImageTransform.Microsoft.Matrix(M11=" + me.get(0, 0) +
54774             ", M12=" + me.get(0, 1) + ", M21=" + me.get(1, 0) + ", M22=" + me.get(1, 1) +
54775             ", Dx=" + me.get(0, 2) + ", Dy=" + me.get(1, 2) + ")";
54776     },
54777
54778     offset: function() {
54779         var matrix = this.matrix;
54780         return [matrix[0][2].toFixed(4), matrix[1][2].toFixed(4)];
54781     },
54782
54783     
54784     split: function () {
54785         function norm(a) {
54786             return a[0] * a[0] + a[1] * a[1];
54787         }
54788         function normalize(a) {
54789             var mag = Math.sqrt(norm(a));
54790             a[0] /= mag;
54791             a[1] /= mag;
54792         }
54793         var matrix = this.matrix,
54794             out = {
54795                 translateX: matrix[0][2],
54796                 translateY: matrix[1][2]
54797             },
54798             row;
54799
54800         
54801         row = [[matrix[0][0], matrix[0][1]], [matrix[1][1], matrix[1][1]]];
54802         out.scaleX = Math.sqrt(norm(row[0]));
54803         normalize(row[0]);
54804
54805         out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
54806         row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
54807
54808         out.scaleY = Math.sqrt(norm(row[1]));
54809         normalize(row[1]);
54810         out.shear /= out.scaleY;
54811
54812         
54813         out.rotate = Math.asin(-row[0][1]);
54814
54815         out.isSimple = !+out.shear.toFixed(9) && (out.scaleX.toFixed(9) == out.scaleY.toFixed(9) || !out.rotate);
54816
54817         return out;
54818     }
54819 });
54820
54821 Ext.define('Ext.draw.SpriteDD', {
54822     extend: 'Ext.dd.DragSource',
54823
54824     constructor : function(sprite, cfg){
54825         var me = this,
54826             el = sprite.el;
54827         me.sprite = sprite;
54828         me.el = el;
54829         me.dragData = {el: el, sprite: sprite};
54830         me.callParent([el, cfg]);
54831         me.sprite.setStyle('cursor', 'move');
54832     },
54833
54834     showFrame: Ext.emptyFn,
54835     createFrame : Ext.emptyFn,
54836
54837     getDragEl : function(e){
54838         return this.el;
54839     },
54840     
54841     getRegion: function() {
54842         var me = this,
54843             el = me.el,
54844             pos, x1, x2, y1, y2, t, r, b, l, bbox, sprite;
54845         
54846         sprite = me.sprite;
54847         bbox = sprite.getBBox();
54848         
54849         try {
54850             pos = Ext.core.Element.getXY(el);
54851         } catch (e) { }
54852
54853         if (!pos) {
54854             return null;
54855         }
54856
54857         x1 = pos[0];
54858         x2 = x1 + bbox.width;
54859         y1 = pos[1];
54860         y2 = y1 + bbox.height;
54861         
54862         return Ext.create('Ext.util.Region', y1, x2, y2, x1);
54863     },
54864
54865     
54866      
54867     startDrag: function(x, y) {
54868         var me = this,
54869             attr = me.sprite.attr,
54870             trans = attr.translation;
54871         if (me.sprite.vml) {
54872             me.prevX = x + attr.x;
54873             me.prevY = y + attr.y;
54874         } else {
54875             me.prevX = x - trans.x;
54876             me.prevY = y - trans.y;
54877         }
54878     },
54879
54880     onDrag: function(e) {
54881         var xy = e.getXY(),
54882             me = this,
54883             sprite = me.sprite,
54884             attr = sprite.attr;
54885         me.translateX = xy[0] - me.prevX;
54886         me.translateY = xy[1] - me.prevY;
54887         sprite.setAttributes({
54888             translate: {
54889                 x: me.translateX,
54890                 y: me.translateY
54891             }
54892         }, true);
54893         if (sprite.vml) {
54894             me.prevX = xy[0] + attr.x || 0;
54895             me.prevY = xy[1] + attr.y || 0;
54896         }
54897     }
54898 });
54899
54900 Ext.define('Ext.draw.Sprite', {
54901     
54902
54903     mixins: {
54904         observable: 'Ext.util.Observable',
54905         animate: 'Ext.util.Animate'
54906     },
54907
54908     requires: ['Ext.draw.SpriteDD'],
54909
54910     
54911
54912     dirty: false,
54913     dirtyHidden: false,
54914     dirtyTransform: false,
54915     dirtyPath: true,
54916     dirtyFont: true,
54917     zIndexDirty: true,
54918     isSprite: true,
54919     zIndex: 0,
54920     fontProperties: [
54921         'font',
54922         'font-size',
54923         'font-weight',
54924         'font-style',
54925         'font-family',
54926         'text-anchor',
54927         'text'
54928     ],
54929     pathProperties: [
54930         'x',
54931         'y',
54932         'd',
54933         'path',
54934         'height',
54935         'width',
54936         'radius',
54937         'r',
54938         'rx',
54939         'ry',
54940         'cx',
54941         'cy'
54942     ],
54943     constructor: function(config) {
54944         var me = this;
54945         config = config || {};
54946         me.id = Ext.id(null, 'ext-sprite-');
54947         me.transformations = [];
54948         Ext.copyTo(this, config, 'surface,group,type,draggable');
54949         
54950         me.bbox = {};
54951         me.attr = {
54952             zIndex: 0,
54953             translation: {
54954                 x: null,
54955                 y: null
54956             },
54957             rotation: {
54958                 degrees: null,
54959                 x: null,
54960                 y: null
54961             },
54962             scaling: {
54963                 x: null,
54964                 y: null,
54965                 cx: null,
54966                 cy: null
54967             }
54968         };
54969         
54970         delete config.surface;
54971         delete config.group;
54972         delete config.type;
54973         delete config.draggable;
54974         me.setAttributes(config);
54975         me.addEvents(
54976             'beforedestroy',
54977             'destroy',
54978             'render',
54979             'mousedown',
54980             'mouseup',
54981             'mouseover',
54982             'mouseout',
54983             'mousemove',
54984             'click'
54985         );
54986         me.mixins.observable.constructor.apply(this, arguments);
54987     },
54988
54989     
54990     initDraggable: function() {
54991         var me = this;
54992         me.draggable = true;
54993         
54994         if (!me.el) {
54995             me.surface.createSpriteElement(me);
54996         }
54997         me.dd = Ext.create('Ext.draw.SpriteDD', me, Ext.isBoolean(me.draggable) ? null : me.draggable);
54998         me.on('beforedestroy', me.dd.destroy, me.dd);
54999     },
55000
55001     
55002     setAttributes: function(attrs, redraw) {
55003         var me = this,
55004             fontProps = me.fontProperties,
55005             fontPropsLength = fontProps.length,
55006             pathProps = me.pathProperties,
55007             pathPropsLength = pathProps.length,
55008             hasSurface = !!me.surface,
55009             custom = hasSurface && me.surface.customAttributes || {},
55010             spriteAttrs = me.attr,
55011             attr, i, translate, translation, rotate, rotation, scale, scaling;
55012
55013         attrs = Ext.apply({}, attrs);
55014         for (attr in custom) {
55015             if (attrs.hasOwnProperty(attr) && typeof custom[attr] == "function") {
55016                 Ext.apply(attrs, custom[attr].apply(me, [].concat(attrs[attr])));
55017             }
55018         }
55019
55020         
55021         if (!!attrs.hidden !== !!spriteAttrs.hidden) {
55022             me.dirtyHidden = true;
55023         }
55024
55025         
55026         for (i = 0; i < pathPropsLength; i++) {
55027             attr = pathProps[i];
55028             if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
55029                 me.dirtyPath = true;
55030                 break;
55031             }
55032         }
55033
55034         
55035         if ('zIndex' in attrs) {
55036             me.zIndexDirty = true;
55037         }
55038
55039         
55040         for (i = 0; i < fontPropsLength; i++) {
55041             attr = fontProps[i];
55042             if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
55043                 me.dirtyFont = true;
55044                 break;
55045             }
55046         }
55047
55048         translate = attrs.translate;
55049         translation = spriteAttrs.translation;
55050         if (translate) {
55051             if ((translate.x && translate.x !== translation.x) ||
55052                 (translate.y && translate.y !== translation.y)) {
55053                 Ext.apply(translation, translate);
55054                 me.dirtyTransform = true;
55055             }
55056             delete attrs.translate;
55057         }
55058
55059         rotate = attrs.rotate;
55060         rotation = spriteAttrs.rotation;
55061         if (rotate) {
55062             if ((rotate.x && rotate.x !== rotation.x) || 
55063                 (rotate.y && rotate.y !== rotation.y) ||
55064                 (rotate.degrees && rotate.degrees !== rotation.degrees)) {
55065                 Ext.apply(rotation, rotate);
55066                 me.dirtyTransform = true;
55067             }
55068             delete attrs.rotate;
55069         }
55070
55071         scale = attrs.scale;
55072         scaling = spriteAttrs.scaling;
55073         if (scale) {
55074             if ((scale.x && scale.x !== scaling.x) || 
55075                 (scale.y && scale.y !== scaling.y) ||
55076                 (scale.cx && scale.cx !== scaling.cx) ||
55077                 (scale.cy && scale.cy !== scaling.cy)) {
55078                 Ext.apply(scaling, scale);
55079                 me.dirtyTransform = true;
55080             }
55081             delete attrs.scale;
55082         }
55083
55084         Ext.apply(spriteAttrs, attrs);
55085         me.dirty = true;
55086
55087         if (redraw === true && hasSurface) {
55088             me.redraw();
55089         }
55090         return this;
55091     },
55092
55093     
55094     getBBox: function() {
55095         return this.surface.getBBox(this);
55096     },
55097     
55098     setText: function(text) {
55099         return this.surface.setText(this, text);
55100     },
55101
55102     
55103     hide: function(redraw) {
55104         this.setAttributes({
55105             hidden: true
55106         }, redraw);
55107         return this;
55108     },
55109
55110     
55111     show: function(redraw) {
55112         this.setAttributes({
55113             hidden: false
55114         }, redraw);
55115         return this;
55116     },
55117
55118     
55119     remove: function() {
55120         if (this.surface) {
55121             this.surface.remove(this);
55122             return true;
55123         }
55124         return false;
55125     },
55126
55127     onRemove: function() {
55128         this.surface.onRemove(this);
55129     },
55130
55131     
55132     destroy: function() {
55133         var me = this;
55134         if (me.fireEvent('beforedestroy', me) !== false) {
55135             me.remove();
55136             me.surface.onDestroy(me);
55137             me.clearListeners();
55138             me.fireEvent('destroy');
55139         }
55140     },
55141
55142     
55143     redraw: function() {
55144         this.surface.renderItem(this);
55145         return this;
55146     },
55147
55148     
55149     setStyle: function() {
55150         this.el.setStyle.apply(this.el, arguments);
55151         return this;
55152     },
55153
55154     
55155     addCls: function(obj) {
55156         this.surface.addCls(this, obj);
55157         return this;
55158     },
55159
55160     
55161     removeCls: function(obj) {
55162         this.surface.removeCls(this, obj);
55163         return this;
55164     }
55165 });
55166
55167
55168 Ext.define('Ext.draw.engine.Svg', {
55169
55170     
55171
55172     extend: 'Ext.draw.Surface',
55173
55174     requires: ['Ext.draw.Draw', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.core.Element'],
55175
55176     
55177
55178     engine: 'Svg',
55179
55180     trimRe: /^\s+|\s+$/g,
55181     spacesRe: /\s+/,
55182     xlink: "http:/" + "/www.w3.org/1999/xlink",
55183
55184     translateAttrs: {
55185         radius: "r",
55186         radiusX: "rx",
55187         radiusY: "ry",
55188         path: "d",
55189         lineWidth: "stroke-width",
55190         fillOpacity: "fill-opacity",
55191         strokeOpacity: "stroke-opacity",
55192         strokeLinejoin: "stroke-linejoin"
55193     },
55194
55195     minDefaults: {
55196         circle: {
55197             cx: 0,
55198             cy: 0,
55199             r: 0,
55200             fill: "none",
55201             stroke: null,
55202             "stroke-width": null,
55203             opacity: null,
55204             "fill-opacity": null,
55205             "stroke-opacity": null
55206         },
55207         ellipse: {
55208             cx: 0,
55209             cy: 0,
55210             rx: 0,
55211             ry: 0,
55212             fill: "none",
55213             stroke: null,
55214             "stroke-width": null,
55215             opacity: null,
55216             "fill-opacity": null,
55217             "stroke-opacity": null
55218         },
55219         rect: {
55220             x: 0,
55221             y: 0,
55222             width: 0,
55223             height: 0,
55224             rx: 0,
55225             ry: 0,
55226             fill: "none",
55227             stroke: null,
55228             "stroke-width": null,
55229             opacity: null,
55230             "fill-opacity": null,
55231             "stroke-opacity": null
55232         },
55233         text: {
55234             x: 0,
55235             y: 0,
55236             "text-anchor": "start",
55237             "font-family": null,
55238             "font-size": null,
55239             "font-weight": null,
55240             "font-style": null,
55241             fill: "#000",
55242             stroke: null,
55243             "stroke-width": null,
55244             opacity: null,
55245             "fill-opacity": null,
55246             "stroke-opacity": null
55247         },
55248         path: {
55249             d: "M0,0",
55250             fill: "none",
55251             stroke: null,
55252             "stroke-width": null,
55253             opacity: null,
55254             "fill-opacity": null,
55255             "stroke-opacity": null
55256         },
55257         image: {
55258             x: 0,
55259             y: 0,
55260             width: 0,
55261             height: 0,
55262             preserveAspectRatio: "none",
55263             opacity: null
55264         }
55265     },
55266
55267     createSvgElement: function(type, attrs) {
55268         var el = this.domRef.createElementNS("http:/" + "/www.w3.org/2000/svg", type),
55269             key;
55270         if (attrs) {
55271             for (key in attrs) {
55272                 el.setAttribute(key, String(attrs[key]));
55273             }
55274         }
55275         return el;
55276     },
55277
55278     createSpriteElement: function(sprite) {
55279         
55280         var el = this.createSvgElement(sprite.type);
55281         el.id = sprite.id;
55282         if (el.style) {
55283             el.style.webkitTapHighlightColor = "rgba(0,0,0,0)";
55284         }
55285         sprite.el = Ext.get(el);
55286         this.applyZIndex(sprite); 
55287         sprite.matrix = Ext.create('Ext.draw.Matrix');
55288         sprite.bbox = {
55289             plain: 0,
55290             transform: 0
55291         };
55292         sprite.fireEvent("render", sprite);
55293         return el;
55294     },
55295
55296     getBBox: function (sprite, isWithoutTransform) {
55297         var realPath = this["getPath" + sprite.type](sprite);
55298         if (isWithoutTransform) {
55299             sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath);
55300             return sprite.bbox.plain;
55301         }
55302         sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
55303         return sprite.bbox.transform;
55304     },
55305     
55306     getBBoxText: function (sprite) {
55307         var bbox = {},
55308             bb, height, width, i, ln, el;
55309
55310         if (sprite && sprite.el) {
55311             el = sprite.el.dom;
55312             try {
55313                 bbox = el.getBBox();
55314                 return bbox;
55315             } catch(e) {
55316                 
55317             }
55318             bbox = {x: bbox.x, y: Infinity, width: 0, height: 0};
55319             ln = el.getNumberOfChars();
55320             for (i = 0; i < ln; i++) {
55321                 bb = el.getExtentOfChar(i);
55322                 bbox.y = Math.min(bb.y, bbox.y);
55323                 height = bb.y + bb.height - bbox.y;
55324                 bbox.height = Math.max(bbox.height, height);
55325                 width = bb.x + bb.width - bbox.x;
55326                 bbox.width = Math.max(bbox.width, width);
55327             }
55328             return bbox;
55329         }
55330     },
55331
55332     hide: function() {
55333         Ext.get(this.el).hide();
55334     },
55335
55336     show: function() {
55337         Ext.get(this.el).show();
55338     },
55339
55340     hidePrim: function(sprite) {
55341         this.addCls(sprite, Ext.baseCSSPrefix + 'hide-visibility');
55342     },
55343
55344     showPrim: function(sprite) {
55345         this.removeCls(sprite, Ext.baseCSSPrefix + 'hide-visibility');
55346     },
55347
55348     getDefs: function() {
55349         return this._defs || (this._defs = this.createSvgElement("defs"));
55350     },
55351
55352     transform: function(sprite) {
55353         var me = this,
55354             matrix = Ext.create('Ext.draw.Matrix'),
55355             transforms = sprite.transformations,
55356             transformsLength = transforms.length,
55357             i = 0,
55358             transform, type;
55359             
55360         for (; i < transformsLength; i++) {
55361             transform = transforms[i];
55362             type = transform.type;
55363             if (type == "translate") {
55364                 matrix.translate(transform.x, transform.y);
55365             }
55366             else if (type == "rotate") {
55367                 matrix.rotate(transform.degrees, transform.x, transform.y);
55368             }
55369             else if (type == "scale") {
55370                 matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY);
55371             }
55372         }
55373         sprite.matrix = matrix;
55374         sprite.el.set({transform: matrix.toSvg()});
55375     },
55376
55377     setSize: function(w, h) {
55378         var me = this,
55379             el = me.el;
55380         
55381         w = +w || me.width;
55382         h = +h || me.height;
55383         me.width = w;
55384         me.height = h;
55385
55386         el.setSize(w, h);
55387         el.set({
55388             width: w,
55389             height: h
55390         });
55391         me.callParent([w, h]);
55392     },
55393
55394     
55395     getRegion: function() {
55396         
55397         
55398         var svgXY = this.el.getXY(),
55399             rectXY = this.bgRect.getXY(),
55400             max = Math.max,
55401             x = max(svgXY[0], rectXY[0]),
55402             y = max(svgXY[1], rectXY[1]);
55403         return {
55404             left: x,
55405             top: y,
55406             right: x + this.width,
55407             bottom: y + this.height
55408         };
55409     },
55410
55411     onRemove: function(sprite) {
55412         if (sprite.el) {
55413             sprite.el.remove();
55414             delete sprite.el;
55415         }
55416         this.callParent(arguments);
55417     },
55418     
55419     setViewBox: function(x, y, width, height) {
55420         if (isFinite(x) && isFinite(y) && isFinite(width) && isFinite(height)) {
55421             this.callParent(arguments);
55422             this.el.dom.setAttribute("viewBox", [x, y, width, height].join(" "));
55423         }
55424     },
55425
55426     render: function (container) {
55427         var me = this;
55428         if (!me.el) {
55429             var width = me.width || 10,
55430                 height = me.height || 10,
55431                 el = me.createSvgElement('svg', {
55432                     xmlns: "http:/" + "/www.w3.org/2000/svg",
55433                     version: 1.1,
55434                     width: width,
55435                     height: height
55436                 }),
55437                 defs = me.getDefs(),
55438
55439                 
55440                 
55441                 
55442                 
55443                 bgRect = me.createSvgElement("rect", {
55444                     width: "100%",
55445                     height: "100%",
55446                     fill: "#000",
55447                     stroke: "none",
55448                     opacity: 0
55449                 }),
55450                 webkitRect;
55451             
55452                 if (Ext.isSafari3) {
55453                     
55454                     webkitRect = me.createSvgElement("rect", {
55455                         x: -10,
55456                         y: -10,
55457                         width: "110%",
55458                         height: "110%",
55459                         fill: "none",
55460                         stroke: "#000"
55461                     });
55462                 }
55463             el.appendChild(defs);
55464             if (Ext.isSafari3) {
55465                 el.appendChild(webkitRect);
55466             }
55467             el.appendChild(bgRect);
55468             container.appendChild(el);
55469             me.el = Ext.get(el);
55470             me.bgRect = Ext.get(bgRect);
55471             if (Ext.isSafari3) {
55472                 me.webkitRect = Ext.get(webkitRect);
55473                 me.webkitRect.hide();
55474             }
55475             me.el.on({
55476                 scope: me,
55477                 mouseup: me.onMouseUp,
55478                 mousedown: me.onMouseDown,
55479                 mouseover: me.onMouseOver,
55480                 mouseout: me.onMouseOut,
55481                 mousemove: me.onMouseMove,
55482                 mouseenter: me.onMouseEnter,
55483                 mouseleave: me.onMouseLeave,
55484                 click: me.onClick
55485             });
55486         }
55487         me.renderAll();
55488     },
55489
55490     
55491     onMouseEnter: function(e) {
55492         if (this.el.parent().getRegion().contains(e.getPoint())) {
55493             this.fireEvent('mouseenter', e);
55494         }
55495     },
55496
55497     
55498     onMouseLeave: function(e) {
55499         if (!this.el.parent().getRegion().contains(e.getPoint())) {
55500             this.fireEvent('mouseleave', e);
55501         }
55502     },
55503     
55504     processEvent: function(name, e) {
55505         var target = e.getTarget(),
55506             surface = this.surface,
55507             sprite;
55508
55509         this.fireEvent(name, e);
55510         
55511         if (target.nodeName == "tspan" && target.parentNode) {
55512             target = target.parentNode;
55513         }
55514         sprite = this.items.get(target.id);
55515         if (sprite) {
55516             sprite.fireEvent(name, sprite, e);
55517         }
55518     },
55519
55520     
55521     tuneText: function (sprite, attrs) {
55522         var el = sprite.el.dom,
55523             tspans = [],
55524             height, tspan, text, i, ln, texts, factor;
55525
55526         if (attrs.hasOwnProperty("text")) {
55527            tspans = this.setText(sprite, attrs.text);
55528         }
55529         
55530         if (tspans.length) {
55531             height = this.getBBoxText(sprite).height;
55532             for (i = 0, ln = tspans.length; i < ln; i++) {
55533                 
55534                 
55535                 factor = (Ext.isFF3_0 || Ext.isFF3_5) ? 2 : 4;
55536                 tspans[i].setAttribute("dy", i ? height * 1.2 : height / factor);
55537             }
55538             sprite.dirty = true;
55539         }
55540     },
55541
55542     setText: function(sprite, textString) {
55543          var me = this,
55544              el = sprite.el.dom,
55545              x = el.getAttribute("x"),
55546              tspans = [],
55547              height, tspan, text, i, ln, texts;
55548         
55549         while (el.firstChild) {
55550             el.removeChild(el.firstChild);
55551         }
55552         
55553         texts = String(textString).split("\n");
55554         for (i = 0, ln = texts.length; i < ln; i++) {
55555             text = texts[i];
55556             if (text) {
55557                 tspan = me.createSvgElement("tspan");
55558                 tspan.appendChild(document.createTextNode(Ext.htmlDecode(text)));
55559                 tspan.setAttribute("x", x);
55560                 el.appendChild(tspan);
55561                 tspans[i] = tspan;
55562             }
55563         }
55564         return tspans;
55565     },
55566
55567     renderAll: function() {
55568         this.items.each(this.renderItem, this);
55569     },
55570
55571     renderItem: function (sprite) {
55572         if (!this.el) {
55573             return;
55574         }
55575         if (!sprite.el) {
55576             this.createSpriteElement(sprite);
55577         }
55578         if (sprite.zIndexDirty) {
55579             this.applyZIndex(sprite);
55580         }
55581         if (sprite.dirty) {
55582             this.applyAttrs(sprite);
55583             this.applyTransformations(sprite);
55584         }
55585     },
55586
55587     redraw: function(sprite) {
55588         sprite.dirty = sprite.zIndexDirty = true;
55589         this.renderItem(sprite);
55590     },
55591
55592     applyAttrs: function (sprite) {
55593         var me = this,
55594             el = sprite.el,
55595             group = sprite.group,
55596             sattr = sprite.attr,
55597             groups, i, ln, attrs, font, key, style, name, rect;
55598
55599         if (group) {
55600             groups = [].concat(group);
55601             ln = groups.length;
55602             for (i = 0; i < ln; i++) {
55603                 group = groups[i];
55604                 me.getGroup(group).add(sprite);
55605             }
55606             delete sprite.group;
55607         }
55608         attrs = me.scrubAttrs(sprite) || {};
55609
55610         
55611             sprite.bbox.plain = 0;
55612             sprite.bbox.transform = 0;
55613             if (sprite.type == "circle" || sprite.type == "ellipse") {
55614                 attrs.cx = attrs.cx || attrs.x;
55615                 attrs.cy = attrs.cy || attrs.y;
55616             }
55617             else if (sprite.type == "rect") {
55618                 attrs.rx = attrs.ry = attrs.r;
55619             }
55620             else if (sprite.type == "path" && attrs.d) {
55621                 attrs.d = Ext.draw.Draw.pathToString(Ext.draw.Draw.pathToAbsolute(attrs.d));
55622                 
55623             }
55624             sprite.dirtyPath = false;
55625         
55626         
55627         
55628         
55629
55630         if (attrs['clip-rect']) {
55631             me.setClip(sprite, attrs);
55632             delete attrs['clip-rect'];
55633         }
55634         if (sprite.type == 'text' && attrs.font && sprite.dirtyFont) {
55635             el.set({ style: "font: " + attrs.font});
55636             sprite.dirtyFont = false;
55637         }
55638         if (sprite.type == "image") {
55639             el.dom.setAttributeNS(me.xlink, "href", attrs.src);
55640         }
55641         Ext.applyIf(attrs, me.minDefaults[sprite.type]);
55642
55643         if (sprite.dirtyHidden) {
55644             (sattr.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
55645             sprite.dirtyHidden = false;
55646         }
55647         for (key in attrs) {
55648             if (attrs.hasOwnProperty(key) && attrs[key] != null) {
55649                 el.dom.setAttribute(key, attrs[key]);
55650             }
55651         }
55652         if (sprite.type == 'text') {
55653             me.tuneText(sprite, attrs);
55654         }
55655
55656         
55657         style = sattr.style;
55658         if (style) {
55659             el.setStyle(style);
55660         }
55661
55662         sprite.dirty = false;
55663
55664         if (Ext.isSafari3) {
55665             
55666             me.webkitRect.show();
55667             setTimeout(function () {
55668                 me.webkitRect.hide();
55669             });
55670         }
55671     },
55672
55673     setClip: function(sprite, params) {
55674         var me = this,
55675             rect = params["clip-rect"],
55676             clipEl, clipPath;
55677         if (rect) {
55678             if (sprite.clip) {
55679                 sprite.clip.parentNode.parentNode.removeChild(sprite.clip.parentNode);
55680             }
55681             clipEl = me.createSvgElement('clipPath');
55682             clipPath = me.createSvgElement('rect');
55683             clipEl.id = Ext.id(null, 'ext-clip-');
55684             clipPath.setAttribute("x", rect.x);
55685             clipPath.setAttribute("y", rect.y);
55686             clipPath.setAttribute("width", rect.width);
55687             clipPath.setAttribute("height", rect.height);
55688             clipEl.appendChild(clipPath);
55689             me.getDefs().appendChild(clipEl);
55690             sprite.el.dom.setAttribute("clip-path", "url(#" + clipEl.id + ")");
55691             sprite.clip = clipPath;
55692         }
55693         
55694         
55695         
55696         
55697         
55698         
55699     },
55700
55701     
55702     applyZIndex: function(sprite) {
55703         var idx = this.normalizeSpriteCollection(sprite),
55704             el = sprite.el,
55705             prevEl;
55706         if (this.el.dom.childNodes[idx + 2] !== el.dom) { 
55707             if (idx > 0) {
55708                 
55709                 do {
55710                     prevEl = this.items.getAt(--idx).el;
55711                 } while (!prevEl && idx > 0);
55712             }
55713             el.insertAfter(prevEl || this.bgRect);
55714         }
55715         sprite.zIndexDirty = false;
55716     },
55717
55718     createItem: function (config) {
55719         var sprite = Ext.create('Ext.draw.Sprite', config);
55720         sprite.surface = this;
55721         return sprite;
55722     },
55723
55724     addGradient: function(gradient) {
55725         gradient = Ext.draw.Draw.parseGradient(gradient);
55726         var ln = gradient.stops.length,
55727             vector = gradient.vector,
55728             gradientEl,
55729             stop,
55730             stopEl,
55731             i;
55732         if (gradient.type == "linear") {
55733             gradientEl = this.createSvgElement("linearGradient");
55734             gradientEl.setAttribute("x1", vector[0]);
55735             gradientEl.setAttribute("y1", vector[1]);
55736             gradientEl.setAttribute("x2", vector[2]);
55737             gradientEl.setAttribute("y2", vector[3]);
55738         }
55739         else {
55740             gradientEl = this.createSvgElement("radialGradient");
55741             gradientEl.setAttribute("cx", gradient.centerX);
55742             gradientEl.setAttribute("cy", gradient.centerY);
55743             gradientEl.setAttribute("r", gradient.radius);
55744             if (Ext.isNumber(gradient.focalX) && Ext.isNumber(gradient.focalY)) {
55745                 gradientEl.setAttribute("fx", gradient.focalX);
55746                 gradientEl.setAttribute("fy", gradient.focalY);
55747             }
55748         }    
55749         gradientEl.id = gradient.id;
55750         this.getDefs().appendChild(gradientEl);
55751
55752         for (i = 0; i < ln; i++) {
55753             stop = gradient.stops[i];
55754             stopEl = this.createSvgElement("stop");
55755             stopEl.setAttribute("offset", stop.offset + "%");
55756             stopEl.setAttribute("stop-color", stop.color);
55757             stopEl.setAttribute("stop-opacity",stop.opacity);
55758             gradientEl.appendChild(stopEl);
55759         }
55760     },
55761
55762     
55763     hasCls: function(sprite, className) {
55764         return className && (' ' + (sprite.el.dom.getAttribute('class') || '') + ' ').indexOf(' ' + className + ' ') != -1;
55765     },
55766
55767     addCls: function(sprite, className) {
55768         var el = sprite.el,
55769             i,
55770             len,
55771             v,
55772             cls = [],
55773             curCls =  el.getAttribute('class') || '';
55774         
55775         if (!Ext.isArray(className)) {
55776             if (typeof className == 'string' && !this.hasCls(sprite, className)) {
55777                 el.set({ 'class': curCls + ' ' + className });
55778             }
55779         }
55780         else {
55781             for (i = 0, len = className.length; i < len; i++) {
55782                 v = className[i];
55783                 if (typeof v == 'string' && (' ' + curCls + ' ').indexOf(' ' + v + ' ') == -1) {
55784                     cls.push(v);
55785                 }
55786             }
55787             if (cls.length) {
55788                 el.set({ 'class': ' ' + cls.join(' ') });
55789             }
55790         }
55791     },
55792
55793     removeCls: function(sprite, className) {
55794         var me = this,
55795             el = sprite.el,
55796             curCls =  el.getAttribute('class') || '',
55797             i, idx, len, cls, elClasses;
55798         if (!Ext.isArray(className)){
55799             className = [className];
55800         }
55801         if (curCls) {
55802             elClasses = curCls.replace(me.trimRe, ' ').split(me.spacesRe);
55803             for (i = 0, len = className.length; i < len; i++) {
55804                 cls = className[i];
55805                 if (typeof cls == 'string') {
55806                     cls = cls.replace(me.trimRe, '');
55807                     idx = Ext.Array.indexOf(elClasses, cls);
55808                     if (idx != -1) {
55809                         elClasses.splice(idx, 1);
55810                     }
55811                 }
55812             }
55813             el.set({ 'class': elClasses.join(' ') });
55814         }
55815     },
55816
55817     destroy: function() {
55818         var me = this;
55819         
55820         me.callParent();
55821         if (me.el) {
55822             me.el.remove();
55823         }
55824         delete me.el;
55825     }
55826 });
55827
55828
55829 Ext.define('Ext.draw.engine.Vml', {
55830
55831     
55832
55833     extend: 'Ext.draw.Surface',
55834
55835     requires: ['Ext.draw.Draw', 'Ext.draw.Color', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.core.Element'],
55836
55837     
55838
55839     engine: 'Vml',
55840
55841     map: {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
55842     bitesRe: /([clmz]),?([^clmz]*)/gi,
55843     valRe: /-?[^,\s-]+/g,
55844     fillUrlRe: /^url\(\s*['"]?([^\)]+?)['"]?\s*\)$/i,
55845     pathlike: /^(path|rect)$/,
55846     NonVmlPathRe: /[ahqstv]/ig, // Non-VML Pathing ops
55847     partialPathRe: /[clmz]/g,
55848     fontFamilyRe: /^['"]+|['"]+$/g,
55849     baseVmlCls: Ext.baseCSSPrefix + 'vml-base',
55850     vmlGroupCls: Ext.baseCSSPrefix + 'vml-group',
55851     spriteCls: Ext.baseCSSPrefix + 'vml-sprite',
55852     measureSpanCls: Ext.baseCSSPrefix + 'vml-measure-span',
55853     zoom: 21600,
55854     coordsize: 1000,
55855     coordorigin: '0 0',
55856
55857     // @private
55858     // Convert an SVG standard path into a VML path
55859     path2vml: function (path) {
55860         var me = this,
55861             nonVML =  me.NonVmlPathRe,
55862             map = me.map,
55863             val = me.valRe,
55864             zoom = me.zoom,
55865             bites = me.bitesRe,
55866             command = Ext.Function.bind(Ext.draw.Draw.pathToAbsolute, Ext.draw.Draw),
55867             res, pa, p, r, i, ii, j, jj;
55868         if (String(path).match(nonVML)) {
55869             command = Ext.Function.bind(Ext.draw.Draw.path2curve, Ext.draw.Draw);
55870         } else if (!String(path).match(me.partialPathRe)) {
55871             res = String(path).replace(bites, function (all, command, args) {
55872                 var vals = [],
55873                     isMove = command.toLowerCase() == "m",
55874                     res = map[command];
55875                 args.replace(val, function (value) {
55876                     if (isMove && vals[length] == 2) {
55877                         res += vals + map[command == "m" ? "l" : "L"];
55878                         vals = [];
55879                     }
55880                     vals.push(Math.round(value * zoom));
55881                 });
55882                 return res + vals;
55883             });
55884             return res;
55885         }
55886         pa = command(path);
55887         res = [];
55888         for (i = 0, ii = pa.length; i < ii; i++) {
55889             p = pa[i];
55890             r = pa[i][0].toLowerCase();
55891             if (r == "z") {
55892                 r = "x";
55893             }
55894             for (j = 1, jj = p.length; j < jj; j++) {
55895                 r += Math.round(p[j] * me.zoom) + (j != jj - 1 ? "," : "");
55896             }
55897             res.push(r);
55898         }
55899         return res.join(" ");
55900     },
55901
55902     // @private - set of attributes which need to be translated from the sprite API to the native browser API
55903     translateAttrs: {
55904         radius: "r",
55905         radiusX: "rx",
55906         radiusY: "ry",
55907         lineWidth: "stroke-width",
55908         fillOpacity: "fill-opacity",
55909         strokeOpacity: "stroke-opacity",
55910         strokeLinejoin: "stroke-linejoin"
55911     },
55912
55913     // @private - Minimun set of defaults for different types of sprites.
55914     minDefaults: {
55915         circle: {
55916             fill: "none",
55917             stroke: null,
55918             "stroke-width": null,
55919             opacity: null,
55920             "fill-opacity": null,
55921             "stroke-opacity": null
55922         },
55923         ellipse: {
55924             cx: 0,
55925             cy: 0,
55926             rx: 0,
55927             ry: 0,
55928             fill: "none",
55929             stroke: null,
55930             "stroke-width": null,
55931             opacity: null,
55932             "fill-opacity": null,
55933             "stroke-opacity": null
55934         },
55935         rect: {
55936             x: 0,
55937             y: 0,
55938             width: 0,
55939             height: 0,
55940             rx: 0,
55941             ry: 0,
55942             fill: "none",
55943             stroke: null,
55944             "stroke-width": null,
55945             opacity: null,
55946             "fill-opacity": null,
55947             "stroke-opacity": null
55948         },
55949         text: {
55950             x: 0,
55951             y: 0,
55952             "text-anchor": "start",
55953             font: '10px "Arial"',
55954             fill: "#000",
55955             stroke: null,
55956             "stroke-width": null,
55957             opacity: null,
55958             "fill-opacity": null,
55959             "stroke-opacity": null
55960         },
55961         path: {
55962             d: "M0,0",
55963             fill: "none",
55964             stroke: null,
55965             "stroke-width": null,
55966             opacity: null,
55967             "fill-opacity": null,
55968             "stroke-opacity": null
55969         },
55970         image: {
55971             x: 0,
55972             y: 0,
55973             width: 0,
55974             height: 0,
55975             preserveAspectRatio: "none",
55976             opacity: null
55977         }
55978     },
55979
55980     // private
55981     onMouseEnter: function(e) {
55982         this.fireEvent("mouseenter", e);
55983     },
55984
55985     // private
55986     onMouseLeave: function(e) {
55987         this.fireEvent("mouseleave", e);
55988     },
55989
55990     // @private - Normalize a delegated single event from the main container to each sprite and sprite group
55991     processEvent: function(name, e) {
55992         var target = e.getTarget(),
55993             surface = this.surface,
55994             sprite;
55995         this.fireEvent(name, e);
55996         sprite = this.items.get(target.id);
55997         if (sprite) {
55998             sprite.fireEvent(name, sprite, e);
55999         }
56000     },
56001
56002     // Create the VML element/elements and append them to the DOM
56003     createSpriteElement: function(sprite) {
56004         var me = this,
56005             attr = sprite.attr,
56006             type = sprite.type,
56007             zoom = me.zoom,
56008             vml = sprite.vml || (sprite.vml = {}),
56009             round = Math.round,
56010             el = (type === 'image') ? me.createNode('image') : me.createNode('shape'),
56011             path, skew, textPath;
56012
56013         el.coordsize = zoom + ' ' + zoom;
56014         el.coordorigin = attr.coordorigin || "0 0";
56015         Ext.get(el).addCls(me.spriteCls);
56016         if (type == "text") {
56017             vml.path = path = me.createNode("path");
56018             path.textpathok = true;
56019             vml.textpath = textPath = me.createNode("textpath");
56020             textPath.on = true;
56021             el.appendChild(textPath);
56022             el.appendChild(path);
56023         }
56024         el.id = sprite.id;
56025         sprite.el = Ext.get(el);
56026         me.el.appendChild(el);
56027         if (type !== 'image') {
56028             skew = me.createNode("skew");
56029             skew.on = true;
56030             el.appendChild(skew);
56031             sprite.skew = skew;
56032         }
56033         sprite.matrix = Ext.create('Ext.draw.Matrix');
56034         sprite.bbox = {
56035             plain: null,
56036             transform: null
56037         };
56038         sprite.fireEvent("render", sprite);
56039         return sprite.el;
56040     },
56041
56042     // @private - Get bounding box for the sprite.  The Sprite itself has the public method.
56043     getBBox: function (sprite, isWithoutTransform) {
56044         var realPath = this["getPath" + sprite.type](sprite);
56045         if (isWithoutTransform) {
56046             sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath);
56047             return sprite.bbox.plain;
56048         }
56049         sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
56050         return sprite.bbox.transform;
56051     },
56052
56053     getBBoxText: function (sprite) {
56054         var vml = sprite.vml;
56055         return {
56056             x: vml.X + (vml.bbx || 0) - vml.W / 2,
56057             y: vml.Y - vml.H / 2,
56058             width: vml.W,
56059             height: vml.H
56060         };
56061     },
56062
56063     applyAttrs: function (sprite) {
56064         var me = this,
56065             vml = sprite.vml,
56066             group = sprite.group,
56067             spriteAttr = sprite.attr,
56068             el = sprite.el,
56069             dom = el.dom,
56070             style, name, groups, i, ln, scrubbedAttrs, font, key, bbox;
56071
56072         if (group) {
56073             groups = [].concat(group);
56074             ln = groups.length;
56075             for (i = 0; i < ln; i++) {
56076                 group = groups[i];
56077                 me.getGroup(group).add(sprite);
56078             }
56079             delete sprite.group;
56080         }
56081         scrubbedAttrs = me.scrubAttrs(sprite) || {};
56082
56083         if (sprite.zIndexDirty) {
56084             me.setZIndex(sprite);
56085         }
56086
56087         // Apply minimum default attributes
56088         Ext.applyIf(scrubbedAttrs, me.minDefaults[sprite.type]);
56089
56090         if (sprite.type == 'image') {
56091             Ext.apply(sprite.attr, {
56092                 x: scrubbedAttrs.x,
56093                 y: scrubbedAttrs.y,
56094                 width: scrubbedAttrs.width,
56095                 height: scrubbedAttrs.height
56096             });
56097             bbox = sprite.getBBox();
56098             el.setStyle({
56099                 width: bbox.width + 'px',
56100                 height: bbox.height + 'px'
56101             });
56102             dom.src = scrubbedAttrs.src;
56103         }
56104
56105         if (dom.href) {
56106             dom.href = scrubbedAttrs.href;
56107         }
56108         if (dom.title) {
56109             dom.title = scrubbedAttrs.title;
56110         }
56111         if (dom.target) {
56112             dom.target = scrubbedAttrs.target;
56113         }
56114         if (dom.cursor) {
56115             dom.cursor = scrubbedAttrs.cursor;
56116         }
56117
56118         // Change visibility
56119         if (sprite.dirtyHidden) {
56120             (scrubbedAttrs.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite);
56121             sprite.dirtyHidden = false;
56122         }
56123
56124         // Update path
56125         if (sprite.dirtyPath) {
56126             if (sprite.type == "circle" || sprite.type == "ellipse") {
56127                 var cx = scrubbedAttrs.x,
56128                     cy = scrubbedAttrs.y,
56129                     rx = scrubbedAttrs.rx || scrubbedAttrs.r || 0,
56130                     ry = scrubbedAttrs.ry || scrubbedAttrs.r || 0;
56131                 dom.path = Ext.String.format("ar{0},{1},{2},{3},{4},{1},{4},{1}",
56132                             Math.round((cx - rx) * me.zoom),
56133                             Math.round((cy - ry) * me.zoom),
56134                             Math.round((cx + rx) * me.zoom),
56135                             Math.round((cy + ry) * me.zoom),
56136                             Math.round(cx * me.zoom));
56137                 sprite.dirtyPath = false;
56138             }
56139             else if (sprite.type !== "text" && sprite.type !== 'image') {
56140                 sprite.attr.path = scrubbedAttrs.path = me.setPaths(sprite, scrubbedAttrs) || scrubbedAttrs.path;
56141                 dom.path = me.path2vml(scrubbedAttrs.path);
56142                 sprite.dirtyPath = false;
56143             }
56144         }
56145
56146         // Apply clipping
56147         if ("clip-rect" in scrubbedAttrs) {
56148             me.setClip(sprite, scrubbedAttrs);
56149         }
56150
56151         // Handle text (special handling required)
56152         if (sprite.type == "text") {
56153             me.setTextAttributes(sprite, scrubbedAttrs);
56154         }
56155
56156         // Handle fill and opacity
56157         if (scrubbedAttrs.opacity  || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) {
56158             me.setFill(sprite, scrubbedAttrs);
56159         }
56160
56161         // Handle stroke (all fills require a stroke element)
56162         if (scrubbedAttrs.stroke || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) {
56163             me.setStroke(sprite, scrubbedAttrs);
56164         }
56165         
56166         //set styles
56167         style = spriteAttr.style;
56168         if (style) {
56169             el.setStyle(style);
56170         }
56171
56172         sprite.dirty = false;
56173     },
56174
56175     setZIndex: function(sprite) {
56176         if (sprite.el) {
56177             if (sprite.attr.zIndex != undefined) {
56178                 sprite.el.setStyle('zIndex', sprite.attr.zIndex);
56179             }
56180             sprite.zIndexDirty = false;
56181         }
56182     },
56183
56184     // Normalize all virtualized types into paths.
56185     setPaths: function(sprite, params) {
56186         var spriteAttr = sprite.attr;
56187         // Clear bbox cache
56188         sprite.bbox.plain = null;
56189         sprite.bbox.transform = null;
56190         if (sprite.type == 'circle') {
56191             spriteAttr.rx = spriteAttr.ry = params.r;
56192             return Ext.draw.Draw.ellipsePath(sprite);
56193         }
56194         else if (sprite.type == 'ellipse') {
56195             spriteAttr.rx = params.rx;
56196             spriteAttr.ry = params.ry;
56197             return Ext.draw.Draw.ellipsePath(sprite);
56198         }
56199         else if (sprite.type == 'rect') {
56200             spriteAttr.rx = spriteAttr.ry = params.r;
56201             return Ext.draw.Draw.rectPath(sprite);
56202         }
56203         else if (sprite.type == 'path' && spriteAttr.path) {
56204             return Ext.draw.Draw.pathToAbsolute(spriteAttr.path);
56205         }
56206         return false;
56207     },
56208
56209     setFill: function(sprite, params) {
56210         var me = this,
56211             el = sprite.el.dom,
56212             fillEl = el.fill,
56213             newfill = false,
56214             opacity, gradient, fillUrl, rotation, angle;
56215
56216         if (!fillEl) {
56217             // NOT an expando (but it sure looks like one)...
56218             fillEl = el.fill = me.createNode("fill");
56219             newfill = true;
56220         }
56221         if (Ext.isArray(params.fill)) {
56222             params.fill = params.fill[0];
56223         }
56224         if (params.fill == "none") {
56225             fillEl.on = false;
56226         }
56227         else {
56228             if (typeof params.opacity == "number") {
56229                 fillEl.opacity = params.opacity;
56230             }
56231             if (typeof params["fill-opacity"] == "number") {
56232                 fillEl.opacity = params["fill-opacity"];
56233             }
56234             fillEl.on = true;
56235             if (typeof params.fill == "string") {
56236                 fillUrl = params.fill.match(me.fillUrlRe);
56237                 if (fillUrl) {
56238                     fillUrl = fillUrl[1];
56239                     // If the URL matches one of the registered gradients, render that gradient
56240                     if (fillUrl.charAt(0) == "#") {
56241                         gradient = me.gradientsColl.getByKey(fillUrl.substring(1));
56242                     }
56243                     if (gradient) {
56244                         // VML angle is offset and inverted from standard, and must be adjusted to match rotation transform
56245                         rotation = params.rotation;
56246                         angle = -(gradient.angle + 270 + (rotation ? rotation.degrees : 0)) % 360;
56247                         // IE will flip the angle at 0 degrees...
56248                         if (angle === 0) {
56249                             angle = 180;
56250                         }
56251                         fillEl.angle = angle;
56252                         fillEl.type = "gradient";
56253                         fillEl.method = "sigma";
56254                         fillEl.colors.value = gradient.colors;
56255                     }
56256                     // Otherwise treat it as an image
56257                     else {
56258                         fillEl.src = fillUrl;
56259                         fillEl.type = "tile";
56260                     }
56261                 }
56262                 else {
56263                     fillEl.color = Ext.draw.Color.toHex(params.fill);
56264                     fillEl.src = "";
56265                     fillEl.type = "solid";
56266                 }
56267             }
56268         }
56269         if (newfill) {
56270             el.appendChild(fillEl);
56271         }
56272     },
56273
56274     setStroke: function(sprite, params) {
56275         var me = this,
56276             el = sprite.el.dom,
56277             strokeEl = sprite.strokeEl,
56278             newStroke = false,
56279             width, opacity;
56280
56281         if (!strokeEl) {
56282             strokeEl = sprite.strokeEl = me.createNode("stroke");
56283             newStroke = true;
56284         }
56285         if (Ext.isArray(params.stroke)) {
56286             params.stroke = params.stroke[0];
56287         }
56288         if (!params.stroke || params.stroke == "none" || params.stroke == 0 || params["stroke-width"] == 0) {
56289             strokeEl.on = false;
56290         }
56291         else {
56292             strokeEl.on = true;
56293             if (params.stroke && !params.stroke.match(me.fillUrlRe)) {
56294                 // VML does NOT support a gradient stroke :(
56295                 strokeEl.color = Ext.draw.Color.toHex(params.stroke);
56296             }
56297             strokeEl.joinstyle = params["stroke-linejoin"];
56298             strokeEl.endcap = params["stroke-linecap"] || "round";
56299             strokeEl.miterlimit = params["stroke-miterlimit"] || 8;
56300             width = parseFloat(params["stroke-width"] || 1) * 0.75;
56301             opacity = params["stroke-opacity"] || 1;
56302             // VML Does not support stroke widths under 1, so we're going to fiddle with stroke-opacity instead.
56303             if (Ext.isNumber(width) && width < 1) {
56304                 strokeEl.weight = 1;
56305                 strokeEl.opacity = opacity * width;
56306             }
56307             else {
56308                 strokeEl.weight = width;
56309                 strokeEl.opacity = opacity;
56310             }
56311         }
56312         if (newStroke) {
56313             el.appendChild(strokeEl);
56314         }
56315     },
56316
56317     setClip: function(sprite, params) {
56318         var me = this,
56319             el = sprite.el,
56320             clipEl = sprite.clipEl,
56321             rect = String(params["clip-rect"]).split(me.separatorRe);
56322         if (!clipEl) {
56323             clipEl = sprite.clipEl = me.el.insertFirst(Ext.getDoc().dom.createElement("div"));
56324             clipEl.addCls(Ext.baseCSSPrefix + 'vml-sprite');
56325         }
56326         if (rect.length == 4) {
56327             rect[2] = +rect[2] + (+rect[0]);
56328             rect[3] = +rect[3] + (+rect[1]);
56329             clipEl.setStyle("clip", Ext.String.format("rect({1}px {2}px {3}px {0}px)", rect[0], rect[1], rect[2], rect[3]));
56330             clipEl.setSize(me.el.width, me.el.height);
56331         }
56332         else {
56333             clipEl.setStyle("clip", "");
56334         }
56335     },
56336
56337     setTextAttributes: function(sprite, params) {
56338         var me = this,
56339             vml = sprite.vml,
56340             textStyle = vml.textpath.style,
56341             spanCacheStyle = me.span.style,
56342             zoom = me.zoom,
56343             round = Math.round,
56344             fontObj = {
56345                 fontSize: "font-size",
56346                 fontWeight: "font-weight",
56347                 fontStyle: "font-style"
56348             },
56349             fontProp,
56350             paramProp;
56351         if (sprite.dirtyFont) {
56352             if (params.font) {
56353                 textStyle.font = spanCacheStyle.font = params.font;
56354             }
56355             if (params["font-family"]) {
56356                 textStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(me.fontFamilyRe, "") + '"';
56357                 spanCacheStyle.fontFamily = params["font-family"];
56358             }
56359
56360             for (fontProp in fontObj) {
56361                 paramProp = params[fontObj[fontProp]];
56362                 if (paramProp) {
56363                     textStyle[fontProp] = spanCacheStyle[fontProp] = paramProp;
56364                 }
56365             }
56366
56367             me.setText(sprite, params.text);
56368             
56369             if (vml.textpath.string) {
56370                 me.span.innerHTML = String(vml.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>");
56371             }
56372             vml.W = me.span.offsetWidth;
56373             vml.H = me.span.offsetHeight + 2; 
56374
56375             
56376             if (params["text-anchor"] == "middle") {
56377                 textStyle["v-text-align"] = "center";
56378             }
56379             else if (params["text-anchor"] == "end") {
56380                 textStyle["v-text-align"] = "right";
56381                 vml.bbx = -Math.round(vml.W / 2);
56382             }
56383             else {
56384                 textStyle["v-text-align"] = "left";
56385                 vml.bbx = Math.round(vml.W / 2);
56386             }
56387         }
56388         vml.X = params.x;
56389         vml.Y = params.y;
56390         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);
56391         
56392         sprite.bbox.plain = null;
56393         sprite.bbox.transform = null;
56394         sprite.dirtyFont = false;
56395     },
56396     
56397     setText: function(sprite, text) {
56398         sprite.vml.textpath.string = Ext.htmlDecode(text);
56399     },
56400
56401     hide: function() {
56402         this.el.hide();
56403     },
56404
56405     show: function() {
56406         this.el.show();
56407     },
56408
56409     hidePrim: function(sprite) {
56410         sprite.el.addCls(Ext.baseCSSPrefix + 'hide-visibility');
56411     },
56412
56413     showPrim: function(sprite) {
56414         sprite.el.removeCls(Ext.baseCSSPrefix + 'hide-visibility');
56415     },
56416
56417     setSize: function(width, height) {
56418         var me = this,
56419             viewBox = me.viewBox,
56420             scaleX, scaleY, items, i, len;
56421         width = width || me.width;
56422         height = height || me.height;
56423         me.width = width;
56424         me.height = height;
56425
56426         if (!me.el) {
56427             return;
56428         }
56429
56430         
56431         if (width != undefined) {
56432             me.el.setWidth(width);
56433         }
56434         if (height != undefined) {
56435             me.el.setHeight(height);
56436         }
56437
56438         
56439         if (viewBox && (width || height)) {
56440             var viewBoxX = viewBox.x,
56441                 viewBoxY = viewBox.y,
56442                 viewBoxWidth = viewBox.width,
56443                 viewBoxHeight = viewBox.height,
56444                 relativeHeight = height / viewBoxHeight,
56445                 relativeWidth = width / viewBoxWidth,
56446                 size;
56447             if (viewBoxWidth * relativeHeight < width) {
56448                 viewBoxX -= (width - viewBoxWidth * relativeHeight) / 2 / relativeHeight;
56449             }
56450             if (viewBoxHeight * relativeWidth < height) {
56451                 viewBoxY -= (height - viewBoxHeight * relativeWidth) / 2 / relativeWidth;
56452             }
56453             size = 1 / Math.max(viewBoxWidth / width, viewBoxHeight / height);
56454             
56455             me.viewBoxShift = {
56456                 dx: -viewBoxX,
56457                 dy: -viewBoxY,
56458                 scale: size
56459             };
56460             items = me.items.items;
56461             for (i = 0, len = items.length; i < len; i++) {
56462                 me.transform(items[i]);
56463             }
56464         }
56465         this.callParent(arguments);
56466     },
56467
56468     setViewBox: function(x, y, width, height) {
56469         this.callParent(arguments);
56470         this.viewBox = {
56471             x: x,
56472             y: y,
56473             width: width,
56474             height: height
56475         };
56476     },
56477
56478     onAdd: function(item) {
56479         this.callParent(arguments);
56480         if (this.el) {
56481             this.renderItem(item);
56482         }
56483     },
56484
56485     onRemove: function(sprite) {
56486         if (sprite.el) {
56487             sprite.el.remove();
56488             delete sprite.el;
56489         }
56490         this.callParent(arguments);
56491     },
56492
56493     render: function (container) {
56494         var me = this,
56495             doc = Ext.getDoc().dom;
56496         
56497         if (!me.createNode) {
56498             try {
56499                 if (!doc.namespaces.rvml) {
56500                     doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
56501                 }
56502                 me.createNode = function (tagName) {
56503                     return doc.createElement("<rvml:" + tagName + ' class="rvml">');
56504                 };
56505             } catch (e) {
56506                 me.createNode = function (tagName) {
56507                     return doc.createElement("<" + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
56508                 };
56509             }
56510         }
56511
56512         if (!me.el) {
56513             var el = doc.createElement("div");
56514             me.el = Ext.get(el);
56515             me.el.addCls(me.baseVmlCls);
56516
56517             
56518             me.span = doc.createElement("span");
56519             Ext.get(me.span).addCls(me.measureSpanCls);
56520             el.appendChild(me.span);
56521             me.el.setSize(me.width || 10, me.height || 10);
56522             container.appendChild(el);
56523             me.el.on({
56524                 scope: me,
56525                 mouseup: me.onMouseUp,
56526                 mousedown: me.onMouseDown,
56527                 mouseover: me.onMouseOver,
56528                 mouseout: me.onMouseOut,
56529                 mousemove: me.onMouseMove,
56530                 mouseenter: me.onMouseEnter,
56531                 mouseleave: me.onMouseLeave,
56532                 click: me.onClick
56533             });
56534         }
56535         me.renderAll();
56536     },
56537
56538     renderAll: function() {
56539         this.items.each(this.renderItem, this);
56540     },
56541
56542     redraw: function(sprite) {
56543         sprite.dirty = true;
56544         this.renderItem(sprite);
56545     },
56546
56547     renderItem: function (sprite) {
56548         
56549         if (!this.el) {
56550             return;
56551         }
56552
56553         
56554         if (!sprite.el) {
56555             this.createSpriteElement(sprite);
56556         }
56557
56558         if (sprite.dirty) {
56559             this.applyAttrs(sprite);
56560             if (sprite.dirtyTransform) {
56561                 this.applyTransformations(sprite);
56562             }
56563         }
56564     },
56565
56566     rotationCompensation: function (deg, dx, dy) {
56567         var matrix = Ext.create('Ext.draw.Matrix');
56568         matrix.rotate(-deg, 0.5, 0.5);
56569         return {
56570             x: matrix.x(dx, dy),
56571             y: matrix.y(dx, dy)
56572         };
56573     },
56574
56575     transform: function(sprite) {
56576         var me = this,
56577             matrix = Ext.create('Ext.draw.Matrix'),
56578             transforms = sprite.transformations,
56579             transformsLength = transforms.length,
56580             i = 0,
56581             deltaDegrees = 0,
56582             deltaScaleX = 1,
56583             deltaScaleY = 1,
56584             flip = "",
56585             el = sprite.el,
56586             dom = el.dom,
56587             domStyle = dom.style,
56588             zoom = me.zoom,
56589             skew = sprite.skew,
56590             deltaX, deltaY, transform, type, compensate, y, fill, newAngle,zoomScaleX, zoomScaleY, newOrigin;
56591
56592         for (; i < transformsLength; i++) {
56593             transform = transforms[i];
56594             type = transform.type;
56595             if (type == "translate") {
56596                 matrix.translate(transform.x, transform.y);
56597             }
56598             else if (type == "rotate") {
56599                 matrix.rotate(transform.degrees, transform.x, transform.y);
56600                 deltaDegrees += transform.degrees;
56601             }
56602             else if (type == "scale") {
56603                 matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY);
56604                 deltaScaleX *= transform.x;
56605                 deltaScaleY *= transform.y;
56606             }
56607         }
56608
56609         if (me.viewBoxShift) {
56610             matrix.scale(me.viewBoxShift.scale, me.viewBoxShift.scale, -1, -1);
56611             matrix.add(1, 0, 0, 1, me.viewBoxShift.dx, me.viewBoxShift.dy);
56612         }
56613
56614         sprite.matrix = matrix;
56615
56616
56617         
56618
56619         if (sprite.type != "image" && skew) {
56620             
56621             skew.matrix = matrix.toString();
56622             skew.offset = matrix.offset();
56623         }
56624         else {
56625             deltaX = matrix.matrix[0][2];
56626             deltaY = matrix.matrix[1][2];
56627             
56628             zoomScaleX = zoom / deltaScaleX;
56629             zoomScaleY = zoom / deltaScaleY;
56630
56631             dom.coordsize = Math.abs(zoomScaleX) + " " + Math.abs(zoomScaleY);
56632
56633             
56634             newAngle = deltaDegrees * (deltaScaleX * ((deltaScaleY < 0) ? -1 : 1));
56635             if (newAngle != domStyle.rotation && !(newAngle === 0 && !domStyle.rotation)) {
56636                 domStyle.rotation = newAngle;
56637             }
56638             if (deltaDegrees) {
56639                 
56640                 compensate = me.rotationCompensation(deltaDegrees, deltaX, deltaY);
56641                 deltaX = compensate.x;
56642                 deltaY = compensate.y;
56643             }
56644
56645             
56646             if (deltaScaleX < 0) {
56647                 flip += "x";
56648             }
56649             if (deltaScaleY < 0) {
56650                 flip += " y";
56651                 y = -1;
56652             }
56653             if (flip != "" && !dom.style.flip) {
56654                 domStyle.flip = flip;
56655             }
56656
56657             
56658             newOrigin = (deltaX * -zoomScaleX) + " " + (deltaY * -zoomScaleY);
56659             if (newOrigin != dom.coordorigin) {
56660                 dom.coordorigin = (deltaX * -zoomScaleX) + " " + (deltaY * -zoomScaleY);
56661             }
56662         }
56663     },
56664
56665     createItem: function (config) {
56666         return Ext.create('Ext.draw.Sprite', config);
56667     },
56668
56669     getRegion: function() {
56670         return this.el.getRegion();
56671     },
56672
56673     addCls: function(sprite, className) {
56674         if (sprite && sprite.el) {
56675             sprite.el.addCls(className);
56676         }
56677     },
56678
56679     removeCls: function(sprite, className) {
56680         if (sprite && sprite.el) {
56681             sprite.el.removeCls(className);
56682         }
56683     },
56684
56685     
56686     addGradient: function(gradient) {
56687         var gradients = this.gradientsColl || (this.gradientsColl = Ext.create('Ext.util.MixedCollection')),
56688             colors = [],
56689             stops = Ext.create('Ext.util.MixedCollection');
56690
56691         
56692         stops.addAll(gradient.stops);
56693         stops.sortByKey("ASC", function(a, b) {
56694             a = parseInt(a, 10);
56695             b = parseInt(b, 10);
56696             return a > b ? 1 : (a < b ? -1 : 0);
56697         });
56698         stops.eachKey(function(k, v) {
56699             colors.push(k + "% " + v.color);
56700         });
56701
56702         gradients.add(gradient.id, {
56703             colors: colors.join(","),
56704             angle: gradient.angle
56705         });
56706     },
56707
56708     destroy: function() {
56709         var me = this;
56710         
56711         me.callParent(arguments);
56712         if (me.el) {
56713             me.el.remove();
56714         }
56715         delete me.el;
56716     }
56717 });
56718
56719
56720 Ext.define('Ext.fx.target.ElementCSS', {
56721
56722     
56723
56724     extend: 'Ext.fx.target.Element',
56725
56726     
56727
56728     setAttr: function(targetData, isFirstFrame) {
56729         var cssArr = {
56730                 attrs: [],
56731                 duration: [],
56732                 easing: []
56733             },
56734             ln = targetData.length,
56735             attributes,
56736             attrs,
56737             attr,
56738             easing,
56739             duration,
56740             o,
56741             i,
56742             j,
56743             ln2;
56744         for (i = 0; i < ln; i++) {
56745             attrs = targetData[i];
56746             duration = attrs.duration;
56747             easing = attrs.easing;
56748             attrs = attrs.attrs;
56749             for (attr in attrs) {
56750                 if (Ext.Array.indexOf(cssArr.attrs, attr) == -1) {
56751                     cssArr.attrs.push(attr.replace(/[A-Z]/g, function(v) {
56752                         return '-' + v.toLowerCase();
56753                     }));
56754                     cssArr.duration.push(duration + 'ms');
56755                     cssArr.easing.push(easing);
56756                 }
56757             }
56758         }
56759         attributes = cssArr.attrs.join(',');
56760         duration = cssArr.duration.join(',');
56761         easing = cssArr.easing.join(', ');
56762         for (i = 0; i < ln; i++) {
56763             attrs = targetData[i].attrs;
56764             for (attr in attrs) {
56765                 ln2 = attrs[attr].length;
56766                 for (j = 0; j < ln2; j++) {
56767                     o = attrs[attr][j];
56768                     o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', isFirstFrame ? '' : attributes);
56769                     o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', isFirstFrame ? '' : duration);
56770                     o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', isFirstFrame ? '' : easing);
56771                     o[0].setStyle(attr, o[1]);
56772
56773                     
56774                     if (isFirstFrame) {
56775                         o = o[0].dom.offsetWidth;
56776                     }
56777                     else {
56778                         
56779                         o[0].on(Ext.supports.CSS3TransitionEnd, function() {
56780                             this.setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', null);
56781                             this.setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', null);
56782                             this.setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', null);
56783                         }, o[0], { single: true });
56784                     }
56785                 }
56786             }
56787         }
56788     }
56789 });
56790
56791 Ext.define('Ext.fx.target.CompositeElementCSS', {
56792
56793     
56794
56795     extend: 'Ext.fx.target.CompositeElement',
56796
56797     requires: ['Ext.fx.target.ElementCSS'],
56798
56799     
56800     setAttr: function() {
56801         return Ext.fx.target.ElementCSS.prototype.setAttr.apply(this, arguments);
56802     }
56803 });
56804
56805 Ext.define('Ext.layout.container.AbstractFit', {
56806
56807     
56808
56809     extend: 'Ext.layout.container.Container',
56810
56811     
56812
56813     itemCls: Ext.baseCSSPrefix + 'fit-item',
56814     targetCls: Ext.baseCSSPrefix + 'layout-fit',
56815     type: 'fit'
56816 });
56817
56818 Ext.define('Ext.layout.container.Fit', {
56819
56820     
56821
56822     extend: 'Ext.layout.container.AbstractFit',
56823     alias: 'layout.fit',
56824     alternateClassName: 'Ext.layout.FitLayout',
56825
56826     
56827    
56828     
56829     onLayout : function() {
56830         var me = this;
56831         me.callParent();
56832
56833         if (me.owner.items.length) {
56834             me.setItemBox(me.owner.items.get(0), me.getLayoutTargetSize());
56835         }
56836     },
56837
56838     getTargetBox : function() {
56839         return this.getLayoutTargetSize();
56840     },
56841
56842     setItemBox : function(item, box) {
56843         var me = this;
56844         if (item && box.height > 0) {
56845             if (me.isManaged('width') === true) {
56846                box.width = undefined;
56847             }
56848             if (me.isManaged('height') === true) {
56849                box.height = undefined;
56850             }
56851             me.setItemSize(item, box.width, box.height);
56852         }
56853     }
56854 });
56855
56856
56857 Ext.define('Ext.layout.container.AbstractCard', {
56858
56859     
56860
56861     extend: 'Ext.layout.container.Fit',
56862
56863     
56864
56865     type: 'card',
56866
56867     sizeAllCards: false,
56868
56869     hideInactive: true,
56870
56871     
56872     deferredRender : false,
56873
56874     beforeLayout: function() {
56875         var me = this;
56876         me.activeItem = me.getActiveItem();
56877         if (me.activeItem && me.deferredRender) {
56878             me.renderItems([me.activeItem], me.getRenderTarget());
56879             return true;
56880         }
56881         else {
56882             return this.callParent(arguments);
56883         }
56884     },
56885
56886     onLayout: function() {
56887         var me = this,
56888             activeItem = me.activeItem,
56889             items = me.getVisibleItems(),
56890             ln = items.length,
56891             targetBox = me.getTargetBox(),
56892             i, item;
56893
56894         for (i = 0; i < ln; i++) {
56895             item = items[i];
56896             me.setItemBox(item, targetBox);
56897         }
56898
56899         if (!me.firstActivated && activeItem) {
56900             if (activeItem.fireEvent('beforeactivate', activeItem) !== false) {
56901                 activeItem.fireEvent('activate', activeItem);
56902             }
56903             me.firstActivated = true;
56904         }
56905     },
56906
56907     isValidParent : function(item, target, position) {
56908         
56909         
56910         var itemEl = item.el ? item.el.dom : Ext.getDom(item);
56911         return (itemEl && itemEl.parentNode === (target.dom || target)) || false;
56912     },
56913
56914     
56915     getActiveItem: function() {
56916         var me = this;
56917         if (!me.activeItem && me.owner) {
56918             me.activeItem = me.parseActiveItem(me.owner.activeItem);
56919         }
56920
56921         if (me.activeItem && me.owner.items.indexOf(me.activeItem) != -1) {
56922             return me.activeItem;
56923         }
56924
56925         return null;
56926     },
56927
56928     
56929     parseActiveItem: function(item) {
56930         if (item && item.isComponent) {
56931             return item;
56932         }
56933         else if (typeof item == 'number' || item === undefined) {
56934             return this.getLayoutItems()[item || 0];
56935         }
56936         else {
56937             return this.owner.getComponent(item);
56938         }
56939     },
56940
56941     
56942     configureItem: function(item, position) {
56943         this.callParent([item, position]);
56944         if (this.hideInactive && this.activeItem !== item) {
56945             item.hide();
56946         }
56947         else {
56948             item.show();
56949         }
56950     },
56951
56952     onRemove: function(component) {
56953         if (component === this.activeItem) {
56954             this.activeItem = null;
56955             if (this.owner.items.getCount() === 0) {
56956                 this.firstActivated = false;
56957             }
56958         }
56959     },
56960
56961     
56962     getAnimation: function(newCard, owner) {
56963         var newAnim = (newCard || {}).cardSwitchAnimation;
56964         if (newAnim === false) {
56965             return false;
56966         }
56967         return newAnim || owner.cardSwitchAnimation;
56968     },
56969
56970     
56971     getNext: function(wrap) {
56972         
56973         
56974         
56975         var items = this.getLayoutItems(),
56976             index = Ext.Array.indexOf(items, this.activeItem);
56977         return items[index + 1] || (wrap ? items[0] : false);
56978     },
56979
56980     
56981     next: function(anim, wrap) {
56982         
56983         
56984         
56985         return this.setActiveItem(this.getNext(wrap), anim);
56986     },
56987
56988     
56989     getPrev: function(wrap) {
56990         
56991         
56992         
56993         var items = this.getLayoutItems(),
56994             index = Ext.Array.indexOf(items, this.activeItem);
56995         return items[index - 1] || (wrap ? items[items.length - 1] : false);
56996     },
56997
56998     
56999     prev: function(anim, wrap) {
57000         
57001         
57002         
57003         return this.setActiveItem(this.getPrev(wrap), anim);
57004     }
57005 });
57006
57007
57008 Ext.define('Ext.selection.Model', {
57009     extend: 'Ext.util.Observable',
57010     alternateClassName: 'Ext.AbstractStoreSelectionModel',
57011     requires: ['Ext.data.StoreManager'],
57012     
57013
57014     
57015     
57016     
57017     allowDeselect: false,
57018
57019     
57020     selected: null,
57021     
57022     
57023     
57024     pruneRemoved: true,
57025
57026     constructor: function(cfg) {
57027         var me = this;
57028         
57029         cfg = cfg || {};
57030         Ext.apply(me, cfg);
57031         
57032         me.addEvents(
57033             
57034              'selectionchange'
57035         );
57036
57037         me.modes = {
57038             SINGLE: true,
57039             SIMPLE: true,
57040             MULTI: true
57041         };
57042
57043         
57044         me.setSelectionMode(cfg.mode || me.mode);
57045
57046         
57047         me.selected = Ext.create('Ext.util.MixedCollection');
57048         
57049         me.callParent(arguments);
57050     },
57051
57052     
57053     bind : function(store, initial){
57054         var me = this;
57055         
57056         if(!initial && me.store){
57057             if(store !== me.store && me.store.autoDestroy){
57058                 me.store.destroy();
57059             }else{
57060                 me.store.un("add", me.onStoreAdd, me);
57061                 me.store.un("clear", me.onStoreClear, me);
57062                 me.store.un("remove", me.onStoreRemove, me);
57063                 me.store.un("update", me.onStoreUpdate, me);
57064             }
57065         }
57066         if(store){
57067             store = Ext.data.StoreManager.lookup(store);
57068             store.on({
57069                 add: me.onStoreAdd,
57070                 clear: me.onStoreClear,
57071                 remove: me.onStoreRemove,
57072                 update: me.onStoreUpdate,
57073                 scope: me
57074             });
57075         }
57076         me.store = store;
57077         if(store && !initial) {
57078             me.refresh();
57079         }
57080     },
57081
57082     
57083     selectAll: function(suppressEvent) {
57084         var me = this,
57085             selections = me.store.getRange(),
57086             i = 0,
57087             len = selections.length,
57088             start = me.getSelection().length;
57089             
57090         me.bulkChange = true;
57091         for (; i < len; i++) {
57092             me.doSelect(selections[i], true, suppressEvent);
57093         }
57094         delete me.bulkChange;
57095         
57096         me.maybeFireSelectionChange(me.getSelection().length !== start);
57097     },
57098
57099     
57100     deselectAll: function(suppressEvent) {
57101         var me = this,
57102             selections = me.getSelection(),
57103             i = 0,
57104             len = selections.length,
57105             start = me.getSelection().length;
57106             
57107         me.bulkChange = true;
57108         for (; i < len; i++) {
57109             me.doDeselect(selections[i], suppressEvent);
57110         }
57111         delete me.bulkChange;
57112         
57113         me.maybeFireSelectionChange(me.getSelection().length !== start);
57114     },
57115
57116     
57117     
57118     
57119     selectWithEvent: function(record, e) {
57120         var me = this;
57121         
57122         switch (me.selectionMode) {
57123             case 'MULTI':
57124                 if (e.ctrlKey && me.isSelected(record)) {
57125                     me.doDeselect(record, false);
57126                 } else if (e.shiftKey && me.lastFocused) {
57127                     me.selectRange(me.lastFocused, record, e.ctrlKey);
57128                 } else if (e.ctrlKey) {
57129                     me.doSelect(record, true, false);
57130                 } else if (me.isSelected(record) && !e.shiftKey && !e.ctrlKey && me.selected.getCount() > 1) {
57131                     me.doSelect(record, false, false);
57132                 } else {
57133                     me.doSelect(record, false);
57134                 }
57135                 break;
57136             case 'SIMPLE':
57137                 if (me.isSelected(record)) {
57138                     me.doDeselect(record);
57139                 } else {
57140                     me.doSelect(record, true);
57141                 }
57142                 break;
57143             case 'SINGLE':
57144                 
57145                 if (me.allowDeselect && me.isSelected(record)) {
57146                     me.doDeselect(record);
57147                 
57148                 } else {
57149                     me.doSelect(record, false);
57150                 }
57151                 break;
57152         }
57153     },
57154
57155     
57156     selectRange : function(startRow, endRow, keepExisting, dir){
57157         var me = this,
57158             store = me.store,
57159             selectedCount = 0,
57160             i,
57161             tmp,
57162             dontDeselect,
57163             records = [];
57164         
57165         if (me.isLocked()){
57166             return;
57167         }
57168         
57169         if (!keepExisting) {
57170             me.clearSelections();
57171         }
57172         
57173         if (!Ext.isNumber(startRow)) {
57174             startRow = store.indexOf(startRow);
57175         } 
57176         if (!Ext.isNumber(endRow)) {
57177             endRow = store.indexOf(endRow);
57178         }
57179         
57180         
57181         if (startRow > endRow){
57182             tmp = endRow;
57183             endRow = startRow;
57184             startRow = tmp;
57185         }
57186
57187         for (i = startRow; i <= endRow; i++) {
57188             if (me.isSelected(store.getAt(i))) {
57189                 selectedCount++;
57190             }
57191         }
57192
57193         if (!dir) {
57194             dontDeselect = -1;
57195         } else {
57196             dontDeselect = (dir == 'up') ? startRow : endRow;
57197         }
57198         
57199         for (i = startRow; i <= endRow; i++){
57200             if (selectedCount == (endRow - startRow + 1)) {
57201                 if (i != dontDeselect) {
57202                     me.doDeselect(i, true);
57203                 }
57204             } else {
57205                 records.push(store.getAt(i));
57206             }
57207         }
57208         me.doMultiSelect(records, true);
57209     },
57210     
57211     
57212     select: function(records, keepExisting, suppressEvent) {
57213         this.doSelect(records, keepExisting, suppressEvent);
57214     },
57215
57216     
57217     deselect: function(records, suppressEvent) {
57218         this.doDeselect(records, suppressEvent);
57219     },
57220     
57221     doSelect: function(records, keepExisting, suppressEvent) {
57222         var me = this,
57223             record;
57224             
57225         if (me.locked) {
57226             return;
57227         }
57228         if (typeof records === "number") {
57229             records = [me.store.getAt(records)];
57230         }
57231         if (me.selectionMode == "SINGLE" && records) {
57232             record = records.length ? records[0] : records;
57233             me.doSingleSelect(record, suppressEvent);
57234         } else {
57235             me.doMultiSelect(records, keepExisting, suppressEvent);
57236         }
57237     },
57238
57239     doMultiSelect: function(records, keepExisting, suppressEvent) {
57240         var me = this,
57241             selected = me.selected,
57242             change = false,
57243             i = 0,
57244             len, record;
57245             
57246         if (me.locked) {
57247             return;
57248         }
57249         
57250
57251         records = !Ext.isArray(records) ? [records] : records;
57252         len = records.length;
57253         if (!keepExisting && selected.getCount() > 0) {
57254             change = true;
57255             me.doDeselect(me.getSelection(), suppressEvent);
57256         }
57257
57258         for (; i < len; i++) {
57259             record = records[i];
57260             if (keepExisting && me.isSelected(record)) {
57261                 continue;
57262             }
57263             change = true;
57264             me.lastSelected = record;
57265             selected.add(record);
57266
57267             me.onSelectChange(record, true, suppressEvent);
57268         }
57269         me.setLastFocused(record, suppressEvent);
57270         
57271         me.maybeFireSelectionChange(change && !suppressEvent);
57272     },
57273
57274     
57275     doDeselect: function(records, suppressEvent) {
57276         var me = this,
57277             selected = me.selected,
57278             change = false,
57279             i = 0,
57280             len, record;
57281             
57282         if (me.locked) {
57283             return;
57284         }
57285
57286         if (typeof records === "number") {
57287             records = [me.store.getAt(records)];
57288         }
57289
57290         records = !Ext.isArray(records) ? [records] : records;
57291         len = records.length;
57292         for (; i < len; i++) {
57293             record = records[i];
57294             if (selected.remove(record)) {
57295                 if (me.lastSelected == record) {
57296                     me.lastSelected = selected.last();
57297                 }
57298                 me.onSelectChange(record, false, suppressEvent);
57299                 change = true;
57300             }
57301         }
57302         
57303         me.maybeFireSelectionChange(change && !suppressEvent);
57304     },
57305
57306     doSingleSelect: function(record, suppressEvent) {
57307         var me = this,
57308             selected = me.selected;
57309             
57310         if (me.locked) {
57311             return;
57312         }
57313         
57314         
57315         if (me.isSelected(record)) {
57316             return;
57317         }
57318         if (selected.getCount() > 0) {
57319             me.doDeselect(me.lastSelected, suppressEvent);
57320         }
57321         selected.add(record);
57322         me.lastSelected = record;
57323         me.onSelectChange(record, true, suppressEvent);
57324         if (!suppressEvent) {
57325             me.setLastFocused(record);
57326         }
57327         me.maybeFireSelectionChange(!suppressEvent);
57328     },
57329
57330     
57331     setLastFocused: function(record, supressFocus) {
57332         var me = this,
57333             recordBeforeLast = me.lastFocused;
57334         me.lastFocused = record;
57335         me.onLastFocusChanged(recordBeforeLast, record, supressFocus);
57336     },
57337     
57338     
57339     isFocused: function(record) {
57340         return record === this.getLastFocused();
57341     },
57342
57343
57344     
57345     
57346     maybeFireSelectionChange: function(fireEvent) {
57347         var me = this;
57348         if (fireEvent && !me.bulkChange) {
57349             me.fireEvent('selectionchange', me, me.getSelection());
57350         }
57351     },
57352
57353     
57354     getLastSelected: function() {
57355         return this.lastSelected;
57356     },
57357     
57358     getLastFocused: function() {
57359         return this.lastFocused;
57360     },
57361
57362     
57363     getSelection: function() {
57364         return this.selected.getRange();
57365     },
57366
57367     
57368     getSelectionMode: function() {
57369         return this.selectionMode;
57370     },
57371
57372     
57373     setSelectionMode: function(selMode) {
57374         selMode = selMode ? selMode.toUpperCase() : 'SINGLE';
57375         
57376         
57377         this.selectionMode = this.modes[selMode] ? selMode : 'SINGLE';
57378     },
57379
57380     
57381     isLocked: function() {
57382         return this.locked;
57383     },
57384
57385     
57386     setLocked: function(locked) {
57387         this.locked = !!locked;
57388     },
57389
57390     
57391     isSelected: function(record) {
57392         record = Ext.isNumber(record) ? this.store.getAt(record) : record;
57393         return this.selected.indexOf(record) !== -1;
57394     },
57395     
57396     
57397     hasSelection: function() {
57398         return this.selected.getCount() > 0;
57399     },
57400
57401     refresh: function() {
57402         var me = this,
57403             toBeSelected = [],
57404             oldSelections = me.getSelection(),
57405             len = oldSelections.length,
57406             selection,
57407             change,
57408             i = 0,
57409             lastFocused = this.getLastFocused();
57410
57411         
57412         
57413         
57414         for (; i < len; i++) {
57415             selection = oldSelections[i];
57416             if (!this.pruneRemoved || me.store.indexOf(selection) !== -1) {
57417                 toBeSelected.push(selection);
57418             }
57419         }
57420
57421         
57422         
57423         if (me.selected.getCount() != toBeSelected.length) {
57424             change = true;
57425         }
57426
57427         me.clearSelections();
57428         
57429         if (me.store.indexOf(lastFocused) !== -1) {
57430             
57431             this.setLastFocused(lastFocused, true);
57432         }
57433
57434         if (toBeSelected.length) {
57435             
57436             me.doSelect(toBeSelected, false, true);
57437         }
57438         
57439         me.maybeFireSelectionChange(change);
57440     },
57441
57442     
57443     clearSelections: function() {
57444         
57445         var me = this;
57446         me.selected.clear();
57447         me.lastSelected = null;
57448         me.setLastFocused(null);
57449     },
57450
57451     
57452     onStoreAdd: function() {
57453
57454     },
57455
57456     
57457     
57458     onStoreClear: function() {
57459         var me = this,
57460             selected = this.selected;
57461             
57462         if (selected.getCount > 0) {
57463             selected.clear();
57464             me.lastSelected = null;
57465             me.setLastFocused(null);
57466             me.maybeFireSelectionChange(true);
57467         }
57468     },
57469
57470     
57471     
57472     
57473     onStoreRemove: function(store, record) {
57474         var me = this,
57475             selected = me.selected;
57476             
57477         if (me.locked || !me.pruneRemoved) {
57478             return;
57479         }
57480
57481         if (selected.remove(record)) {
57482             if (me.lastSelected == record) {
57483                 me.lastSelected = null;
57484             }
57485             if (me.getLastFocused() == record) {
57486                 me.setLastFocused(null);
57487             }
57488             me.maybeFireSelectionChange(true);
57489         }
57490     },
57491
57492     getCount: function() {
57493         return this.selected.getCount();
57494     },
57495
57496     
57497     destroy: function() {
57498
57499     },
57500
57501     
57502     onStoreUpdate: function() {
57503
57504     },
57505
57506     
57507     onSelectChange: function(record, isSelected, suppressEvent) {
57508
57509     },
57510
57511     
57512     onLastFocusChanged: function(oldFocused, newFocused) {
57513
57514     },
57515
57516     
57517     onEditorKey: function(field, e) {
57518
57519     },
57520
57521     
57522     bindComponent: function(cmp) {
57523
57524     }
57525 });
57526
57527 Ext.define('Ext.selection.DataViewModel', {
57528     extend: 'Ext.selection.Model',
57529     
57530     requires: ['Ext.util.KeyNav'],
57531
57532     deselectOnContainerClick: true,
57533     
57534     
57535     enableKeyNav: true,
57536     
57537     constructor: function(cfg){
57538         this.addEvents(
57539             
57540             'deselect',
57541             
57542             
57543             'select'
57544         );
57545         this.callParent(arguments);
57546     },
57547     
57548     bindComponent: function(view) {
57549         var me = this,
57550             eventListeners = {
57551                 refresh: me.refresh,
57552                 scope: me
57553             };
57554
57555         me.view = view;
57556         me.bind(view.getStore());
57557
57558         view.on(view.triggerEvent, me.onItemClick, me);
57559         view.on(view.triggerCtEvent, me.onContainerClick, me);
57560
57561         view.on(eventListeners);
57562
57563         if (me.enableKeyNav) {
57564             me.initKeyNav(view);
57565         }
57566     },
57567
57568     onItemClick: function(view, record, item, index, e) {
57569         this.selectWithEvent(record, e);
57570     },
57571
57572     onContainerClick: function() {
57573         if (this.deselectOnContainerClick) {
57574             this.deselectAll();
57575         }
57576     },
57577     
57578     initKeyNav: function(view) {
57579         var me = this;
57580         
57581         if (!view.rendered) {
57582             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
57583             return;
57584         }
57585         
57586         view.el.set({
57587             tabIndex: -1
57588         });
57589         me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
57590             down: Ext.pass(me.onNavKey, [1], me),
57591             right: Ext.pass(me.onNavKey, [1], me),
57592             left: Ext.pass(me.onNavKey, [-1], me),
57593             up: Ext.pass(me.onNavKey, [-1], me),
57594             scope: me
57595         });
57596     },
57597     
57598     onNavKey: function(step) {
57599         step = step || 1;
57600         var me = this,
57601             view = me.view,
57602             selected = me.getSelection()[0],
57603             numRecords = me.view.store.getCount(),
57604             idx;
57605                 
57606         if (selected) {
57607             idx = view.indexOf(view.getNode(selected)) + step;
57608         } else {
57609             idx = 0;
57610         }
57611         
57612         if (idx < 0) {
57613             idx = numRecords - 1;
57614         } else if (idx >= numRecords) {
57615             idx = 0;
57616         }
57617         
57618         me.select(idx);
57619     },
57620
57621     
57622     onSelectChange: function(record, isSelected, suppressEvent) {
57623         var me = this,
57624             view = me.view,
57625             allowSelect = true;
57626         
57627         if (isSelected) {
57628             if (!suppressEvent) {
57629                 allowSelect = me.fireEvent('beforeselect', me, record) !== false;
57630             }
57631             if (allowSelect) {
57632                 view.onItemSelect(record);
57633                 if (!suppressEvent) {
57634                     me.fireEvent('select', me, record);
57635                 }
57636             }
57637         } else {
57638             view.onItemDeselect(record);
57639             if (!suppressEvent) {
57640                 me.fireEvent('deselect', me, record);
57641             }
57642         }
57643     }
57644 });
57645
57646
57647 Ext.define('Ext.state.CookieProvider', {
57648     extend: 'Ext.state.Provider',
57649
57650     constructor : function(config){
57651         var me = this;
57652         me.path = "/";
57653         me.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); 
57654         me.domain = null;
57655         me.secure = false;
57656         me.callParent(arguments);
57657         me.state = me.readCookies();
57658     },
57659     
57660     
57661     set : function(name, value){
57662         var me = this;
57663         
57664         if(typeof value == "undefined" || value === null){
57665             me.clear(name);
57666             return;
57667         }
57668         me.setCookie(name, value);
57669         me.callParent(arguments);
57670     },
57671
57672     
57673     clear : function(name){
57674         this.clearCookie(name);
57675         this.callParent(arguments);
57676     },
57677
57678     
57679     readCookies : function(){
57680         var cookies = {},
57681             c = document.cookie + ";",
57682             re = /\s?(.*?)=(.*?);/g,
57683             prefix = this.prefix,
57684             len = prefix.length,
57685             matches,
57686             name,
57687             value;
57688             
57689         while((matches = re.exec(c)) != null){
57690             name = matches[1];
57691             value = matches[2];
57692             if (name && name.substring(0, len) == prefix){
57693                 cookies[name.substr(len)] = this.decodeValue(value);
57694             }
57695         }
57696         return cookies;
57697     },
57698
57699     
57700     setCookie : function(name, value){
57701         var me = this;
57702         
57703         document.cookie = me.prefix + name + "=" + me.encodeValue(value) +
57704            ((me.expires == null) ? "" : ("; expires=" + me.expires.toGMTString())) +
57705            ((me.path == null) ? "" : ("; path=" + me.path)) +
57706            ((me.domain == null) ? "" : ("; domain=" + me.domain)) +
57707            ((me.secure == true) ? "; secure" : "");
57708     },
57709
57710     
57711     clearCookie : function(name){
57712         var me = this;
57713         
57714         document.cookie = me.prefix + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
57715            ((me.path == null) ? "" : ("; path=" + me.path)) +
57716            ((me.domain == null) ? "" : ("; domain=" + me.domain)) +
57717            ((me.secure == true) ? "; secure" : "");
57718     }
57719 });
57720
57721 Ext.define('Ext.state.LocalStorageProvider', {
57722     
57723     
57724     extend: 'Ext.state.Provider',
57725     
57726     alias: 'state.localstorage',
57727     
57728     
57729    
57730     constructor: function(){
57731         var me = this;
57732         me.callParent(arguments);
57733         me.store = me.getStorageObject();
57734         me.state = me.readLocalStorage();
57735     },
57736     
57737     readLocalStorage: function(){
57738         var store = this.store,
57739             i = 0,
57740             len = store.length,
57741             prefix = this.prefix,
57742             prefixLen = prefix.length,
57743             data = {},
57744             key;
57745             
57746         for (; i < len; ++i) {
57747             key = store.key(i);
57748             if (key.substring(0, prefixLen) == prefix) {
57749                 data[key.substr(prefixLen)] = this.decodeValue(store.getItem(key));
57750             }            
57751         }
57752         return data;
57753     },
57754     
57755     set : function(name, value){
57756         var me = this;
57757         
57758         me.clear(name);
57759         if (typeof value == "undefined" || value === null) {
57760             return;
57761         }
57762         me.store.setItem(me.prefix + name, me.encodeValue(value));
57763         me.callParent(arguments);
57764     },
57765
57766     
57767     clear : function(name){
57768         this.store.removeItem(this.prefix + name);
57769         this.callParent(arguments);
57770     },
57771     
57772     getStorageObject: function(){
57773         try {
57774             var supports = 'localStorage' in window && window['localStorage'] !== null;
57775             if (supports) {
57776                 return window.localStorage;
57777             }
57778         } catch (e) {
57779             return false;
57780         }
57781         Ext.Error.raise('LocalStorage is not supported by the current browser');
57782     }    
57783 });
57784
57785
57786
57787 Ext.define('Ext.util.Point', {
57788
57789     
57790     extend: 'Ext.util.Region',
57791
57792     statics: {
57793
57794         
57795         fromEvent: function(e) {
57796             e = (e.changedTouches && e.changedTouches.length > 0) ? e.changedTouches[0] : e;
57797             return new this(e.pageX, e.pageY);
57798         }
57799     },
57800
57801     
57802
57803     constructor: function(x, y) {
57804         this.callParent([y, x, y, x]);
57805     },
57806
57807     
57808     toString: function() {
57809         return "Point[" + this.x + "," + this.y + "]";
57810     },
57811
57812     
57813     equals: function(p) {
57814         return (this.x == p.x && this.y == p.y);
57815     },
57816
57817     
57818     isWithin: function(p, threshold) {
57819         if (!Ext.isObject(threshold)) {
57820             threshold = {
57821                 x: threshold,
57822                 y: threshold
57823             };
57824         }
57825
57826         return (this.x <= p.x + threshold.x && this.x >= p.x - threshold.x &&
57827                 this.y <= p.y + threshold.y && this.y >= p.y - threshold.y);
57828     },
57829
57830     
57831     roundedEquals: function(p) {
57832         return (Math.round(this.x) == Math.round(p.x) && Math.round(this.y) == Math.round(p.y));
57833     }
57834 }, function() {
57835     
57836     this.prototype.translate = Ext.util.Region.prototype.translateBy;
57837 });
57838
57839
57840 Ext.define('Ext.view.AbstractView', {
57841     extend: 'Ext.Component',
57842     alternateClassName: 'Ext.view.AbstractView',
57843     requires: [
57844         'Ext.LoadMask',
57845         'Ext.data.StoreManager',
57846         'Ext.CompositeElementLite',
57847         'Ext.DomQuery',
57848         'Ext.selection.DataViewModel'
57849     ],
57850     
57851     inheritableStatics: {
57852         getRecord: function(node) {
57853             return this.getBoundView(node).getRecord(node);
57854         },
57855         
57856         getBoundView: function(node) {
57857             return Ext.getCmp(node.boundView);
57858         }
57859     },
57860     
57861     
57862     
57863
57864     
57865     
57866     
57867     itemCls: Ext.baseCSSPrefix + 'dataview-item',
57868     
57869     
57870
57871     
57872
57873     
57874     loadingText: 'Loading...',
57875     
57876     
57877     
57878     
57879     loadingUseMsg: true,
57880     
57881
57882     
57883
57884     
57885     selectedItemCls: Ext.baseCSSPrefix + 'item-selected',
57886
57887     
57888     emptyText: "",
57889
57890     
57891     deferEmptyText: true,
57892
57893     
57894     trackOver: false,
57895
57896     
57897     blockRefresh: false,
57898
57899     
57900
57901
57902     
57903     last: false,
57904     
57905     triggerEvent: 'itemclick',
57906     triggerCtEvent: 'containerclick',
57907     
57908     addCmpEvents: function() {
57909         
57910     },
57911
57912     
57913     initComponent : function(){
57914         var me = this,
57915             isDef = Ext.isDefined,
57916             itemTpl = me.itemTpl,
57917             memberFn = {};
57918             
57919         if (itemTpl) {
57920             if (Ext.isArray(itemTpl)) {
57921                 
57922                 itemTpl = itemTpl.join('');
57923             } else if (Ext.isObject(itemTpl)) {
57924                 
57925                 memberFn = Ext.apply(memberFn, itemTpl.initialConfig);
57926                 itemTpl = itemTpl.html;
57927             }
57928             
57929             if (!me.itemSelector) {
57930                 me.itemSelector = '.' + me.itemCls;
57931             }
57932             
57933             itemTpl = Ext.String.format('<tpl for="."><div class="{0}">{1}</div></tpl>', me.itemCls, itemTpl);
57934             me.tpl = Ext.create('Ext.XTemplate', itemTpl, memberFn);
57935         }
57936
57937         if (!isDef(me.tpl) || !isDef(me.itemSelector)) {
57938             Ext.Error.raise({
57939                 sourceClass: 'Ext.view.View',
57940                 tpl: me.tpl,
57941                 itemSelector: me.itemSelector,
57942                 msg: "DataView requires both tpl and itemSelector configurations to be defined."
57943             });
57944         }
57945
57946         me.callParent();
57947         if(Ext.isString(me.tpl) || Ext.isArray(me.tpl)){
57948             me.tpl = Ext.create('Ext.XTemplate', me.tpl);
57949         }
57950
57951         
57952         
57953         if (isDef(me.overCls) || isDef(me.overClass)) {
57954             if (Ext.isDefined(Ext.global.console)) {
57955                 Ext.global.console.warn('Ext.view.View: Using the deprecated overCls or overClass configuration. Use overItemCls instead.');
57956             }
57957             me.overItemCls = me.overCls || me.overClass;
57958             delete me.overCls;
57959             delete me.overClass;
57960         }
57961
57962         if (me.overItemCls) {
57963             me.trackOver = true;
57964         }
57965         
57966         if (isDef(me.selectedCls) || isDef(me.selectedClass)) {
57967             if (Ext.isDefined(Ext.global.console)) {
57968                 Ext.global.console.warn('Ext.view.View: Using the deprecated selectedCls or selectedClass configuration. Use selectedItemCls instead.');
57969             }
57970             me.selectedItemCls = me.selectedCls || me.selectedClass;
57971             delete me.selectedCls;
57972             delete me.selectedClass;
57973         }
57974         
57975         me.addEvents(
57976             
57977             'beforerefresh',
57978             
57979             'refresh',
57980             
57981             'itemupdate',
57982             
57983             'itemadd',
57984             
57985             'itemremove'
57986         );
57987
57988         me.addCmpEvents();
57989
57990         if (me.store) {
57991             me.store = Ext.data.StoreManager.lookup(me.store);
57992         }
57993         me.all = new Ext.CompositeElementLite();
57994         me.getSelectionModel().bindComponent(me);
57995     },
57996
57997     onRender: function() {
57998         var me = this,
57999             loadingText = me.loadingText,
58000             loadingHeight = me.loadingHeight,
58001             undef;
58002
58003         me.callParent(arguments);
58004         if (loadingText) {
58005             
58006             
58007             
58008             
58009             
58010             me.loadMask = Ext.create('Ext.LoadMask', me.floating ? me : me.ownerCt || me, {
58011                 msg: loadingText,
58012                 msgCls: me.loadingCls,
58013                 useMsg: me.loadingUseMsg,
58014                 listeners: {
58015                     beforeshow: function() {
58016                         me.getTargetEl().update('');
58017                         me.getSelectionModel().deselectAll();
58018                         me.all.clear();
58019                         if (loadingHeight) {
58020                             me.setCalculatedSize(undef, loadingHeight);
58021                         }
58022                     },
58023                     hide: function() {
58024                         if (loadingHeight) {
58025                             me.setHeight(me.height);
58026                         }
58027                     }
58028                 }
58029             });
58030         }
58031     },
58032
58033     getSelectionModel: function(){
58034         var me = this,
58035             mode = 'SINGLE';
58036
58037         if (!me.selModel) {
58038             me.selModel = {};
58039         }
58040
58041         if (me.simpleSelect) {
58042             mode = 'SIMPLE';
58043         } else if (me.multiSelect) {
58044             mode = 'MULTI';
58045         }
58046
58047         Ext.applyIf(me.selModel, {
58048             allowDeselect: me.allowDeselect,
58049             mode: mode
58050         });
58051
58052         if (!me.selModel.events) {
58053             me.selModel = Ext.create('Ext.selection.DataViewModel', me.selModel);
58054         }
58055
58056         if (!me.selModel.hasRelaySetup) {
58057             me.relayEvents(me.selModel, ['selectionchange', 'beforeselect', 'select', 'deselect']);
58058             me.selModel.hasRelaySetup = true;
58059         }
58060
58061         
58062         
58063         if (me.disableSelection) {
58064             me.selModel.locked = true;
58065         }
58066
58067         return me.selModel;
58068     },
58069
58070     
58071     refresh: function() {
58072         var me = this,
58073             el,
58074             records;
58075             
58076         if (!me.rendered) {
58077             return;
58078         }
58079         
58080         me.fireEvent('beforerefresh', me);
58081         el = me.getTargetEl();
58082         records = me.store.getRange();
58083
58084         el.update('');
58085         if (records.length < 1) {
58086             if (!me.deferEmptyText || me.hasSkippedEmptyText) {
58087                 el.update(me.emptyText);
58088             }
58089             me.all.clear();
58090         } else {
58091             me.tpl.overwrite(el, me.collectData(records, 0));
58092             me.all.fill(Ext.query(me.getItemSelector(), el.dom));
58093             me.updateIndexes(0);
58094         }
58095         
58096         me.selModel.refresh();
58097         me.hasSkippedEmptyText = true;
58098         me.fireEvent('refresh', me);
58099     },
58100
58101     
58102     prepareData: function(data, index, record) {
58103         if (record) {    
58104             Ext.apply(data, record.getAssociatedData());            
58105         }
58106         return data;
58107     },
58108     
58109     
58110     collectData : function(records, startIndex){
58111         var r = [],
58112             i = 0,
58113             len = records.length;
58114
58115         for(; i < len; i++){
58116             r[r.length] = this.prepareData(records[i].data, startIndex + i, records[i]);
58117         }
58118
58119         return r;
58120     },
58121
58122     
58123     bufferRender : function(records, index){
58124         var div = document.createElement('div');
58125         this.tpl.overwrite(div, this.collectData(records, index));
58126         return Ext.query(this.getItemSelector(), div);
58127     },
58128
58129     
58130     onUpdate : function(ds, record){
58131         var me = this,
58132             index = me.store.indexOf(record),
58133             original,
58134             node;
58135
58136         if (index > -1){
58137             original = me.all.elements[index];
58138             node = me.bufferRender([record], index)[0];
58139
58140             me.all.replaceElement(index, node, true);
58141             me.updateIndexes(index, index);
58142
58143             
58144             
58145             me.selModel.refresh();
58146             me.fireEvent('itemupdate', record, index, node);
58147         }
58148
58149     },
58150
58151     
58152     onAdd : function(ds, records, index) {
58153         var me = this,
58154             nodes;
58155             
58156         if (me.all.getCount() === 0) {
58157             me.refresh();
58158             return;
58159         }
58160         
58161         nodes = me.bufferRender(records, index);
58162         me.doAdd(nodes, records, index);
58163
58164         me.selModel.refresh();
58165         me.updateIndexes(index);
58166         me.fireEvent('itemadd', records, index, nodes);
58167     },
58168
58169     doAdd: function(nodes, records, index) {
58170         var n, a = this.all.elements;
58171         if (index < this.all.getCount()) {
58172             n = this.all.item(index).insertSibling(nodes, 'before', true);
58173             a.splice.apply(a, [index, 0].concat(nodes));
58174         } 
58175         else {
58176             n = this.all.last().insertSibling(nodes, 'after', true);
58177             a.push.apply(a, nodes);
58178         }    
58179     },
58180     
58181     
58182     onRemove : function(ds, record, index) {
58183         var me = this;
58184         
58185         me.doRemove(record, index);
58186         me.updateIndexes(index);
58187         if (me.store.getCount() === 0){
58188             me.refresh();
58189         }
58190         me.fireEvent('itemremove', record, index);
58191     },
58192     
58193     doRemove: function(record, index) {
58194         this.all.removeElement(index, true);
58195     },
58196
58197     
58198     refreshNode : function(index){
58199         this.onUpdate(this.store, this.store.getAt(index));
58200     },
58201
58202     
58203     updateIndexes : function(startIndex, endIndex) {
58204         var ns = this.all.elements,
58205             records = this.store.getRange();
58206         startIndex = startIndex || 0;
58207         endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
58208         for(var i = startIndex; i <= endIndex; i++){
58209             ns[i].viewIndex = i;
58210             ns[i].viewRecordId = records[i].internalId;
58211             if (!ns[i].boundView) {
58212                 ns[i].boundView = this.id;
58213             }
58214         }
58215     },
58216
58217     
58218     getStore : function(){
58219         return this.store;
58220     },
58221
58222     
58223     bindStore : function(store, initial) {
58224         var me = this;
58225         
58226         if (!initial && me.store) {
58227             if (store !== me.store && me.store.autoDestroy) {
58228                 me.store.destroy();
58229             } 
58230             else {
58231                 me.mun(me.store, {
58232                     scope: me,
58233                     datachanged: me.onDataChanged,
58234                     add: me.onAdd,
58235                     remove: me.onRemove,
58236                     update: me.onUpdate,
58237                     clear: me.refresh
58238                 });
58239             }
58240             if (!store) {
58241                 if (me.loadMask) {
58242                     me.loadMask.bindStore(null);
58243                 }
58244                 me.store = null;
58245             }
58246         }
58247         if (store) {
58248             store = Ext.data.StoreManager.lookup(store);
58249             me.mon(store, {
58250                 scope: me,
58251                 datachanged: me.onDataChanged,
58252                 add: me.onAdd,
58253                 remove: me.onRemove,
58254                 update: me.onUpdate,
58255                 clear: me.refresh
58256             });
58257             if (me.loadMask) {
58258                 me.loadMask.bindStore(store);
58259             }
58260         }
58261         
58262         me.store = store;
58263         
58264         me.getSelectionModel().bind(store);
58265         
58266         if (store) {
58267             me.refresh(true);
58268         }
58269     },
58270
58271     
58272     onDataChanged: function() {
58273         if (this.blockRefresh !== true) {
58274             this.refresh.apply(this, arguments);
58275         }
58276     },
58277
58278     
58279     findItemByChild: function(node){
58280         return Ext.fly(node).findParent(this.getItemSelector(), this.getTargetEl());
58281     },
58282     
58283     
58284     findTargetByEvent: function(e) {
58285         return e.getTarget(this.getItemSelector(), this.getTargetEl());
58286     },
58287
58288
58289     
58290     getSelectedNodes: function(){
58291         var nodes   = [],
58292             records = this.selModel.getSelection(),
58293             ln = records.length,
58294             i  = 0;
58295
58296         for (; i < ln; i++) {
58297             nodes.push(this.getNode(records[i]));
58298         }
58299
58300         return nodes;
58301     },
58302
58303     
58304     getRecords: function(nodes) {
58305         var records = [],
58306             i = 0,
58307             len = nodes.length,
58308             data = this.store.data;
58309
58310         for (; i < len; i++) {
58311             records[records.length] = data.getByKey(nodes[i].viewRecordId);
58312         }
58313
58314         return records;
58315     },
58316
58317     
58318     getRecord: function(node){
58319         return this.store.data.getByKey(Ext.getDom(node).viewRecordId);
58320     },
58321     
58322
58323     
58324     isSelected : function(node) {
58325         
58326         var r = this.getRecord(node);
58327         return this.selModel.isSelected(r);
58328     },
58329     
58330     
58331     select: function(records, keepExisting, suppressEvent) {
58332         this.selModel.select(records, keepExisting, suppressEvent);
58333     },
58334
58335     
58336     deselect: function(records, suppressEvent) {
58337         this.selModel.deselect(records, suppressEvent);
58338     },
58339
58340     
58341     getNode : function(nodeInfo) {
58342         if (Ext.isString(nodeInfo)) {
58343             return document.getElementById(nodeInfo);
58344         } else if (Ext.isNumber(nodeInfo)) {
58345             return this.all.elements[nodeInfo];
58346         } else if (nodeInfo instanceof Ext.data.Model) {
58347             return this.getNodeByRecord(nodeInfo);
58348         }
58349         return nodeInfo;
58350     },
58351     
58352     
58353     getNodeByRecord: function(record) {
58354         var ns = this.all.elements,
58355             ln = ns.length,
58356             i = 0;
58357         
58358         for (; i < ln; i++) {
58359             if (ns[i].viewRecordId === record.internalId) {
58360                 return ns[i];
58361             }
58362         }
58363         
58364         return null;
58365     },
58366     
58367     
58368     getNodes: function(start, end) {
58369         var ns = this.all.elements,
58370             nodes = [],
58371             i;
58372
58373         start = start || 0;
58374         end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
58375         if (start <= end) {
58376             for (i = start; i <= end && ns[i]; i++) {
58377                 nodes.push(ns[i]);
58378             }
58379         } else {
58380             for (i = start; i >= end && ns[i]; i--) {
58381                 nodes.push(ns[i]);
58382             }
58383         }
58384         return nodes;
58385     },
58386
58387     
58388     indexOf: function(node) {
58389         node = this.getNode(node);
58390         if (Ext.isNumber(node.viewIndex)) {
58391             return node.viewIndex;
58392         }
58393         return this.all.indexOf(node);
58394     },
58395
58396     onDestroy : function() {
58397         var me = this;
58398         
58399         me.all.clear();
58400         me.callParent();
58401         me.bindStore(null);
58402         me.selModel.destroy();
58403     },
58404
58405     
58406     onItemSelect: function(record) {
58407         var node = this.getNode(record);
58408         Ext.fly(node).addCls(this.selectedItemCls);
58409     },
58410
58411     
58412     onItemDeselect: function(record) {
58413         var node = this.getNode(record);
58414         Ext.fly(node).removeCls(this.selectedItemCls);
58415     },
58416     
58417     getItemSelector: function() {
58418         return this.itemSelector;
58419     }
58420 }, function() {
58421     
58422     
58423     
58424     
58425     Ext.deprecate('extjs', '4.0', function() {
58426         Ext.view.AbstractView.override({
58427             
58428             
58429             
58430             
58431             
58432             getSelectionCount : function(){
58433                 if (Ext.global.console) {
58434                     Ext.global.console.warn("DataView: getSelectionCount will be removed, please interact with the Ext.selection.DataViewModel");
58435                 }
58436                 return this.selModel.getSelection().length;
58437             },
58438         
58439             
58440             getSelectedRecords : function(){
58441                 if (Ext.global.console) {
58442                     Ext.global.console.warn("DataView: getSelectedRecords will be removed, please interact with the Ext.selection.DataViewModel");
58443                 }
58444                 return this.selModel.getSelection();
58445             },
58446     
58447             select: function(records, keepExisting, supressEvents) {
58448                 if (Ext.global.console) {
58449                     Ext.global.console.warn("DataView: select will be removed, please access select through a DataView's SelectionModel, ie: view.getSelectionModel().select()");
58450                 }
58451                 var sm = this.getSelectionModel();
58452                 return sm.select.apply(sm, arguments);
58453             },
58454             
58455             clearSelections: function() {
58456                 if (Ext.global.console) {
58457                     Ext.global.console.warn("DataView: clearSelections will be removed, please access deselectAll through DataView's SelectionModel, ie: view.getSelectionModel().deselectAll()");
58458                 }
58459                 var sm = this.getSelectionModel();
58460                 return sm.deselectAll();
58461             }
58462         });    
58463     });
58464 });
58465
58466
58467 Ext.define('Ext.Action', {
58468
58469     
58470
58471     
58472
58473     
58474     
58475     
58476     
58477     
58478     
58479     
58480
58481     constructor : function(config){
58482         this.initialConfig = config;
58483         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
58484         this.items = [];
58485     },
58486
58487     
58488     isAction : true,
58489
58490     
58491     setText : function(text){
58492         this.initialConfig.text = text;
58493         this.callEach('setText', [text]);
58494     },
58495
58496     
58497     getText : function(){
58498         return this.initialConfig.text;
58499     },
58500
58501     
58502     setIconCls : function(cls){
58503         this.initialConfig.iconCls = cls;
58504         this.callEach('setIconCls', [cls]);
58505     },
58506
58507     
58508     getIconCls : function(){
58509         return this.initialConfig.iconCls;
58510     },
58511
58512     
58513     setDisabled : function(v){
58514         this.initialConfig.disabled = v;
58515         this.callEach('setDisabled', [v]);
58516     },
58517
58518     
58519     enable : function(){
58520         this.setDisabled(false);
58521     },
58522
58523     
58524     disable : function(){
58525         this.setDisabled(true);
58526     },
58527
58528     
58529     isDisabled : function(){
58530         return this.initialConfig.disabled;
58531     },
58532
58533     
58534     setHidden : function(v){
58535         this.initialConfig.hidden = v;
58536         this.callEach('setVisible', [!v]);
58537     },
58538
58539     
58540     show : function(){
58541         this.setHidden(false);
58542     },
58543
58544     
58545     hide : function(){
58546         this.setHidden(true);
58547     },
58548
58549     
58550     isHidden : function(){
58551         return this.initialConfig.hidden;
58552     },
58553
58554     
58555     setHandler : function(fn, scope){
58556         this.initialConfig.handler = fn;
58557         this.initialConfig.scope = scope;
58558         this.callEach('setHandler', [fn, scope]);
58559     },
58560
58561     
58562     each : function(fn, scope){
58563         Ext.each(this.items, fn, scope);
58564     },
58565
58566     
58567     callEach : function(fnName, args){
58568         var items = this.items,
58569             i = 0,
58570             len = items.length;
58571             
58572         for(; i < len; i++){
58573             items[i][fnName].apply(items[i], args);
58574         }
58575     },
58576
58577     
58578     addComponent : function(comp){
58579         this.items.push(comp);
58580         comp.on('destroy', this.removeComponent, this);
58581     },
58582
58583     
58584     removeComponent : function(comp){
58585         Ext.Array.remove(this.items, comp);
58586     },
58587
58588     
58589     execute : function(){
58590         this.initialConfig.handler.apply(this.initialConfig.scope || Ext.global, arguments);
58591     }
58592 });
58593
58594
58595 Ext.define('Ext.layout.component.Editor', {
58596
58597     
58598
58599     alias: ['layout.editor'],
58600
58601     extend: 'Ext.layout.component.Component',
58602
58603     
58604
58605     onLayout: function(width, height) {
58606         var me = this,
58607             owner = me.owner,
58608             autoSize = owner.autoSize;
58609             
58610         if (autoSize === true) {
58611             autoSize = {
58612                 width: 'field',
58613                 height: 'field'    
58614             };
58615         }
58616         
58617         if (autoSize) {
58618             width = me.getDimension(owner, autoSize.width, 'Width', width);
58619             height = me.getDimension(owner, autoSize.height, 'Height', height);
58620         }
58621         me.setTargetSize(width, height);
58622         owner.field.setSize(width, height);
58623     },
58624     
58625     getDimension: function(owner, type, dimension, actual){
58626         var method = 'get' + dimension;
58627         switch (type) {
58628             case 'boundEl':
58629                 return owner.boundEl[method]();
58630             case 'field':
58631                 return owner.field[method]();
58632             default:
58633                 return actual;
58634         }
58635     }
58636 });
58637
58638 Ext.define('Ext.Editor', {
58639
58640     
58641
58642     extend: 'Ext.Component',
58643
58644     alias: 'widget.editor',
58645
58646     requires: ['Ext.layout.component.Editor'],
58647
58648     
58649
58650    componentLayout: 'editor',
58651
58652     
58653
58654     
58655     allowBlur: true,
58656
58657     
58658
58659     
58660     revertInvalid: true,
58661
58662     
58663
58664     
58665
58666     
58667     value : '',
58668
58669     
58670     alignment: 'c-c?',
58671
58672     
58673     offsets: [0, 0],
58674
58675     
58676     shadow : 'frame',
58677
58678     
58679     constrain : false,
58680
58681     
58682     swallowKeys : true,
58683
58684     
58685     completeOnEnter : true,
58686
58687     
58688     cancelOnEsc : true,
58689
58690     
58691     updateEl : false,
58692
58693     
58694
58695     
58696     hidden: true,
58697     baseCls: Ext.baseCSSPrefix + 'editor',
58698
58699     initComponent : function() {
58700         var me = this,
58701             field = me.field = Ext.ComponentManager.create(me.field, 'textfield');
58702
58703         Ext.apply(field, {
58704             inEditor: true,
58705             msgTarget: field.msgTarget == 'title' ? 'title' :  'qtip'
58706         });
58707         me.mon(field, {
58708             scope: me,
58709             blur: {
58710                 fn: me.onBlur,
58711                 
58712                 delay: 1
58713             },
58714             specialkey: me.onSpecialKey
58715         });
58716
58717         if (field.grow) {
58718             me.mon(field, 'autosize', me.onAutoSize,  me, {delay: 1});
58719         }
58720         me.floating = {
58721             constrain: me.constrain
58722         };
58723
58724         me.callParent(arguments);
58725
58726         me.addEvents(
58727             
58728             'beforestartedit',
58729             
58730             'startedit',
58731             
58732             'beforecomplete',
58733             
58734             'complete',
58735             
58736             'canceledit',
58737             
58738             'specialkey'
58739         );
58740     },
58741
58742     
58743     onAutoSize: function(){
58744         this.doComponentLayout();
58745     },
58746
58747     
58748     onRender : function(ct, position) {
58749         var me = this,
58750             field = me.field;
58751
58752         me.callParent(arguments);
58753
58754         field.render(me.el);
58755         
58756         
58757         field.inputEl.dom.name = '';
58758         if (me.swallowKeys) {
58759             field.inputEl.swallowEvent([
58760                 'keypress', 
58761                 'keydown'   
58762             ]);
58763         }
58764     },
58765
58766     
58767     onSpecialKey : function(field, event) {
58768         var me = this,
58769             key = event.getKey(),
58770             complete = me.completeOnEnter && key == event.ENTER,
58771             cancel = me.cancelOnEsc && key == event.ESC;
58772
58773         if (complete || cancel) {
58774             event.stopEvent();
58775             
58776             
58777             Ext.defer(function() {
58778                 if (complete) {
58779                     me.completeEdit();
58780                 } else {
58781                     me.cancelEdit();
58782                 }
58783                 if (field.triggerBlur) {
58784                     field.triggerBlur();
58785                 }
58786             }, 10);
58787         }
58788
58789         this.fireEvent('specialkey', this, field, event);
58790     },
58791
58792     
58793     startEdit : function(el, value) {
58794         var me = this,
58795             field = me.field;
58796
58797         me.completeEdit();
58798         me.boundEl = Ext.get(el);
58799         value = Ext.isDefined(value) ? value : me.boundEl.dom.innerHTML;
58800
58801         if (!me.rendered) {
58802             me.render(me.parentEl || document.body);
58803         }
58804
58805         if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) {
58806             me.startValue = value;
58807             me.show();
58808             field.reset();
58809             field.setValue(value);
58810             me.realign(true);
58811             field.focus(false, 10);
58812             if (field.autoSize) {
58813                 field.autoSize();
58814             }
58815             me.editing = true;
58816         }
58817     },
58818
58819     
58820     realign : function(autoSize) {
58821         var me = this;
58822         if (autoSize === true) {
58823             me.doComponentLayout();
58824         }
58825         me.alignTo(me.boundEl, me.alignment, me.offsets);
58826     },
58827
58828     
58829     completeEdit : function(remainVisible) {
58830         var me = this,
58831             field = me.field,
58832             value;
58833
58834         if (!me.editing) {
58835             return;
58836         }
58837
58838         
58839         if (field.assertValue) {
58840             field.assertValue();
58841         }
58842
58843         value = me.getValue();
58844         if (!field.isValid()) {
58845             if (me.revertInvalid !== false) {
58846                 me.cancelEdit(remainVisible);
58847             }
58848             return;
58849         }
58850
58851         if (String(value) === String(me.startValue) && me.ignoreNoChange) {
58852             me.hideEdit(remainVisible);
58853             return;
58854         }
58855
58856         if (me.fireEvent('beforecomplete', me, value, me.startValue) !== false) {
58857             
58858             value = me.getValue();
58859             if (me.updateEl && me.boundEl) {
58860                 me.boundEl.update(value);
58861             }
58862             me.hideEdit(remainVisible);
58863             me.fireEvent('complete', me, value, me.startValue);
58864         }
58865     },
58866
58867     
58868     onShow : function() {
58869         var me = this;
58870
58871         me.callParent(arguments);
58872         if (me.hideEl !== false) {
58873             me.boundEl.hide();
58874         }
58875         me.fireEvent("startedit", me.boundEl, me.startValue);
58876     },
58877
58878     
58879     cancelEdit : function(remainVisible) {
58880         var me = this,
58881             startValue = me.startValue,
58882             value;
58883
58884         if (me.editing) {
58885             value = me.getValue();
58886             me.setValue(startValue);
58887             me.hideEdit(remainVisible);
58888             me.fireEvent('canceledit', me, value, startValue);
58889         }
58890     },
58891
58892     
58893     hideEdit: function(remainVisible) {
58894         if (remainVisible !== true) {
58895             this.editing = false;
58896             this.hide();
58897         }
58898     },
58899
58900     
58901     onBlur : function() {
58902         var me = this;
58903
58904         
58905         if(me.allowBlur === true && me.editing && me.selectSameEditor !== true) {
58906             me.completeEdit();
58907         }
58908     },
58909
58910     
58911     onHide : function() {
58912         var me = this,
58913             field = me.field;
58914
58915         if (me.editing) {
58916             me.completeEdit();
58917             return;
58918         }
58919         field.blur();
58920         if (field.collapse) {
58921             field.collapse();
58922         }
58923
58924         
58925         if (me.hideEl !== false) {
58926             me.boundEl.show();
58927         }
58928         me.callParent(arguments);
58929     },
58930
58931     
58932     setValue : function(value) {
58933         this.field.setValue(value);
58934     },
58935
58936     
58937     getValue : function() {
58938         return this.field.getValue();
58939     },
58940
58941     beforeDestroy : function() {
58942         var me = this;
58943
58944         Ext.destroy(me.field);
58945         delete me.field;
58946         delete me.parentEl;
58947         delete me.boundEl;
58948
58949         me.callParent(arguments);
58950     }
58951 });
58952
58953 Ext.define('Ext.Img', {
58954     extend: 'Ext.Component',
58955     alias: ['widget.image', 'widget.imagecomponent'],
58956     
58957     src: '',
58958
58959     getElConfig: function() {
58960         return {
58961             tag: 'img',
58962             src: this.src
58963         };
58964     },
58965     
58966     
58967     initRenderTpl: Ext.emptyFn,
58968     
58969     
58970     setSrc: function(src) {
58971         var me = this,
58972             img = me.el;
58973         me.src = src;
58974         if (img) {
58975             img.dom.src = src;
58976         }
58977     }
58978 });
58979
58980
58981 Ext.define('Ext.Layer', {
58982     uses: ['Ext.Shadow'],
58983
58984     
58985     statics: {
58986         shims: []
58987     },
58988
58989     extend: 'Ext.core.Element',
58990
58991     constructor: function(config, existingEl) {
58992         config = config || {};
58993         var me = this,
58994             dh = Ext.core.DomHelper,
58995             cp = config.parentEl,
58996             pel = cp ? Ext.getDom(cp) : document.body,
58997         hm = config.hideMode;
58998
58999         if (existingEl) {
59000             me.dom = Ext.getDom(existingEl);
59001         }
59002         if (!me.dom) {
59003             me.dom = dh.append(pel, config.dh || {
59004                 tag: 'div',
59005                 cls: Ext.baseCSSPrefix + 'layer'
59006             });
59007         } else {
59008             me.addCls(Ext.baseCSSPrefix + 'layer');
59009             if (!me.dom.parentNode) {
59010                 pel.appendChild(me.dom);
59011             }
59012         }
59013
59014         if (config.cls) {
59015             me.addCls(config.cls);
59016         }
59017         me.constrain = config.constrain !== false;
59018
59019         
59020         
59021         
59022         if (hm) {
59023             me.setVisibilityMode(Ext.core.Element[hm.toUpperCase()]);
59024             if (me.visibilityMode == Ext.core.Element.ASCLASS) {
59025                 me.visibilityCls = config.visibilityCls;
59026             }
59027         } else if (config.useDisplay) {
59028             me.setVisibilityMode(Ext.core.Element.DISPLAY);
59029         } else {
59030             me.setVisibilityMode(Ext.core.Element.VISIBILITY);
59031         }
59032
59033         if (config.id) {
59034             me.id = me.dom.id = config.id;
59035         } else {
59036             me.id = Ext.id(me.dom);
59037         }
59038         me.position('absolute');
59039         if (config.shadow) {
59040             me.shadowOffset = config.shadowOffset || 4;
59041             me.shadow = Ext.create('Ext.Shadow', {
59042                 offset: me.shadowOffset,
59043                 mode: config.shadow
59044             });
59045             me.disableShadow();
59046         } else {
59047             me.shadowOffset = 0;
59048         }
59049         me.useShim = config.shim !== false && Ext.useShims;
59050         if (config.hidden === true) {
59051             me.hide();
59052         } else {
59053             this.show();
59054         }
59055     },
59056
59057     getZIndex: function() {
59058         return parseInt((this.getShim() || this).getStyle('z-index'), 10);
59059     },
59060
59061     getShim: function() {
59062         var me = this,
59063             shim, pn;
59064
59065         if (!me.useShim) {
59066             return null;
59067         }
59068         if (!me.shim) {
59069             shim = me.self.shims.shift();
59070             if (!shim) {
59071                 shim = me.createShim();
59072                 shim.enableDisplayMode('block');
59073                 shim.hide();
59074             }
59075             pn = me.dom.parentNode;
59076             if (shim.dom.parentNode != pn) {
59077                 pn.insertBefore(shim.dom, me.dom);
59078             }
59079             me.shim = shim;
59080         }
59081         return me.shim;
59082     },
59083
59084     hideShim: function() {
59085         if (this.shim) {
59086             this.shim.setDisplayed(false);
59087             this.self.shims.push(this.shim);
59088             delete this.shim;
59089         }
59090     },
59091
59092     disableShadow: function() {
59093         if (this.shadow) {
59094             this.shadowDisabled = true;
59095             this.shadow.hide();
59096             this.lastShadowOffset = this.shadowOffset;
59097             this.shadowOffset = 0;
59098         }
59099     },
59100
59101     enableShadow: function(show) {
59102         if (this.shadow) {
59103             this.shadowDisabled = false;
59104             this.shadowOffset = this.lastShadowOffset;
59105             delete this.lastShadowOffset;
59106             if (show) {
59107                 this.sync(true);
59108             }
59109         }
59110     },
59111
59112     
59113     sync: function(doShow) {
59114         var me = this,
59115             shadow = me.shadow,
59116             shadowPos, shimStyle, shadowSize;
59117
59118         if (!this.updating && this.isVisible() && (shadow || this.useShim)) {
59119             var shim = this.getShim(),
59120                 l = this.getLeft(true),
59121                 t = this.getTop(true),
59122                 w = this.getWidth(),
59123                 h = this.getHeight(),
59124                 shimIndex;
59125
59126             if (shadow && !this.shadowDisabled) {
59127                 if (doShow && !shadow.isVisible()) {
59128                     shadow.show(this);
59129                 } else {
59130                     shadow.realign(l, t, w, h);
59131                 }
59132                 if (shim) {
59133                     
59134                     shimIndex = shim.getStyle('z-index');
59135                     if (shimIndex > me.zindex) {
59136                         me.shim.setStyle('z-index', me.zindex - 2);
59137                     }
59138                     shim.show();
59139                     
59140                     if (shadow.isVisible()) {
59141                         shadowPos = shadow.el.getXY();
59142                         shimStyle = shim.dom.style;
59143                         shadowSize = shadow.el.getSize();
59144                         shimStyle.left = (shadowPos[0]) + 'px';
59145                         shimStyle.top = (shadowPos[1]) + 'px';
59146                         shimStyle.width = (shadowSize.width) + 'px';
59147                         shimStyle.height = (shadowSize.height) + 'px';
59148                     } else {
59149                         shim.setSize(w, h);
59150                         shim.setLeftTop(l, t);
59151                     }
59152                 }
59153             } else if (shim) {
59154                 
59155                 shimIndex = shim.getStyle('z-index');
59156                 if (shimIndex > me.zindex) {
59157                     me.shim.setStyle('z-index', me.zindex - 2);
59158                 }
59159                 shim.show();
59160                 shim.setSize(w, h);
59161                 shim.setLeftTop(l, t);
59162             }
59163         }
59164         return this;
59165     },
59166
59167     remove: function() {
59168         this.hideUnders();
59169         this.callParent();
59170     },
59171
59172     
59173     beginUpdate: function() {
59174         this.updating = true;
59175     },
59176
59177     
59178     endUpdate: function() {
59179         this.updating = false;
59180         this.sync(true);
59181     },
59182
59183     
59184     hideUnders: function() {
59185         if (this.shadow) {
59186             this.shadow.hide();
59187         }
59188         this.hideShim();
59189     },
59190
59191     
59192     constrainXY: function() {
59193         if (this.constrain) {
59194             var vw = Ext.core.Element.getViewWidth(),
59195                 vh = Ext.core.Element.getViewHeight(),
59196                 s = Ext.getDoc().getScroll(),
59197                 xy = this.getXY(),
59198                 x = xy[0],
59199                 y = xy[1],
59200                 so = this.shadowOffset,
59201                 w = this.dom.offsetWidth + so,
59202                 h = this.dom.offsetHeight + so,
59203                 moved = false; 
59204             
59205             if ((x + w) > vw + s.left) {
59206                 x = vw - w - so;
59207                 moved = true;
59208             }
59209             if ((y + h) > vh + s.top) {
59210                 y = vh - h - so;
59211                 moved = true;
59212             }
59213             
59214             if (x < s.left) {
59215                 x = s.left;
59216                 moved = true;
59217             }
59218             if (y < s.top) {
59219                 y = s.top;
59220                 moved = true;
59221             }
59222             if (moved) {
59223                 Ext.Layer.superclass.setXY.call(this, [x, y]);
59224                 this.sync();
59225             }
59226         }
59227         return this;
59228     },
59229
59230     getConstrainOffset: function() {
59231         return this.shadowOffset;
59232     },
59233
59234     
59235     setVisible: function(visible, animate, duration, callback, easing) {
59236         var me = this,
59237             cb;
59238
59239         
59240         cb = function() {
59241             if (visible) {
59242                 me.sync(true);
59243             }
59244             if (callback) {
59245                 callback();
59246             }
59247         };
59248
59249         
59250         if (!visible) {
59251             this.hideUnders(true);
59252         }
59253         this.callParent([visible, animate, duration, callback, easing]);
59254         if (!animate) {
59255             cb();
59256         }
59257         return this;
59258     },
59259
59260     
59261     beforeFx: function() {
59262         this.beforeAction();
59263         return this.callParent(arguments);
59264     },
59265
59266     
59267     afterFx: function() {
59268         this.callParent(arguments);
59269         this.sync(this.isVisible());
59270     },
59271
59272     
59273     beforeAction: function() {
59274         if (!this.updating && this.shadow) {
59275             this.shadow.hide();
59276         }
59277     },
59278
59279     
59280     setLeft: function(left) {
59281         this.callParent(arguments);
59282         return this.sync();
59283     },
59284
59285     setTop: function(top) {
59286         this.callParent(arguments);
59287         return this.sync();
59288     },
59289
59290     setLeftTop: function(left, top) {
59291         this.callParent(arguments);
59292         return this.sync();
59293     },
59294
59295     setXY: function(xy, animate, duration, callback, easing) {
59296
59297         
59298         callback = this.createCB(callback);
59299
59300         this.fixDisplay();
59301         this.beforeAction();
59302         this.callParent([xy, animate, duration, callback, easing]);
59303         if (!animate) {
59304             callback();
59305         }
59306         return this;
59307     },
59308
59309     
59310     createCB: function(callback) {
59311         var me = this,
59312             showShadow = me.shadow && me.shadow.isVisible();
59313
59314         return function() {
59315             me.constrainXY();
59316             me.sync(showShadow);
59317             if (callback) {
59318                 callback();
59319             }
59320         };
59321     },
59322
59323     
59324     setX: function(x, animate, duration, callback, easing) {
59325         this.setXY([x, this.getY()], animate, duration, callback, easing);
59326         return this;
59327     },
59328
59329     
59330     setY: function(y, animate, duration, callback, easing) {
59331         this.setXY([this.getX(), y], animate, duration, callback, easing);
59332         return this;
59333     },
59334
59335     
59336     setSize: function(w, h, animate, duration, callback, easing) {
59337         
59338         callback = this.createCB(callback);
59339
59340         this.beforeAction();
59341         this.callParent([w, h, animate, duration, callback, easing]);
59342         if (!animate) {
59343             callback();
59344         }
59345         return this;
59346     },
59347
59348     
59349     setWidth: function(w, animate, duration, callback, easing) {
59350         
59351         callback = this.createCB(callback);
59352
59353         this.beforeAction();
59354         this.callParent([w, animate, duration, callback, easing]);
59355         if (!animate) {
59356             callback();
59357         }
59358         return this;
59359     },
59360
59361     
59362     setHeight: function(h, animate, duration, callback, easing) {
59363         
59364         callback = this.createCB(callback);
59365
59366         this.beforeAction();
59367         this.callParent([h, animate, duration, callback, easing]);
59368         if (!animate) {
59369             callback();
59370         }
59371         return this;
59372     },
59373
59374     
59375     setBounds: function(x, y, width, height, animate, duration, callback, easing) {
59376         
59377         callback = this.createCB(callback);
59378
59379         this.beforeAction();
59380         if (!animate) {
59381             Ext.Layer.superclass.setXY.call(this, [x, y]);
59382             Ext.Layer.superclass.setSize.call(this, width, height);
59383             callback();
59384         } else {
59385             this.callParent([x, y, width, height, animate, duration, callback, easing]);
59386         }
59387         return this;
59388     },
59389
59390     
59391     setZIndex: function(zindex) {
59392         this.zindex = zindex;
59393         if (this.getShim()) {
59394             this.shim.setStyle('z-index', zindex++);
59395         }
59396         if (this.shadow) {
59397             this.shadow.setZIndex(zindex++);
59398         }
59399         this.setStyle('z-index', zindex);
59400         return this;
59401     }
59402 });
59403
59404
59405
59406 Ext.define('Ext.layout.component.ProgressBar', {
59407
59408     
59409
59410     alias: ['layout.progressbar'],
59411
59412     extend: 'Ext.layout.component.Component',
59413
59414     
59415
59416     type: 'progressbar',
59417
59418     onLayout: function(width, height) {
59419         var me = this,
59420             owner = me.owner,
59421             textEl = owner.textEl;
59422         
59423         me.setElementSize(owner.el, width, height);
59424         textEl.setWidth(owner.el.getWidth(true));
59425         
59426         me.callParent([width, height]);
59427         
59428         owner.updateProgress(owner.value);
59429     }
59430 });
59431
59432 Ext.define('Ext.ProgressBar', {
59433     extend: 'Ext.Component',
59434     alias: 'widget.progressbar',
59435
59436     requires: [
59437         'Ext.Template',
59438         'Ext.CompositeElement',
59439         'Ext.TaskManager',
59440         'Ext.layout.component.ProgressBar'
59441     ],
59442
59443     uses: ['Ext.fx.Anim'],
59444    
59445     baseCls: Ext.baseCSSPrefix + 'progress',
59446
59447     config: {
59448         
59449         animate: false,
59450
59451         
59452         text: ''
59453     },
59454
59455     
59456     waitTimer: null,
59457
59458     renderTpl: [
59459         '<div class="{baseCls}-text {baseCls}-text-back">',
59460             '<div>&#160;</div>',
59461         '</div>',
59462         '<div class="{baseCls}-bar">',
59463             '<div class="{baseCls}-text">',
59464                 '<div>&#160;</div>',
59465             '</div>',
59466         '</div>'
59467     ],
59468
59469     componentLayout: 'progressbar',
59470
59471     
59472     initComponent: function() {
59473         this.callParent();
59474
59475         this.renderSelectors = Ext.apply(this.renderSelectors || {}, {
59476             textTopEl: '.' + this.baseCls + '-text',
59477             textBackEl: '.' + this.baseCls + '-text-back',
59478             bar: '.' + this.baseCls + '-bar'
59479         });
59480
59481         this.addEvents(
59482             
59483             "update"
59484         );
59485     },
59486
59487     afterRender : function() {
59488         var me = this;
59489
59490         me.textEl = me.textEl ? Ext.get(me.textEl) : me.el.select('.' + me.baseCls + '-text');
59491
59492         this.callParent(arguments);
59493
59494         if (me.value) {
59495             me.updateProgress(me.value, me.text);
59496         }
59497         else {
59498             me.updateText(me.text);
59499         }
59500     },
59501
59502     
59503     updateProgress: function(value, text, animate) {
59504         var newWidth;
59505         this.value = value || 0;
59506         if (text) {
59507             this.updateText(text);
59508         }
59509         if (this.rendered && !this.isDestroyed) {
59510             newWidth = Math.floor(this.value * this.el.getWidth(true));
59511             if (Ext.isForcedBorderBox) {
59512                 newWidth += this.bar.getBorderWidth("lr");
59513             }
59514             if (animate === true || (animate !== false && this.animate)) {
59515                 this.bar.stopAnimation();
59516                 this.bar.animate(Ext.apply({
59517                     to: {
59518                         width: newWidth + 'px'
59519                     }
59520                 }, this.animate));
59521             } else {
59522                 this.bar.setWidth(newWidth);
59523             }
59524         }
59525         this.fireEvent('update', this, this.value, text);
59526         return this;
59527     },
59528
59529     
59530     updateText: function(text) {
59531         this.text = text;
59532         if (this.rendered) {
59533             this.textEl.update(this.text);
59534         }
59535         return this;
59536     },
59537
59538     applyText : function(text) {
59539         this.updateText(text);
59540     },
59541
59542     
59543     wait: function(o) {
59544         if (!this.waitTimer) {
59545             var scope = this;
59546             o = o || {};
59547             this.updateText(o.text);
59548             this.waitTimer = Ext.TaskManager.start({
59549                 run: function(i){
59550                     var inc = o.increment || 10;
59551                     i -= 1;
59552                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
59553                 },
59554                 interval: o.interval || 1000,
59555                 duration: o.duration,
59556                 onStop: function(){
59557                     if (o.fn) {
59558                         o.fn.apply(o.scope || this);
59559                     }
59560                     this.reset();
59561                 },
59562                 scope: scope
59563             });
59564         }
59565         return this;
59566     },
59567
59568     
59569     isWaiting: function(){
59570         return this.waitTimer !== null;
59571     },
59572
59573     
59574     reset: function(hide){
59575         this.updateProgress(0);
59576         this.clearTimer();
59577         if (hide === true) {
59578             this.hide();
59579         }
59580         return this;
59581     },
59582
59583     
59584     clearTimer: function(){
59585         if (this.waitTimer) {
59586             this.waitTimer.onStop = null; 
59587             Ext.TaskManager.stop(this.waitTimer);
59588             this.waitTimer = null;
59589         }
59590     },
59591
59592     onDestroy: function(){
59593         this.clearTimer();
59594         if (this.rendered) {
59595             if (this.textEl.isComposite) {
59596                 this.textEl.clear();
59597             }
59598             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
59599         }
59600         this.callParent();
59601     }
59602 });
59603
59604
59605 Ext.define('Ext.ShadowPool', {
59606     singleton: true,
59607     requires: ['Ext.core.DomHelper'],
59608
59609     markup: function() {
59610         if (Ext.supports.CSS3BoxShadow) {
59611             return '<div class="' + Ext.baseCSSPrefix + 'css-shadow" role="presentation"></div>';
59612         } else if (Ext.isIE) {
59613             return '<div class="' + Ext.baseCSSPrefix + 'ie-shadow" role="presentation"></div>';
59614         } else {
59615             return '<div class="' + Ext.baseCSSPrefix + 'frame-shadow" role="presentation">' +
59616                 '<div class="xst" role="presentation">' +
59617                     '<div class="xstl" role="presentation"></div>' +
59618                     '<div class="xstc" role="presentation"></div>' +
59619                     '<div class="xstr" role="presentation"></div>' +
59620                 '</div>' +
59621                 '<div class="xsc" role="presentation">' +
59622                     '<div class="xsml" role="presentation"></div>' +
59623                     '<div class="xsmc" role="presentation"></div>' +
59624                     '<div class="xsmr" role="presentation"></div>' +
59625                 '</div>' +
59626                 '<div class="xsb" role="presentation">' +
59627                     '<div class="xsbl" role="presentation"></div>' +
59628                     '<div class="xsbc" role="presentation"></div>' +
59629                     '<div class="xsbr" role="presentation"></div>' +
59630                 '</div>' +
59631             '</div>';
59632         }
59633     }(),
59634
59635     shadows: [],
59636
59637     pull: function() {
59638         var sh = this.shadows.shift();
59639         if (!sh) {
59640             sh = Ext.get(Ext.core.DomHelper.insertHtml("beforeBegin", document.body.firstChild, this.markup));
59641             sh.autoBoxAdjust = false;
59642         }
59643         return sh;
59644     },
59645
59646     push: function(sh) {
59647         this.shadows.push(sh);
59648     },
59649     
59650     reset: function() {
59651         Ext.Array.each(this.shadows, function(shadow) {
59652             shadow.remove();
59653         });
59654         this.shadows = [];
59655     }
59656 });
59657
59658 Ext.define('Ext.Shadow', {
59659     requires: ['Ext.ShadowPool'],
59660
59661     constructor: function(config) {
59662         Ext.apply(this, config);
59663         if (typeof this.mode != "string") {
59664             this.mode = this.defaultMode;
59665         }
59666         var offset = this.offset,
59667             adjusts = {
59668                 h: 0
59669             },
59670             rad = Math.floor(this.offset / 2);
59671
59672         switch (this.mode.toLowerCase()) {
59673             
59674             case "drop":
59675                 if (Ext.supports.CSS3BoxShadow) {
59676                     adjusts.w = adjusts.h = -offset;
59677                     adjusts.l = adjusts.t = offset;
59678                 } else {
59679                     adjusts.w = 0;
59680                     adjusts.l = adjusts.t = offset;
59681                     adjusts.t -= 1;
59682                     if (Ext.isIE) {
59683                         adjusts.l -= offset + rad;
59684                         adjusts.t -= offset + rad;
59685                         adjusts.w -= rad;
59686                         adjusts.h -= rad;
59687                         adjusts.t += 1;
59688                     }
59689                 }
59690                 break;
59691             case "sides":
59692                 if (Ext.supports.CSS3BoxShadow) {
59693                     adjusts.h -= offset;
59694                     adjusts.t = offset;
59695                     adjusts.l = adjusts.w = 0;
59696                 } else {
59697                     adjusts.w = (offset * 2);
59698                     adjusts.l = -offset;
59699                     adjusts.t = offset - 1;
59700                     if (Ext.isIE) {
59701                         adjusts.l -= (offset - rad);
59702                         adjusts.t -= offset + rad;
59703                         adjusts.l += 1;
59704                         adjusts.w -= (offset - rad) * 2;
59705                         adjusts.w -= rad + 1;
59706                         adjusts.h -= 1;
59707                     }
59708                 }
59709                 break;
59710             case "frame":
59711                 if (Ext.supports.CSS3BoxShadow) {
59712                     adjusts.l = adjusts.w = adjusts.t = 0;
59713                 } else {
59714                     adjusts.w = adjusts.h = (offset * 2);
59715                     adjusts.l = adjusts.t = -offset;
59716                     adjusts.t += 1;
59717                     adjusts.h -= 2;
59718                     if (Ext.isIE) {
59719                         adjusts.l -= (offset - rad);
59720                         adjusts.t -= (offset - rad);
59721                         adjusts.l += 1;
59722                         adjusts.w -= (offset + rad + 1);
59723                         adjusts.h -= (offset + rad);
59724                         adjusts.h += 1;
59725                     }
59726                     break;
59727                 }
59728         }
59729         this.adjusts = adjusts;
59730     },
59731
59732     
59733     
59734     offset: 4,
59735
59736     
59737     defaultMode: "drop",
59738
59739     
59740     show: function(target) {
59741         target = Ext.get(target);
59742         if (!this.el) {
59743             this.el = Ext.ShadowPool.pull();
59744             if (this.el.dom.nextSibling != target.dom) {
59745                 this.el.insertBefore(target);
59746             }
59747         }
59748         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10) - 1);
59749         if (Ext.isIE && !Ext.supports.CSS3BoxShadow) {
59750             this.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (this.offset) + ")";
59751         }
59752         this.realign(
59753             target.getLeft(true),
59754             target.getTop(true),
59755             target.getWidth(),
59756             target.getHeight()
59757         );
59758         this.el.dom.style.display = "block";
59759     },
59760
59761     
59762     isVisible: function() {
59763         return this.el ? true: false;
59764     },
59765
59766     
59767     realign: function(l, t, targetWidth, targetHeight) {
59768         if (!this.el) {
59769             return;
59770         }
59771         var adjusts = this.adjusts,
59772             d = this.el.dom,
59773             targetStyle = d.style,
59774             shadowWidth,
59775             shadowHeight,
59776             cn,
59777             sww, 
59778             sws, 
59779             shs;
59780
59781         targetStyle.left = (l + adjusts.l) + "px";
59782         targetStyle.top = (t + adjusts.t) + "px";
59783         shadowWidth = Math.max(targetWidth + adjusts.w, 0);
59784         shadowHeight = Math.max(targetHeight + adjusts.h, 0);
59785         sws = shadowWidth + "px";
59786         shs = shadowHeight + "px";
59787         if (targetStyle.width != sws || targetStyle.height != shs) {
59788             targetStyle.width = sws;
59789             targetStyle.height = shs;
59790             if (Ext.supports.CSS3BoxShadow) {
59791                 targetStyle.boxShadow = '0 0 ' + this.offset + 'px 0 #888';
59792             } else {
59793
59794                 
59795                 if (!Ext.isIE) {
59796                     cn = d.childNodes;
59797                     sww = Math.max(0, (shadowWidth - 12)) + "px";
59798                     cn[0].childNodes[1].style.width = sww;
59799                     cn[1].childNodes[1].style.width = sww;
59800                     cn[2].childNodes[1].style.width = sww;
59801                     cn[1].style.height = Math.max(0, (shadowHeight - 12)) + "px";
59802                 }
59803             }
59804         }
59805     },
59806
59807     
59808     hide: function() {
59809         if (this.el) {
59810             this.el.dom.style.display = "none";
59811             Ext.ShadowPool.push(this.el);
59812             delete this.el;
59813         }
59814     },
59815
59816     
59817     setZIndex: function(z) {
59818         this.zIndex = z;
59819         if (this.el) {
59820             this.el.setStyle("z-index", z);
59821         }
59822     }
59823 });
59824
59825
59826 Ext.define('Ext.button.Split', {
59827
59828     
59829
59830     alias: 'widget.splitbutton',
59831
59832     extend: 'Ext.button.Button',
59833     alternateClassName: 'Ext.SplitButton',
59834
59835     
59836     arrowCls      : 'split',
59837     split         : true,
59838
59839     
59840     initComponent : function(){
59841         this.callParent();
59842         
59843         this.addEvents("arrowclick");
59844     },
59845
59846      
59847     setArrowHandler : function(handler, scope){
59848         this.arrowHandler = handler;
59849         this.scope = scope;
59850     },
59851
59852     
59853     onClick : function(e, t) {
59854         var me = this;
59855         
59856         e.preventDefault();
59857         if (!me.disabled) {
59858             if (me.overMenuTrigger) {
59859                 if (me.menu && !me.menu.isVisible() && !me.ignoreNextClick) {
59860                     me.showMenu();
59861                 }
59862                 me.fireEvent("arrowclick", me, e);
59863                 if (me.arrowHandler) {
59864                     me.arrowHandler.call(me.scope || me, me, e);
59865                 }
59866             } else {
59867                 if (me.enableToggle) {
59868                     me.toggle();
59869                 }
59870                 me.fireEvent("click", me, e);
59871                 if (me.handler) {
59872                     me.handler.call(me.scope || me, me, e);
59873                 }
59874                 me.onBlur();
59875             }
59876         }
59877     }
59878 });
59879
59880
59881 Ext.define('Ext.button.Cycle', {
59882
59883     
59884
59885     alias: 'widget.cycle',
59886
59887     extend: 'Ext.button.Split',
59888     alternateClassName: 'Ext.CycleButton',
59889
59890     
59891
59892     
59893     
59894     
59895     
59896     
59897     
59898
59899     
59900     getButtonText: function(item) {
59901         var me = this,
59902             text = '';
59903
59904         if (item && me.showText === true) {
59905             if (me.prependText) {
59906                 text += me.prependText;
59907             }
59908             text += item.text;
59909             return text;
59910         }
59911         return me.text;
59912     },
59913
59914     
59915     setActiveItem: function(item, suppressEvent) {
59916         var me = this;
59917
59918         if (!Ext.isObject(item)) {
59919             item = me.menu.getComponent(item);
59920         }
59921         if (item) {
59922             if (!me.rendered) {
59923                 me.text = me.getButtonText(item);
59924                 me.iconCls = item.iconCls;
59925             } else {
59926                 me.setText(me.getButtonText(item));
59927                 me.setIconCls(item.iconCls);
59928             }
59929             me.activeItem = item;
59930             if (!item.checked) {
59931                 item.setChecked(true, false);
59932             }
59933             if (me.forceIcon) {
59934                 me.setIconCls(me.forceIcon);
59935             }
59936             if (!suppressEvent) {
59937                 me.fireEvent('change', me, item);
59938             }
59939         }
59940     },
59941
59942     
59943     getActiveItem: function() {
59944         return this.activeItem;
59945     },
59946
59947     
59948     initComponent: function() {
59949         var me = this,
59950             checked = 0,
59951             items;
59952
59953         me.addEvents(
59954             
59955             "change"
59956         );
59957
59958         if (me.changeHandler) {
59959             me.on('change', me.changeHandler, me.scope || me);
59960             delete me.changeHandler;
59961         }
59962
59963         
59964         
59965         items = (me.menu.items||[]).concat(me.items||[]);
59966         me.menu = Ext.applyIf({
59967             cls: Ext.baseCSSPrefix + 'cycle-menu',
59968             items: []
59969         }, me.menu);
59970
59971         
59972         Ext.each(items, function(item, i) {
59973             item = Ext.applyIf({
59974                 group: me.id,
59975                 itemIndex: i,
59976                 checkHandler: me.checkHandler,
59977                 scope: me,
59978                 checked: item.checked || false
59979             }, item);
59980             me.menu.items.push(item);
59981             if (item.checked) {
59982                 checked = i;
59983             }
59984         });
59985         me.itemCount = me.menu.items.length;
59986         me.callParent(arguments);
59987         me.on('click', me.toggleSelected, me);
59988         me.setActiveItem(checked, me);
59989
59990         
59991         if (me.width && me.showText) {
59992             me.addCls(Ext.baseCSSPrefix + 'cycle-fixed-width');
59993         }
59994     },
59995
59996     
59997     checkHandler: function(item, pressed) {
59998         if (pressed) {
59999             this.setActiveItem(item);
60000         }
60001     },
60002
60003     
60004     toggleSelected: function() {
60005         var me = this,
60006             m = me.menu,
60007             checkItem;
60008
60009         checkItem = me.activeItem.next(':not([disabled])') || m.items.getAt(0);
60010         checkItem.setChecked(true);
60011     }
60012 });
60013
60014 Ext.define('Ext.container.ButtonGroup', {
60015     extend: 'Ext.panel.Panel',
60016     alias: 'widget.buttongroup',
60017     alternateClassName: 'Ext.ButtonGroup',
60018
60019     
60020
60021     
60022     baseCls: Ext.baseCSSPrefix + 'btn-group',
60023
60024     
60025     layout: {
60026         type: 'table'
60027     },
60028
60029     defaultType: 'button',
60030
60031     
60032     frame: true,
60033     
60034     frameHeader: false,
60035     
60036     internalDefaults: {removeMode: 'container', hideParent: true},
60037
60038     initComponent : function(){
60039         
60040         var me = this,
60041             cols = me.columns;
60042
60043         me.noTitleCls = me.baseCls + '-notitle';
60044         if (cols) {
60045             me.layout = Ext.apply({}, {columns: cols}, me.layout);
60046         }
60047
60048         if (!me.title) {
60049             me.addCls(me.noTitleCls);
60050         }
60051         me.callParent(arguments);
60052     },
60053
60054     afterLayout: function() {
60055         var me = this;
60056         
60057         me.callParent(arguments);
60058
60059         
60060         
60061         if (me.layout.table && (Ext.isIEQuirks || Ext.isIE6) && !me.width) {
60062             var t = me.getTargetEl();
60063             t.setWidth(me.layout.table.offsetWidth + t.getPadding('lr'));
60064         }
60065     },
60066
60067     afterRender: function() {
60068         var me = this;
60069         
60070         
60071         if (me.header) {
60072             me.header.insert(0, {
60073                 xtype: 'component',
60074                 ui   : me.ui,
60075                 html : '&nbsp;',
60076                 flex : 1
60077             });
60078         }
60079         
60080         me.callParent(arguments);
60081     },
60082     
60083     
60084     onBeforeAdd: function(component) {
60085         if (component.is('button')) {
60086             component.ui = component.ui + '-toolbar';
60087         }
60088         this.callParent(arguments);
60089     },
60090
60091     
60092     applyDefaults: function(c) {
60093         if (!Ext.isString(c)) {
60094             c = this.callParent(arguments);
60095             var d = this.internalDefaults;
60096             if (c.events) {
60097                 Ext.applyIf(c.initialConfig, d);
60098                 Ext.apply(c, d);
60099             } else {
60100                 Ext.applyIf(c, d);
60101             }
60102         }
60103         return c;
60104     }
60105
60106     
60107     
60108     
60109     
60110     
60111 });
60112
60113
60114 Ext.define('Ext.container.Viewport', {
60115     extend: 'Ext.container.Container',
60116     alias: 'widget.viewport',
60117     requires: ['Ext.EventManager'],
60118     alternateClassName: 'Ext.Viewport',
60119
60120     
60121     
60122     
60123     
60124     
60125     
60126     
60127     
60128     
60129     
60130     
60131     
60132
60133     isViewport: true,
60134
60135     ariaRole: 'application',
60136     initComponent : function() {
60137         var me = this,
60138             html = Ext.fly(document.body.parentNode),
60139             el;
60140         me.callParent(arguments);
60141         html.addCls(Ext.baseCSSPrefix + 'viewport');
60142         if (me.autoScroll) {
60143             html.setStyle('overflow', 'auto');
60144         }
60145         me.el = el = Ext.getBody();
60146         el.setHeight = Ext.emptyFn;
60147         el.setWidth = Ext.emptyFn;
60148         el.setSize = Ext.emptyFn;
60149         el.dom.scroll = 'no';
60150         me.allowDomMove = false;
60151         
60152         
60153         Ext.EventManager.onWindowResize(me.fireResize, me);
60154         me.renderTo = me.el;
60155     },
60156
60157     fireResize : function(w, h){
60158         
60159         this.setSize(w, h);
60160         
60161     }
60162 });
60163
60164
60165
60166
60167
60168 Ext.define('Ext.dd.DDTarget', {
60169     extend: 'Ext.dd.DragDrop',
60170     constructor: function(id, sGroup, config) {
60171         if (id) {
60172             this.initTarget(id, sGroup, config);
60173         }
60174     },
60175
60176     
60177     getDragEl: Ext.emptyFn,
60178     
60179     isValidHandleChild: Ext.emptyFn,
60180     
60181     startDrag: Ext.emptyFn,
60182     
60183     endDrag: Ext.emptyFn,
60184     
60185     onDrag: Ext.emptyFn,
60186     
60187     onDragDrop: Ext.emptyFn,
60188     
60189     onDragEnter: Ext.emptyFn,
60190     
60191     onDragOut: Ext.emptyFn,
60192     
60193     onDragOver: Ext.emptyFn,
60194     
60195     onInvalidDrop: Ext.emptyFn,
60196     
60197     onMouseDown: Ext.emptyFn,
60198     
60199     onMouseUp: Ext.emptyFn,
60200     
60201     setXConstraint: Ext.emptyFn,
60202     
60203     setYConstraint: Ext.emptyFn,
60204     
60205     resetConstraints: Ext.emptyFn,
60206     
60207     clearConstraints: Ext.emptyFn,
60208     
60209     clearTicks: Ext.emptyFn,
60210     
60211     setInitPosition: Ext.emptyFn,
60212     
60213     setDragElId: Ext.emptyFn,
60214     
60215     setHandleElId: Ext.emptyFn,
60216     
60217     setOuterHandleElId: Ext.emptyFn,
60218     
60219     addInvalidHandleClass: Ext.emptyFn,
60220     
60221     addInvalidHandleId: Ext.emptyFn,
60222     
60223     addInvalidHandleType: Ext.emptyFn,
60224     
60225     removeInvalidHandleClass: Ext.emptyFn,
60226     
60227     removeInvalidHandleId: Ext.emptyFn,
60228     
60229     removeInvalidHandleType: Ext.emptyFn,
60230
60231     toString: function() {
60232         return ("DDTarget " + this.id);
60233     }
60234 });
60235
60236 Ext.define('Ext.dd.DragTracker', {
60237
60238     uses: ['Ext.util.Region'],
60239
60240     mixins: {
60241         observable: 'Ext.util.Observable'
60242     },
60243
60244     
60245     active: false,
60246
60247     
60248
60249     
60250     trackOver: false,
60251
60252     
60253
60254     
60255
60256     
60257     tolerance: 5,
60258
60259     
60260     autoStart: false,
60261
60262     
60263
60264     
60265
60266     
60267
60268     constructor : function(config){
60269         Ext.apply(this, config);
60270         this.addEvents(
60271             
60272             'mouseover',
60273
60274             
60275             'mouseout',
60276
60277             
60278             'mousedown',
60279
60280             
60281             'mouseup',
60282
60283             
60284             'mousemove',
60285
60286             
60287             'beforedragstart',
60288
60289             
60290             'dragstart',
60291
60292             
60293             'dragend',
60294
60295             
60296             'drag'
60297         );
60298
60299         this.dragRegion = Ext.create('Ext.util.Region', 0,0,0,0);
60300
60301         if (this.el) {
60302             this.initEl(this.el);
60303         }
60304
60305         
60306         this.mixins.observable.constructor.call(this);
60307         if (this.disabled) {
60308             this.disable();
60309         }
60310
60311     },
60312
60313     
60314     initEl: function(el) {
60315         this.el = Ext.get(el);
60316
60317         
60318         this.handle = Ext.get(this.delegate);
60319
60320         
60321         this.delegate = this.handle ? undefined : this.delegate;
60322
60323         if (!this.handle) {
60324             this.handle = this.el;
60325         }
60326
60327         
60328         
60329         this.mon(this.handle, {
60330             mousedown: this.onMouseDown,
60331             delegate: this.delegate,
60332             scope: this
60333         });
60334
60335         
60336         
60337         
60338         if (this.trackOver || this.overCls) {
60339             this.mon(this.handle, {
60340                 mouseover: this.onMouseOver,
60341                 mouseout: this.onMouseOut,
60342                 delegate: this.delegate,
60343                 scope: this
60344             });
60345         }
60346     },
60347
60348     disable: function() {
60349         this.disabled = true;
60350     },
60351
60352     enable: function() {
60353         this.disabled = false;
60354     },
60355
60356     destroy : function() {
60357         this.clearListeners();
60358         delete this.el;
60359     },
60360
60361     
60362     
60363     onMouseOver: function(e, target) {
60364         var me = this;
60365         if (!me.disabled) {
60366             if (Ext.EventManager.contains(e) || me.delegate) {
60367                 me.mouseIsOut = false;
60368                 if (me.overCls) {
60369                     me.el.addCls(me.overCls);
60370                 }
60371                 me.fireEvent('mouseover', me, e, me.delegate ? e.getTarget(me.delegate, target) : me.handle);
60372             }
60373         }
60374     },
60375
60376     
60377     
60378     onMouseOut: function(e) {
60379         if (this.mouseIsDown) {
60380             this.mouseIsOut = true;
60381         } else {
60382             if (this.overCls) {
60383                 this.el.removeCls(this.overCls);
60384             }
60385             this.fireEvent('mouseout', this, e);
60386         }
60387     },
60388
60389     onMouseDown: function(e, target){
60390         
60391         if (this.disabled ||e.dragTracked) {
60392             return;
60393         }
60394
60395         
60396         this.dragTarget = this.delegate ? target : this.handle.dom;
60397         this.startXY = this.lastXY = e.getXY();
60398         this.startRegion = Ext.fly(this.dragTarget).getRegion();
60399
60400         if (this.fireEvent('mousedown', this, e) === false ||
60401             this.fireEvent('beforedragstart', this, e) === false ||
60402             this.onBeforeStart(e) === false) {
60403             return;
60404         }
60405
60406         
60407         
60408         this.mouseIsDown = true;
60409
60410         
60411         e.dragTracked = true;
60412
60413         if (this.preventDefault !== false) {
60414             e.preventDefault();
60415         }
60416         Ext.getDoc().on({
60417             scope: this,
60418             mouseup: this.onMouseUp,
60419             mousemove: this.onMouseMove,
60420             selectstart: this.stopSelect
60421         });
60422         if (this.autoStart) {
60423             this.timer =  Ext.defer(this.triggerStart, this.autoStart === true ? 1000 : this.autoStart, this, [e]);
60424         }
60425     },
60426
60427     onMouseMove: function(e, target){
60428         
60429         
60430         if (this.active && Ext.isIE && !e.browserEvent.button) {
60431             e.preventDefault();
60432             this.onMouseUp(e);
60433             return;
60434         }
60435
60436         e.preventDefault();
60437         var xy = e.getXY(),
60438             s = this.startXY;
60439
60440         this.lastXY = xy;
60441         if (!this.active) {
60442             if (Math.max(Math.abs(s[0]-xy[0]), Math.abs(s[1]-xy[1])) > this.tolerance) {
60443                 this.triggerStart(e);
60444             } else {
60445                 return;
60446             }
60447         }
60448
60449         
60450         if (this.fireEvent('mousemove', this, e) === false) {
60451             this.onMouseUp(e);
60452         } else {
60453             this.onDrag(e);
60454             this.fireEvent('drag', this, e);
60455         }
60456     },
60457
60458     onMouseUp: function(e) {
60459         
60460         
60461         this.mouseIsDown = false;
60462
60463         
60464         delete e.dragTracked;
60465
60466         
60467         if (this.mouseIsOut) {
60468             this.mouseIsOut = false;
60469             this.onMouseOut(e);
60470         }
60471         e.preventDefault();
60472         this.fireEvent('mouseup', this, e);
60473         this.endDrag(e);
60474     },
60475
60476     
60477     endDrag: function(e) {
60478         var doc = Ext.getDoc(),
60479         wasActive = this.active;
60480
60481         doc.un('mousemove', this.onMouseMove, this);
60482         doc.un('mouseup', this.onMouseUp, this);
60483         doc.un('selectstart', this.stopSelect, this);
60484         this.clearStart();
60485         this.active = false;
60486         if (wasActive) {
60487             this.onEnd(e);
60488             this.fireEvent('dragend', this, e);
60489         }
60490         
60491         delete this._constrainRegion;
60492     },
60493
60494     triggerStart: function(e) {
60495         this.clearStart();
60496         this.active = true;
60497         this.onStart(e);
60498         this.fireEvent('dragstart', this, e);
60499     },
60500
60501     clearStart : function() {
60502         if (this.timer) {
60503             clearTimeout(this.timer);
60504             delete this.timer;
60505         }
60506     },
60507
60508     stopSelect : function(e) {
60509         e.stopEvent();
60510         return false;
60511     },
60512
60513     
60514     onBeforeStart : function(e) {
60515
60516     },
60517
60518     
60519     onStart : function(xy) {
60520
60521     },
60522
60523     
60524     onDrag : function(e) {
60525
60526     },
60527
60528     
60529     onEnd : function(e) {
60530
60531     },
60532
60533     
60534     getDragTarget : function(){
60535         return this.dragTarget;
60536     },
60537
60538     
60539     getDragCt : function(){
60540         return this.el;
60541     },
60542
60543     
60544     getConstrainRegion: function() {
60545         if (this.constrainTo) {
60546             if (this.constrainTo instanceof Ext.util.Region) {
60547                 return this.constrainTo;
60548             }
60549             if (!this._constrainRegion) {
60550                 this._constrainRegion = Ext.fly(this.constrainTo).getViewRegion();
60551             }
60552         } else {
60553             if (!this._constrainRegion) {
60554                 this._constrainRegion = this.getDragCt().getViewRegion();
60555             }
60556         }
60557         return this._constrainRegion;
60558     },
60559
60560     getXY : function(constrain){
60561         return constrain ? this.constrainModes[constrain](this, this.lastXY) : this.lastXY;
60562     },
60563
60564     
60565     getOffset : function(constrain){
60566         var xy = this.getXY(constrain),
60567             s = this.startXY;
60568
60569         return [xy[0]-s[0], xy[1]-s[1]];
60570     },
60571
60572     constrainModes: {
60573         
60574         point: function(me, xy) {
60575             var dr = me.dragRegion,
60576                 constrainTo = me.getConstrainRegion();
60577
60578             
60579             if (!constrainTo) {
60580                 return xy;
60581             }
60582
60583             dr.x = dr.left = dr[0] = dr.right = xy[0];
60584             dr.y = dr.top = dr[1] = dr.bottom = xy[1];
60585             dr.constrainTo(constrainTo);
60586
60587             return [dr.left, dr.top];
60588         },
60589
60590         
60591         dragTarget: function(me, xy) {
60592             var s = me.startXY,
60593                 dr = me.startRegion.copy(),
60594                 constrainTo = me.getConstrainRegion(),
60595                 adjust;
60596
60597             
60598             if (!constrainTo) {
60599                 return xy;
60600             }
60601
60602             
60603             
60604             
60605             dr.translateBy(xy[0]-s[0], xy[1]-s[1]);
60606
60607             
60608             if (dr.right > constrainTo.right) {
60609                 xy[0] += adjust = (constrainTo.right - dr.right);    
60610                 dr.left += adjust;
60611             }
60612             if (dr.left < constrainTo.left) {
60613                 xy[0] += (constrainTo.left - dr.left);      
60614             }
60615
60616             
60617             if (dr.bottom > constrainTo.bottom) {
60618                 xy[1] += adjust = (constrainTo.bottom - dr.bottom);  
60619                 dr.top += adjust;
60620             }
60621             if (dr.top < constrainTo.top) {
60622                 xy[1] += (constrainTo.top - dr.top);        
60623             }
60624             return xy;
60625         }
60626     }
60627 });
60628
60629 Ext.define('Ext.dd.DragZone', {
60630
60631     extend: 'Ext.dd.DragSource',
60632
60633     constructor : function(el, config){
60634         this.callParent([el, config]);
60635         if (this.containerScroll) {
60636             Ext.dd.ScrollManager.register(this.el);
60637         }
60638     },
60639
60640     
60641
60642     
60643
60644     
60645     getDragData : function(e){
60646         return Ext.dd.Registry.getHandleFromEvent(e);
60647     },
60648
60649     
60650     onInitDrag : function(x, y){
60651         this.proxy.update(this.dragData.ddel.cloneNode(true));
60652         this.onStartDrag(x, y);
60653         return true;
60654     },
60655
60656     
60657     afterRepair : function(){
60658         var me = this;
60659         if (Ext.enableFx) {
60660             Ext.fly(me.dragData.ddel).highlight(me.repairHighlightColor);
60661         }
60662         me.dragging = false;
60663     },
60664
60665     
60666     getRepairXY : function(e){
60667         return Ext.core.Element.fly(this.dragData.ddel).getXY();
60668     },
60669
60670     destroy : function(){
60671         this.callParent();
60672         if (this.containerScroll) {
60673             Ext.dd.ScrollManager.unregister(this.el);
60674         }
60675     }
60676 });
60677
60678
60679 Ext.define('Ext.dd.ScrollManager', {
60680     singleton: true,
60681     requires: [
60682         'Ext.dd.DragDropManager'
60683     ],
60684
60685     constructor: function() {
60686         var ddm = Ext.dd.DragDropManager;
60687         ddm.fireEvents = Ext.Function.createSequence(ddm.fireEvents, this.onFire, this);
60688         ddm.stopDrag = Ext.Function.createSequence(ddm.stopDrag, this.onStop, this);
60689         this.doScroll = Ext.Function.bind(this.doScroll, this);
60690         this.ddmInstance = ddm;
60691         this.els = {};
60692         this.dragEl = null;
60693         this.proc = {};
60694     },
60695
60696     onStop: function(e){
60697         var sm = Ext.dd.ScrollManager;
60698         sm.dragEl = null;
60699         sm.clearProc();
60700     },
60701
60702     triggerRefresh: function() {
60703         if (this.ddmInstance.dragCurrent) {
60704             this.ddmInstance.refreshCache(this.ddmInstance.dragCurrent.groups);
60705         }
60706     },
60707
60708     doScroll: function() {
60709         if (this.ddmInstance.dragCurrent) {
60710             var proc   = this.proc,
60711                 procEl = proc.el,
60712                 ddScrollConfig = proc.el.ddScrollConfig,
60713                 inc = ddScrollConfig ? ddScrollConfig.increment : this.increment;
60714
60715             if (!this.animate) {
60716                 if (procEl.scroll(proc.dir, inc)) {
60717                     this.triggerRefresh();
60718                 }
60719             } else {
60720                 procEl.scroll(proc.dir, inc, true, this.animDuration, this.triggerRefresh);
60721             }
60722         }
60723     },
60724
60725     clearProc: function() {
60726         var proc = this.proc;
60727         if (proc.id) {
60728             clearInterval(proc.id);
60729         }
60730         proc.id = 0;
60731         proc.el = null;
60732         proc.dir = "";
60733     },
60734
60735     startProc: function(el, dir) {
60736         this.clearProc();
60737         this.proc.el = el;
60738         this.proc.dir = dir;
60739         var group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined,
60740             freq  = (el.ddScrollConfig && el.ddScrollConfig.frequency)
60741                   ? el.ddScrollConfig.frequency
60742                   : this.frequency;
60743
60744         if (group === undefined || this.ddmInstance.dragCurrent.ddGroup == group) {
60745             this.proc.id = setInterval(this.doScroll, freq);
60746         }
60747     },
60748
60749     onFire: function(e, isDrop) {
60750         if (isDrop || !this.ddmInstance.dragCurrent) {
60751             return;
60752         }
60753         if (!this.dragEl || this.dragEl != this.ddmInstance.dragCurrent) {
60754             this.dragEl = this.ddmInstance.dragCurrent;
60755             
60756             this.refreshCache();
60757         }
60758
60759         var xy = e.getXY(),
60760             pt = e.getPoint(),
60761             proc = this.proc,
60762             els = this.els;
60763
60764         for (var id in els) {
60765             var el = els[id], r = el._region;
60766             var c = el.ddScrollConfig ? el.ddScrollConfig : this;
60767             if (r && r.contains(pt) && el.isScrollable()) {
60768                 if (r.bottom - pt.y <= c.vthresh) {
60769                     if(proc.el != el){
60770                         this.startProc(el, "down");
60771                     }
60772                     return;
60773                 }else if (r.right - pt.x <= c.hthresh) {
60774                     if (proc.el != el) {
60775                         this.startProc(el, "left");
60776                     }
60777                     return;
60778                 } else if(pt.y - r.top <= c.vthresh) {
60779                     if (proc.el != el) {
60780                         this.startProc(el, "up");
60781                     }
60782                     return;
60783                 } else if(pt.x - r.left <= c.hthresh) {
60784                     if (proc.el != el) {
60785                         this.startProc(el, "right");
60786                     }
60787                     return;
60788                 }
60789             }
60790         }
60791         this.clearProc();
60792     },
60793
60794     
60795     register : function(el){
60796         if (Ext.isArray(el)) {
60797             for(var i = 0, len = el.length; i < len; i++) {
60798                     this.register(el[i]);
60799             }
60800         } else {
60801             el = Ext.get(el);
60802             this.els[el.id] = el;
60803         }
60804     },
60805
60806     
60807     unregister : function(el){
60808         if(Ext.isArray(el)){
60809             for (var i = 0, len = el.length; i < len; i++) {
60810                 this.unregister(el[i]);
60811             }
60812         }else{
60813             el = Ext.get(el);
60814             delete this.els[el.id];
60815         }
60816     },
60817
60818     
60819     vthresh : 25,
60820     
60821     hthresh : 25,
60822
60823     
60824     increment : 100,
60825
60826     
60827     frequency : 500,
60828
60829     
60830     animate: true,
60831
60832     
60833     animDuration: 0.4,
60834
60835     
60836     ddGroup: undefined,
60837
60838     
60839     refreshCache : function(){
60840         var els = this.els,
60841             id;
60842         for (id in els) {
60843             if(typeof els[id] == 'object'){ 
60844                 els[id]._region = els[id].getRegion();
60845             }
60846         }
60847     }
60848 });
60849
60850
60851 Ext.define('Ext.dd.DropTarget', {
60852     extend: 'Ext.dd.DDTarget',
60853     requires: ['Ext.dd.ScrollManager'],
60854
60855     constructor : function(el, config){
60856         this.el = Ext.get(el);
60857
60858         Ext.apply(this, config);
60859
60860         if(this.containerScroll){
60861             Ext.dd.ScrollManager.register(this.el);
60862         }
60863
60864         this.callParent([this.el.dom, this.ddGroup || this.group,
60865               {isTarget: true}]);
60866     },
60867
60868     
60869     
60870     
60871     dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok',
60872     
60873     dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop',
60874
60875     
60876     isTarget : true,
60877
60878     
60879     isNotifyTarget : true,
60880
60881     
60882     notifyEnter : function(dd, e, data){
60883         if(this.overClass){
60884             this.el.addCls(this.overClass);
60885         }
60886         return this.dropAllowed;
60887     },
60888
60889     
60890     notifyOver : function(dd, e, data){
60891         return this.dropAllowed;
60892     },
60893
60894     
60895     notifyOut : function(dd, e, data){
60896         if(this.overClass){
60897             this.el.removeCls(this.overClass);
60898         }
60899     },
60900
60901     
60902     notifyDrop : function(dd, e, data){
60903         return false;
60904     },
60905
60906     destroy : function(){
60907         this.callParent();
60908         if(this.containerScroll){
60909             Ext.dd.ScrollManager.unregister(this.el);
60910         }
60911     }
60912 });
60913
60914
60915 Ext.define('Ext.dd.Registry', {
60916     singleton: true,
60917     constructor: function() {
60918         this.elements = {}; 
60919         this.handles = {}; 
60920         this.autoIdSeed = 0;
60921     },
60922     
60923     getId: function(el, autogen){
60924         if(typeof el == "string"){
60925             return el;
60926         }
60927         var id = el.id;
60928         if(!id && autogen !== false){
60929             id = "extdd-" + (++this.autoIdSeed);
60930             el.id = id;
60931         }
60932         return id;
60933     },
60934     
60935     
60936     register : function(el, data){
60937         data = data || {};
60938         if (typeof el == "string") {
60939             el = document.getElementById(el);
60940         }
60941         data.ddel = el;
60942         this.elements[this.getId(el)] = data;
60943         if (data.isHandle !== false) {
60944             this.handles[data.ddel.id] = data;
60945         }
60946         if (data.handles) {
60947             var hs = data.handles;
60948             for (var i = 0, len = hs.length; i < len; i++) {
60949                 this.handles[this.getId(hs[i])] = data;
60950             }
60951         }
60952     },
60953
60954     
60955     unregister : function(el){
60956         var id = this.getId(el, false);
60957         var data = this.elements[id];
60958         if(data){
60959             delete this.elements[id];
60960             if(data.handles){
60961                 var hs = data.handles;
60962                 for (var i = 0, len = hs.length; i < len; i++) {
60963                     delete this.handles[this.getId(hs[i], false)];
60964                 }
60965             }
60966         }
60967     },
60968
60969     
60970     getHandle : function(id){
60971         if(typeof id != "string"){ 
60972             id = id.id;
60973         }
60974         return this.handles[id];
60975     },
60976
60977     
60978     getHandleFromEvent : function(e){
60979         var t = e.getTarget();
60980         return t ? this.handles[t.id] : null;
60981     },
60982
60983     
60984     getTarget : function(id){
60985         if(typeof id != "string"){ 
60986             id = id.id;
60987         }
60988         return this.elements[id];
60989     },
60990
60991     
60992     getTargetFromEvent : function(e){
60993         var t = e.getTarget();
60994         return t ? this.elements[t.id] || this.handles[t.id] : null;
60995     }
60996 });
60997
60998 Ext.define('Ext.dd.DropZone', {
60999     extend: 'Ext.dd.DropTarget',
61000     requires: ['Ext.dd.Registry'],
61001
61002     
61003     getTargetFromEvent : function(e){
61004         return Ext.dd.Registry.getTargetFromEvent(e);
61005     },
61006
61007     
61008     onNodeEnter : function(n, dd, e, data){
61009         
61010     },
61011
61012     
61013     onNodeOver : function(n, dd, e, data){
61014         return this.dropAllowed;
61015     },
61016
61017     
61018     onNodeOut : function(n, dd, e, data){
61019         
61020     },
61021
61022     
61023     onNodeDrop : function(n, dd, e, data){
61024         return false;
61025     },
61026
61027     
61028     onContainerOver : function(dd, e, data){
61029         return this.dropNotAllowed;
61030     },
61031
61032     
61033     onContainerDrop : function(dd, e, data){
61034         return false;
61035     },
61036
61037     
61038     notifyEnter : function(dd, e, data){
61039         return this.dropNotAllowed;
61040     },
61041
61042     
61043     notifyOver : function(dd, e, data){
61044         var n = this.getTargetFromEvent(e);
61045         if(!n) { 
61046             if(this.lastOverNode){
61047                 this.onNodeOut(this.lastOverNode, dd, e, data);
61048                 this.lastOverNode = null;
61049             }
61050             return this.onContainerOver(dd, e, data);
61051         }
61052         if(this.lastOverNode != n){
61053             if(this.lastOverNode){
61054                 this.onNodeOut(this.lastOverNode, dd, e, data);
61055             }
61056             this.onNodeEnter(n, dd, e, data);
61057             this.lastOverNode = n;
61058         }
61059         return this.onNodeOver(n, dd, e, data);
61060     },
61061
61062     
61063     notifyOut : function(dd, e, data){
61064         if(this.lastOverNode){
61065             this.onNodeOut(this.lastOverNode, dd, e, data);
61066             this.lastOverNode = null;
61067         }
61068     },
61069
61070     
61071     notifyDrop : function(dd, e, data){
61072         if(this.lastOverNode){
61073             this.onNodeOut(this.lastOverNode, dd, e, data);
61074             this.lastOverNode = null;
61075         }
61076         var n = this.getTargetFromEvent(e);
61077         return n ?
61078             this.onNodeDrop(n, dd, e, data) :
61079             this.onContainerDrop(dd, e, data);
61080     },
61081
61082     
61083     triggerCacheRefresh : function() {
61084         Ext.dd.DDM.refreshCache(this.groups);
61085     }
61086 });
61087
61088 Ext.define('Ext.flash.Component', {
61089     extend: 'Ext.Component',
61090     alternateClassName: 'Ext.FlashComponent',
61091     alias: 'widget.flash',
61092
61093     
61094     flashVersion : '9.0.115',
61095
61096     
61097     backgroundColor: '#ffffff',
61098
61099     
61100     wmode: 'opaque',
61101
61102     
61103
61104     
61105
61106     
61107
61108     
61109
61110     
61111     swfWidth: '100%',
61112
61113     
61114     swfHeight: '100%',
61115
61116     
61117     expressInstall: false,
61118
61119     
61120
61121     
61122     renderTpl: ['<div id="{swfId}"></div>'],
61123
61124     initComponent: function() {
61125         if (!('swfobject' in window)) {
61126             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/');
61127         }
61128         if (!this.url) {
61129             Ext.Error.raise('The "url" config is required for Ext.flash.Component');
61130         }
61131
61132         this.callParent();
61133         this.addEvents(
61134             
61135             'success',
61136
61137             
61138             'failure'
61139         );
61140     },
61141
61142     onRender: function() {
61143         var me = this,
61144             params, vars, undef,
61145             swfId = me.getSwfId();
61146
61147         me.renderData.swfId = swfId;
61148
61149         me.callParent(arguments);
61150
61151         params = Ext.apply({
61152             allowScriptAccess: 'always',
61153             bgcolor: me.backgroundColor,
61154             wmode: me.wmode
61155         }, me.flashParams);
61156
61157         vars = Ext.apply({
61158             allowedDomain: document.location.hostname
61159         }, me.flashVars);
61160
61161         new swfobject.embedSWF(
61162             me.url,
61163             swfId,
61164             me.swfWidth,
61165             me.swfHeight,
61166             me.flashVersion,
61167             me.expressInstall ? me.statics.EXPRESS_INSTALL_URL : undef,
61168             vars,
61169             params,
61170             me.flashAttributes,
61171             Ext.bind(me.swfCallback, me)
61172         );
61173     },
61174
61175     
61176     swfCallback: function(e) {
61177         var me = this;
61178         if (e.success) {
61179             me.swf = Ext.get(e.ref);
61180             me.onSuccess();
61181             me.fireEvent('success', me);
61182         } else {
61183             me.onFailure();
61184             me.fireEvent('failure', me);
61185         }
61186     },
61187
61188     
61189     getSwfId: function() {
61190         return this.swfId || (this.swfId = "extswf" + this.getAutoId());
61191     },
61192
61193     onSuccess: function() {
61194         
61195         
61196         this.swf.setStyle('visibility', 'inherit');
61197     },
61198
61199     onFailure: Ext.emptyFn,
61200
61201     beforeDestroy: function() {
61202         var me = this,
61203             swf = me.swf;
61204         if (swf) {
61205             swfobject.removeSWF(me.getSwfId());
61206             Ext.destroy(swf);
61207             delete me.swf;
61208         }
61209         me.callParent();
61210     },
61211
61212     statics: {
61213         
61214         EXPRESS_INSTALL_URL: 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf'
61215     }
61216 });
61217
61218
61219 Ext.define('Ext.form.action.Action', {
61220     alternateClassName: 'Ext.form.Action',
61221
61222     
61223
61224     
61225
61226     
61227
61228     
61229
61230     
61231
61232     
61233
61234     
61235
61236     
61237
61238     
61239
61240     
61241
61242     
61243
61244     
61245
61246     
61247
61248     
61249
61250     
61251
61252     
61253
61254     
61255
61256
61257
61258     constructor: function(config) {
61259         if (config) {
61260             Ext.apply(this, config);
61261         }
61262
61263         
61264         var params = config.params;
61265         if (Ext.isString(params)) {
61266             this.params = Ext.Object.fromQueryString(params);
61267         }
61268     },
61269
61270     
61271     run: Ext.emptyFn,
61272
61273     
61274
61275     
61276
61277     
61278     onFailure : function(response){
61279         this.response = response;
61280         this.failureType = Ext.form.action.Action.CONNECT_FAILURE;
61281         this.form.afterAction(this, false);
61282     },
61283
61284     
61285     processResponse : function(response){
61286         this.response = response;
61287         if (!response.responseText && !response.responseXML) {
61288             return true;
61289         }
61290         return (this.result = this.handleResponse(response));
61291     },
61292
61293     
61294     getUrl: function() {
61295         return this.url || this.form.url;
61296     },
61297
61298     
61299     getMethod: function() {
61300         return (this.method || this.form.method || 'POST').toUpperCase();
61301     },
61302
61303     
61304     getParams: function() {
61305         return Ext.apply({}, this.params, this.form.baseParams);
61306     },
61307
61308     
61309     createCallback: function() {
61310         var me = this,
61311             undef,
61312             form = me.form;
61313         return {
61314             success: me.onSuccess,
61315             failure: me.onFailure,
61316             scope: me,
61317             timeout: (this.timeout * 1000) || (form.timeout * 1000),
61318             upload: form.fileUpload ? me.onSuccess : undef
61319         };
61320     },
61321
61322     statics: {
61323         
61324         CLIENT_INVALID: 'client',
61325
61326         
61327         SERVER_INVALID: 'server',
61328
61329         
61330         CONNECT_FAILURE: 'connect',
61331
61332         
61333         LOAD_FAILURE: 'load'
61334
61335
61336     }
61337 });
61338
61339
61340 Ext.define('Ext.form.action.Submit', {
61341     extend:'Ext.form.action.Action',
61342     alternateClassName: 'Ext.form.Action.Submit',
61343     alias: 'formaction.submit',
61344
61345     type: 'submit',
61346
61347     
61348
61349     
61350     run : function(){
61351         var form = this.form;
61352         if (this.clientValidation === false || form.isValid()) {
61353             this.doSubmit();
61354         } else {
61355             
61356             this.failureType = Ext.form.action.Action.CLIENT_INVALID;
61357             form.afterAction(this, false);
61358         }
61359     },
61360
61361     
61362     doSubmit: function() {
61363         var formEl,
61364             ajaxOptions = Ext.apply(this.createCallback(), {
61365                 url: this.getUrl(),
61366                 method: this.getMethod(),
61367                 headers: this.headers
61368             });
61369
61370         
61371         
61372         if (this.form.hasUpload()) {
61373             formEl = ajaxOptions.form = this.buildForm();
61374             ajaxOptions.isUpload = true;
61375         } else {
61376             ajaxOptions.params = this.getParams();
61377         }
61378
61379         Ext.Ajax.request(ajaxOptions);
61380
61381         if (formEl) {
61382             Ext.removeNode(formEl);
61383         }
61384     },
61385
61386     
61387     getParams: function() {
61388         var nope = false,
61389             configParams = this.callParent(),
61390             fieldParams = this.form.getValues(nope, nope, this.submitEmptyText !== nope);
61391         return Ext.apply({}, fieldParams, configParams);
61392     },
61393
61394     
61395     buildForm: function() {
61396         var fieldsSpec = [],
61397             formSpec,
61398             formEl,
61399             basicForm = this.form,
61400             params = this.getParams(),
61401             uploadFields = [];
61402
61403         basicForm.getFields().each(function(field) {
61404             if (field.isFileUpload()) {
61405                 uploadFields.push(field);
61406             }
61407         });
61408
61409         function addField(name, val) {
61410             fieldsSpec.push({
61411                 tag: 'input',
61412                 type: 'hidden',
61413                 name: name,
61414                 value: Ext.String.htmlEncode(val)
61415             });
61416         }
61417
61418         
61419         Ext.iterate(params, function(key, val) {
61420             if (Ext.isArray(val)) {
61421                 Ext.each(val, function(v) {
61422                     addField(key, v);
61423                 });
61424             } else {
61425                 addField(key, val);
61426             }
61427         });
61428
61429         formSpec = {
61430             tag: 'form',
61431             action: this.getUrl(),
61432             method: this.getMethod(),
61433             target: this.target || '_self',
61434             style: 'display:none',
61435             cn: fieldsSpec
61436         };
61437
61438         
61439         if (uploadFields.length) {
61440             formSpec.encoding = formSpec.enctype = 'multipart/form-data';
61441         }
61442
61443         
61444         formEl = Ext.core.DomHelper.append(Ext.getBody(), formSpec);
61445
61446         
61447         
61448         
61449         Ext.Array.each(uploadFields, function(field) {
61450             if (field.rendered) { 
61451                 formEl.appendChild(field.extractFileInput());
61452             }
61453         });
61454
61455         return formEl;
61456     },
61457
61458
61459
61460     
61461     onSuccess: function(response) {
61462         var form = this.form,
61463             success = true,
61464             result = this.processResponse(response);
61465         if (result !== true && !result.success) {
61466             if (result.errors) {
61467                 form.markInvalid(result.errors);
61468             }
61469             this.failureType = Ext.form.action.Action.SERVER_INVALID;
61470             success = false;
61471         }
61472         form.afterAction(this, success);
61473     },
61474
61475     
61476     handleResponse: function(response) {
61477         var form = this.form,
61478             errorReader = form.errorReader,
61479             rs, errors, i, len, records;
61480         if (errorReader) {
61481             rs = errorReader.read(response);
61482             records = rs.records;
61483             errors = [];
61484             if (records) {
61485                 for(i = 0, len = records.length; i < len; i++) {
61486                     errors[i] = records[i].data;
61487                 }
61488             }
61489             if (errors.length < 1) {
61490                 errors = null;
61491             }
61492             return {
61493                 success : rs.success,
61494                 errors : errors
61495             };
61496         }
61497         return Ext.decode(response.responseText);
61498     }
61499 });
61500
61501
61502 Ext.define('Ext.util.ComponentDragger', {
61503
61504     
61505
61506     
61507
61508     
61509
61510     extend: 'Ext.dd.DragTracker',
61511
61512     autoStart: 500,
61513
61514     constructor: function(comp, config) {
61515         this.comp = comp;
61516         this.initialConstrainTo = config.constrainTo;
61517         this.callParent([ config ]);
61518     },
61519
61520     onStart: function(e) {
61521         var me = this,
61522             comp = me.comp;
61523
61524         
61525         this.startPosition = comp.getPosition();
61526
61527         
61528         
61529         if (comp.ghost && !comp.liveDrag) {
61530              me.proxy = comp.ghost();
61531              me.dragTarget = me.proxy.header.el;
61532         }
61533
61534         
61535         if (me.constrain || me.constrainDelegate) {
61536             me.constrainTo = me.calculateConstrainRegion();
61537         }
61538     },
61539
61540     calculateConstrainRegion: function() {
61541         var me = this,
61542             comp = me.comp,
61543             c = me.initialConstrainTo,
61544             delegateRegion,
61545             elRegion,
61546             shadowSize = comp.el.shadow ? comp.el.shadow.offset : 0;
61547
61548         
61549         if (!(c instanceof Ext.util.Region)) {
61550             c =  Ext.fly(c).getViewRegion();
61551         }
61552
61553         
61554         if (shadowSize) {
61555             c.adjust(0, -shadowSize, -shadowSize, shadowSize);
61556         }
61557
61558         
61559         
61560         
61561         if (!me.constrainDelegate) {
61562             delegateRegion = Ext.fly(me.dragTarget).getRegion();
61563             elRegion = me.proxy ? me.proxy.el.getRegion() : comp.el.getRegion();
61564
61565             c.adjust(
61566                 delegateRegion.top - elRegion.top,
61567                 delegateRegion.right - elRegion.right,
61568                 delegateRegion.bottom - elRegion.bottom,
61569                 delegateRegion.left - elRegion.left
61570             );
61571         }
61572         return c;
61573     },
61574
61575     
61576     onDrag: function(e) {
61577         var me = this,
61578             comp = (me.proxy && !me.comp.liveDrag) ? me.proxy : me.comp,
61579             offset = me.getOffset(me.constrain || me.constrainDelegate ? 'dragTarget' : null);
61580
61581         comp.setPosition(me.startPosition[0] + offset[0], me.startPosition[1] + offset[1]);
61582     },
61583
61584     onEnd: function(e) {
61585         if (this.proxy && !this.comp.liveDrag) {
61586             this.comp.unghost();
61587         }
61588     }
61589 });
61590
61591 Ext.define("Ext.form.Labelable", {
61592     requires: ['Ext.XTemplate'],
61593
61594     
61595     labelableRenderTpl: [
61596         '<tpl if="!hideLabel && !(!fieldLabel && hideEmptyLabel)">',
61597             '<label<tpl if="inputId"> for="{inputId}"</tpl> class="{labelCls}"<tpl if="labelStyle"> style="{labelStyle}"</tpl>>',
61598                 '<tpl if="fieldLabel">{fieldLabel}{labelSeparator}</tpl>',
61599             '</label>',
61600         '</tpl>',
61601         '<div class="{baseBodyCls} {fieldBodyCls}"<tpl if="inputId"> id="{baseBodyCls}-{inputId}"</tpl> role="presentation">{subTplMarkup}</div>',
61602         '<div class="{errorMsgCls}" style="display:none"></div>',
61603         '<div class="{clearCls}" role="presentation"><!-- --></div>',
61604         {
61605             compiled: true,
61606             disableFormats: true
61607         }
61608     ],
61609
61610     
61611     activeErrorsTpl: [
61612         '<tpl if="errors && errors.length">',
61613             '<ul><tpl for="errors"><li<tpl if="xindex == xcount"> class="last"</tpl>>{.}</li></tpl></ul>',
61614         '</tpl>'
61615     ],
61616
61617     
61618     isFieldLabelable: true,
61619
61620     
61621     formItemCls: Ext.baseCSSPrefix + 'form-item',
61622
61623     
61624     labelCls: Ext.baseCSSPrefix + 'form-item-label',
61625
61626     
61627     errorMsgCls: Ext.baseCSSPrefix + 'form-error-msg',
61628
61629     
61630     baseBodyCls: Ext.baseCSSPrefix + 'form-item-body',
61631
61632     
61633     fieldBodyCls: '',
61634
61635     
61636     clearCls: Ext.baseCSSPrefix + 'clear',
61637
61638     
61639     invalidCls : Ext.baseCSSPrefix + 'form-invalid',
61640
61641     
61642     fieldLabel: undefined,
61643
61644     
61645     labelAlign : 'left',
61646
61647     
61648     labelWidth: 100,
61649
61650     
61651     labelPad : 5,
61652
61653     
61654     labelSeparator : ':',
61655
61656     
61657
61658     
61659     hideLabel: false,
61660
61661     
61662     hideEmptyLabel: true,
61663
61664     
61665     preventMark: false,
61666
61667     
61668     autoFitErrors: true,
61669
61670     
61671     msgTarget: 'qtip',
61672
61673     
61674
61675
61676     
61677     initLabelable: function() {
61678         this.addCls(this.formItemCls);
61679
61680         this.addEvents(
61681             
61682             'errorchange'
61683         );
61684     },
61685
61686     
61687     getFieldLabel: function() {
61688         return this.fieldLabel || '';
61689     },
61690
61691     
61692     getLabelableRenderData: function() {
61693         var me = this,
61694             labelAlign = me.labelAlign,
61695             labelPad = me.labelPad,
61696             labelStyle;
61697
61698         
61699         
61700         if (labelAlign === 'top') {
61701             labelStyle = 'margin-bottom:' + labelPad + 'px;';
61702         } else {
61703             labelStyle = 'margin-right:' + labelPad + 'px;';
61704             
61705             if (Ext.isBorderBox) {
61706                 labelStyle += 'width:' + me.labelWidth + 'px;';
61707             }
61708         }
61709
61710         return Ext.copyTo(
61711             {
61712                 inputId: me.getInputId(),
61713                 fieldLabel: me.getFieldLabel(),
61714                 labelStyle: labelStyle + (me.labelStyle || ''),
61715                 subTplMarkup: me.getSubTplMarkup()
61716             },
61717             me,
61718             'hideLabel,hideEmptyLabel,labelCls,fieldBodyCls,baseBodyCls,errorMsgCls,clearCls,labelSeparator',
61719             true
61720         );
61721     },
61722
61723     
61724     getLabelableSelectors: function() {
61725         return {
61726             
61727             labelEl: 'label.' + this.labelCls,
61728
61729             
61730             bodyEl: '.' + this.baseBodyCls,
61731
61732             
61733             errorEl: '.' + this.errorMsgCls
61734         };
61735     },
61736
61737     
61738     getSubTplMarkup: function() {
61739         return '';
61740     },
61741
61742     
61743     getInputId: function() {
61744         return '';
61745     },
61746
61747     
61748     getActiveError : function() {
61749         return this.activeError || '';
61750     },
61751
61752     
61753     hasActiveError: function() {
61754         return !!this.getActiveError();
61755     },
61756
61757     
61758     setActiveError: function(msg) {
61759         this.activeError = msg;
61760         this.activeErrors = [msg];
61761         this.renderActiveError();
61762     },
61763
61764     
61765     getActiveErrors: function() {
61766         return this.activeErrors || [];
61767     },
61768
61769     
61770     setActiveErrors: function(errors) {
61771         this.activeErrors = errors;
61772         this.activeError = this.getTpl('activeErrorsTpl').apply({errors: errors});
61773         this.renderActiveError();
61774     },
61775
61776     
61777     unsetActiveError: function() {
61778         delete this.activeError;
61779         delete this.activeErrors;
61780         this.renderActiveError();
61781     },
61782
61783     
61784     renderActiveError: function() {
61785         var me = this,
61786             activeError = me.getActiveError(),
61787             hasError = !!activeError;
61788
61789         if (activeError !== me.lastActiveError) {
61790             me.fireEvent('errorchange', me, activeError);
61791             me.lastActiveError = activeError;
61792         }
61793
61794         if (me.rendered && !me.isDestroyed && !me.preventMark) {
61795             
61796             me.el[hasError ? 'addCls' : 'removeCls'](me.invalidCls);
61797
61798             
61799             me.getActionEl().dom.setAttribute('aria-invalid', hasError);
61800
61801             
61802             me.errorEl.dom.innerHTML = activeError;
61803         }
61804     },
61805
61806     
61807     setFieldDefaults: function(defaults) {
61808         var me = this;
61809         Ext.iterate(defaults, function(key, val) {
61810             if (!me.hasOwnProperty(key)) {
61811                 me[key] = val;
61812             }
61813         });
61814     },
61815
61816     
61817     getBodyNaturalWidth: function() {
61818         return this.bodyEl.getWidth();
61819     }
61820
61821 });
61822
61823
61824 Ext.define('Ext.form.field.Field', {
61825
61826     
61827     isFormField : true,
61828
61829     
61830     
61831     
61832
61833     
61834     disabled : false,
61835
61836     
61837     submitValue: true,
61838
61839     
61840     validateOnChange: true,
61841
61842     
61843     suspendCheckChange: 0,
61844
61845     
61846     initField: function() {
61847         this.addEvents(
61848             
61849             'change',
61850             
61851             'validitychange',
61852             
61853             'dirtychange'
61854         );
61855
61856         this.initValue();
61857     },
61858
61859     
61860     initValue: function() {
61861         var me = this;
61862
61863         
61864         me.originalValue = me.lastValue = me.value;
61865
61866         
61867         me.suspendCheckChange++;
61868         me.setValue(me.value);
61869         me.suspendCheckChange--;
61870     },
61871
61872     
61873     getName: function() {
61874         return this.name;
61875     },
61876
61877     
61878     getValue: function() {
61879         return this.value;
61880     },
61881     
61882     
61883     setValue: function(value) {
61884         var me = this;
61885         me.value = value;
61886         me.checkChange();
61887         return me;
61888     },
61889
61890     
61891     isEqual: function(value1, value2) {
61892         return String(value1) === String(value2);
61893     },
61894
61895     
61896     getSubmitData: function() {
61897         var me = this,
61898             data = null;
61899         if (!me.disabled && me.submitValue && !me.isFileUpload()) {
61900             data = {};
61901             data[me.getName()] = '' + me.getValue();
61902         }
61903         return data;
61904     },
61905
61906     
61907     getModelData: function() {
61908         var me = this,
61909             data = null;
61910         if (!me.disabled && !me.isFileUpload()) {
61911             data = {};
61912             data[me.getName()] = me.getValue();
61913         }
61914         return data;
61915     },
61916
61917     
61918     reset : function(){
61919         var me = this;
61920         
61921         me.setValue(me.originalValue);
61922         me.clearInvalid();
61923         
61924         delete me.wasValid;
61925     },
61926
61927     
61928     resetOriginalValue: function() {
61929         this.originalValue = this.getValue();
61930         this.checkDirty();
61931     },
61932
61933     
61934     checkChange: function() {
61935         if (!this.suspendCheckChange) {
61936             var me = this,
61937                 newVal = me.getValue(),
61938                 oldVal = me.lastValue;
61939             if (!me.isEqual(newVal, oldVal) && !me.isDestroyed) {
61940                 me.lastValue = newVal;
61941                 me.fireEvent('change', me, newVal, oldVal);
61942                 me.onChange(newVal, oldVal);
61943             }
61944         }
61945     },
61946
61947     
61948     onChange: function(newVal, oldVal) {
61949         if (this.validateOnChange) {
61950             this.validate();
61951         }
61952         this.checkDirty();
61953     },
61954
61955     
61956     isDirty : function() {
61957         var me = this;
61958         return !me.disabled && !me.isEqual(me.getValue(), me.originalValue);
61959     },
61960
61961     
61962     checkDirty: function() {
61963         var me = this,
61964             isDirty = me.isDirty();
61965         if (isDirty !== me.wasDirty) {
61966             me.fireEvent('dirtychange', me, isDirty);
61967             me.onDirtyChange(isDirty);
61968             me.wasDirty = isDirty;
61969         }
61970     },
61971
61972     
61973     onDirtyChange: Ext.emptyFn,
61974
61975     
61976     getErrors: function(value) {
61977         return [];
61978     },
61979
61980     
61981     isValid : function() {
61982         var me = this;
61983         return me.disabled || Ext.isEmpty(me.getErrors());
61984     },
61985
61986     
61987     validate : function() {
61988         var me = this,
61989             isValid = me.isValid();
61990         if (isValid !== me.wasValid) {
61991             me.wasValid = isValid;
61992             me.fireEvent('validitychange', me, isValid);
61993         }
61994         return isValid;
61995     },
61996
61997     
61998     batchChanges: function(fn) {
61999         this.suspendCheckChange++;
62000         fn();
62001         this.suspendCheckChange--;
62002         this.checkChange();
62003     },
62004
62005     
62006     isFileUpload: function() {
62007         return false;
62008     },
62009
62010     
62011     extractFileInput: function() {
62012         return null;
62013     },
62014
62015     
62016     markInvalid: Ext.emptyFn,
62017
62018     
62019     clearInvalid: Ext.emptyFn
62020
62021 });
62022
62023
62024 Ext.define('Ext.layout.component.field.Field', {
62025
62026     
62027
62028     alias: ['layout.field'],
62029
62030     extend: 'Ext.layout.component.Component',
62031
62032     uses: ['Ext.tip.QuickTip', 'Ext.util.TextMetrics'],
62033
62034     
62035
62036     type: 'field',
62037
62038     beforeLayout: function(width, height) {
62039         var me = this;
62040         return me.callParent(arguments) || (!me.owner.preventMark && me.activeError !== me.owner.getActiveError());
62041     },
62042
62043     onLayout: function(width, height) {
62044         var me = this,
62045             owner = me.owner,
62046             labelStrategy = me.getLabelStrategy(),
62047             errorStrategy = me.getErrorStrategy(),
62048             isDefined = Ext.isDefined,
62049             isNumber = Ext.isNumber,
62050             lastSize, autoWidth, autoHeight, info, undef;
62051
62052         lastSize = me.lastComponentSize || {};
62053         if (!isDefined(width)) {
62054             width = lastSize.width;
62055             if (width < 0) { 
62056                 width = undef;
62057             }
62058         }
62059         if (!isDefined(height)) {
62060             height = lastSize.height;
62061             if (height < 0) { 
62062                 height = undef;
62063             }
62064         }
62065         autoWidth = !isNumber(width);
62066         autoHeight = !isNumber(height);
62067
62068         info = {
62069             autoWidth: autoWidth,
62070             autoHeight: autoHeight,
62071             width: autoWidth ? owner.getBodyNaturalWidth() : width, 
62072             height: height,
62073             setOuterWidth: false, 
62074
62075             
62076             insets: {
62077                 top: 0,
62078                 right: 0,
62079                 bottom: 0,
62080                 left: 0
62081             }
62082         };
62083
62084         
62085         
62086         
62087
62088         
62089         labelStrategy.prepare(owner, info);
62090         errorStrategy.prepare(owner, info);
62091
62092         
62093         labelStrategy.adjustHorizInsets(owner, info);
62094         errorStrategy.adjustHorizInsets(owner, info);
62095
62096         
62097         labelStrategy.layoutHoriz(owner, info);
62098         errorStrategy.layoutHoriz(owner, info);
62099
62100         
62101         labelStrategy.adjustVertInsets(owner, info);
62102         errorStrategy.adjustVertInsets(owner, info);
62103
62104         
62105         labelStrategy.layoutVert(owner, info);
62106         errorStrategy.layoutVert(owner, info);
62107
62108         
62109         if (autoWidth && autoHeight) {
62110             
62111             me.setElementSize(owner.el, (info.setOuterWidth ? info.width : undef), info.height);
62112         } else {
62113             me.setTargetSize((!autoWidth || info.setOuterWidth ? info.width : undef), info.height);
62114         }
62115         me.sizeBody(info);
62116
62117         me.activeError = owner.getActiveError();
62118     },
62119
62120
62121     
62122     sizeBody: function(info) {
62123         var me = this,
62124             owner = me.owner,
62125             insets = info.insets,
62126             totalWidth = info.width,
62127             totalHeight = info.height,
62128             width = Ext.isNumber(totalWidth) ? totalWidth - insets.left - insets.right : totalWidth,
62129             height = Ext.isNumber(totalHeight) ? totalHeight - insets.top - insets.bottom : totalHeight;
62130
62131         
62132         me.setElementSize(owner.bodyEl, width, height);
62133
62134         
62135         me.sizeBodyContents(width, height);
62136     },
62137
62138     
62139     sizeBodyContents: Ext.emptyFn,
62140
62141
62142     
62143     getLabelStrategy: function() {
62144         var me = this,
62145             strategies = me.labelStrategies,
62146             labelAlign = me.owner.labelAlign;
62147         return strategies[labelAlign] || strategies.base;
62148     },
62149
62150     
62151     getErrorStrategy: function() {
62152         var me = this,
62153             owner = me.owner,
62154             strategies = me.errorStrategies,
62155             msgTarget = owner.msgTarget;
62156         return !owner.preventMark && Ext.isString(msgTarget) ?
62157                 (strategies[msgTarget] || strategies.elementId) :
62158                 strategies.none;
62159     },
62160
62161
62162
62163     
62164     labelStrategies: (function() {
62165         var applyIf = Ext.applyIf,
62166             emptyFn = Ext.emptyFn,
62167             base = {
62168                 prepare: function(owner, info) {
62169                     var cls = owner.labelCls + '-' + owner.labelAlign,
62170                         labelEl = owner.labelEl;
62171                     if (labelEl && !labelEl.hasCls(cls)) {
62172                         labelEl.addCls(cls);
62173                     }
62174                 },
62175                 adjustHorizInsets: emptyFn,
62176                 adjustVertInsets: emptyFn,
62177                 layoutHoriz: emptyFn,
62178                 layoutVert: emptyFn
62179             },
62180             left = applyIf({
62181                 prepare: function(owner, info) {
62182                     base.prepare(owner, info);
62183                     
62184                     if (info.autoWidth) {
62185                         info.width += (!owner.labelEl ? 0 : owner.labelWidth + owner.labelPad);
62186                     }
62187                     
62188                     info.setOuterWidth = true;
62189                 },
62190                 adjustHorizInsets: function(owner, info) {
62191                     if (owner.labelEl) {
62192                         info.insets.left += owner.labelWidth + owner.labelPad;
62193                     }
62194                 },
62195                 layoutHoriz: function(owner, info) {
62196                     
62197                     
62198                     
62199                     
62200                     
62201                     var labelEl = owner.labelEl;
62202                     if (labelEl && !owner.isLabelSized && !Ext.isBorderBox) {
62203                         labelEl.setWidth(owner.labelWidth);
62204                         owner.isLabelSized = true;
62205                     }
62206                 }
62207             }, base);
62208
62209
62210         return {
62211             base: base,
62212
62213             
62214             top: applyIf({
62215                 adjustVertInsets: function(owner, info) {
62216                     var labelEl = owner.labelEl;
62217                     if (labelEl) {
62218                         info.insets.top += Ext.util.TextMetrics.measure(labelEl, owner.fieldLabel, info.width).height +
62219                                            labelEl.getFrameWidth('tb') + owner.labelPad;
62220                     }
62221                 }
62222             }, base),
62223
62224             
62225             left: left,
62226
62227             
62228             right: left
62229         };
62230     })(),
62231
62232
62233
62234     
62235     errorStrategies: (function() {
62236         function setDisplayed(el, displayed) {
62237             var wasDisplayed = el.getStyle('display') !== 'none';
62238             if (displayed !== wasDisplayed) {
62239                 el.setDisplayed(displayed);
62240             }
62241         }
62242
62243         function setStyle(el, name, value) {
62244             if (el.getStyle(name) !== value) {
62245                 el.setStyle(name, value);
62246             }
62247         }
62248
62249         var applyIf = Ext.applyIf,
62250             emptyFn = Ext.emptyFn,
62251             base = {
62252                 prepare: function(owner) {
62253                     setDisplayed(owner.errorEl, false);
62254                 },
62255                 adjustHorizInsets: emptyFn,
62256                 adjustVertInsets: emptyFn,
62257                 layoutHoriz: emptyFn,
62258                 layoutVert: emptyFn
62259             };
62260
62261         return {
62262             none: base,
62263
62264             
62265             side: applyIf({
62266                 prepare: function(owner) {
62267                     var errorEl = owner.errorEl;
62268                     errorEl.addCls(Ext.baseCSSPrefix + 'form-invalid-icon');
62269                     Ext.layout.component.field.Field.initTip();
62270                     errorEl.dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
62271                     setDisplayed(errorEl, owner.hasActiveError());
62272                 },
62273                 adjustHorizInsets: function(owner, info) {
62274                     if (owner.autoFitErrors && owner.hasActiveError()) {
62275                         info.insets.right += owner.errorEl.getWidth();
62276                     }
62277                 },
62278                 layoutHoriz: function(owner, info) {
62279                     if (owner.hasActiveError()) {
62280                         setStyle(owner.errorEl, 'left', info.width - info.insets.right + 'px');
62281                     }
62282                 },
62283                 layoutVert: function(owner, info) {
62284                     if (owner.hasActiveError()) {
62285                         setStyle(owner.errorEl, 'top', info.insets.top + 'px');
62286                     }
62287                 }
62288             }, base),
62289
62290             
62291             under: applyIf({
62292                 prepare: function(owner) {
62293                     var errorEl = owner.errorEl,
62294                         cls = Ext.baseCSSPrefix + 'form-invalid-under';
62295                     if (!errorEl.hasCls(cls)) {
62296                         errorEl.addCls(cls);
62297                     }
62298                     setDisplayed(errorEl, owner.hasActiveError());
62299                 },
62300                 adjustVertInsets: function(owner, info) {
62301                     if (owner.autoFitErrors) {
62302                         info.insets.bottom += owner.errorEl.getHeight();
62303                     }
62304                 },
62305                 layoutHoriz: function(owner, info) {
62306                     var errorEl = owner.errorEl,
62307                         insets = info.insets;
62308
62309                     setStyle(errorEl, 'width', info.width - insets.right - insets.left + 'px');
62310                     setStyle(errorEl, 'marginLeft', insets.left + 'px');
62311                 }
62312             }, base),
62313
62314             
62315             qtip: applyIf({
62316                 prepare: function(owner) {
62317                     setDisplayed(owner.errorEl, false);
62318                     Ext.layout.component.field.Field.initTip();
62319                     owner.getActionEl().dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
62320                 }
62321             }, base),
62322
62323             
62324             title: applyIf({
62325                 prepare: function(owner) {
62326                     setDisplayed(owner.errorEl, false);
62327                     owner.el.dom.title = owner.getActiveError() || '';
62328                 }
62329             }, base),
62330
62331             
62332             elementId: applyIf({
62333                 prepare: function(owner) {
62334                     setDisplayed(owner.errorEl, false);
62335                     var targetEl = Ext.fly(owner.msgTarget);
62336                     if (targetEl) {
62337                         targetEl.dom.innerHTML = owner.getActiveError() || '';
62338                         targetEl.setDisplayed(owner.hasActiveError());
62339                     }
62340                 }
62341             }, base)
62342         };
62343     })(),
62344
62345     statics: {
62346         
62347         initTip: function() {
62348             var tip = this.tip;
62349             if (!tip) {
62350                 tip = this.tip = Ext.create('Ext.tip.QuickTip', {
62351                     baseCls: Ext.baseCSSPrefix + 'form-invalid-tip',
62352                     renderTo: Ext.getBody()
62353                 });
62354                 tip.tagConfig = Ext.apply({}, {attribute: 'errorqtip'}, tip.tagConfig);
62355             }
62356         },
62357
62358         
62359         destroyTip: function() {
62360             var tip = this.tip;
62361             if (tip) {
62362                 tip.destroy();
62363                 delete this.tip;
62364             }
62365         }
62366     }
62367
62368 });
62369
62370
62371 Ext.define('Ext.form.field.VTypes', (function(){
62372     
62373     var alpha = /^[a-zA-Z_]+$/,
62374         alphanum = /^[a-zA-Z0-9_]+$/,
62375         email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
62376         url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
62377
62378     
62379     return {
62380         singleton: true,
62381         alternateClassName: 'Ext.form.VTypes',
62382
62383         
62384         'email' : function(v){
62385             return email.test(v);
62386         },
62387         
62388         'emailText' : 'This field should be an e-mail address in the format "user@example.com"',
62389         
62390         'emailMask' : /[a-z0-9_\.\-@\+]/i,
62391
62392         
62393         'url' : function(v){
62394             return url.test(v);
62395         },
62396         
62397         'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"',
62398
62399         
62400         'alpha' : function(v){
62401             return alpha.test(v);
62402         },
62403         
62404         'alphaText' : 'This field should only contain letters and _',
62405         
62406         'alphaMask' : /[a-z_]/i,
62407
62408         
62409         'alphanum' : function(v){
62410             return alphanum.test(v);
62411         },
62412         
62413         'alphanumText' : 'This field should only contain letters, numbers and _',
62414         
62415         'alphanumMask' : /[a-z0-9_]/i
62416     };
62417 })());
62418
62419
62420 Ext.define('Ext.layout.component.field.Text', {
62421     extend: 'Ext.layout.component.field.Field',
62422     alias: 'layout.textfield',
62423     requires: ['Ext.util.TextMetrics'],
62424
62425     type: 'textfield',
62426
62427
62428     
62429     beforeLayout: function(width, height) {
62430         var me = this,
62431             owner = me.owner,
62432             lastValue = this.lastValue,
62433             value = owner.getRawValue();
62434         this.lastValue = value;
62435         return me.callParent(arguments) || (owner.grow && value !== lastValue);
62436     },
62437
62438
62439     
62440     sizeBodyContents: function(width, height) {
62441         var size = this.adjustForGrow(width, height);
62442         this.setElementSize(this.owner.inputEl, size[0], size[1]);
62443     },
62444
62445
62446     
62447     adjustForGrow: function(width, height) {
62448         var me = this,
62449             owner = me.owner,
62450             inputEl, value, calcWidth,
62451             result = [width, height];
62452
62453         if (owner.grow) {
62454             inputEl = owner.inputEl;
62455
62456             
62457             value = (inputEl.dom.value || (owner.hasFocus ? '' : owner.emptyText) || '') + owner.growAppend;
62458             calcWidth = inputEl.getTextWidth(value) + inputEl.getBorderWidth("lr") + inputEl.getPadding("lr");
62459
62460             
62461             result[0] = Ext.Number.constrain(calcWidth, owner.growMin,
62462                     Math.max(owner.growMin, Math.min(owner.growMax, Ext.isNumber(width) ? width : Infinity)));
62463         }
62464
62465         return result;
62466     }
62467
62468 });
62469
62470
62471 Ext.define('Ext.layout.component.field.TextArea', {
62472     extend: 'Ext.layout.component.field.Text',
62473     alias: 'layout.textareafield',
62474
62475     type: 'textareafield',
62476
62477
62478     
62479     adjustForGrow: function(width, height) {
62480         var me = this,
62481             owner = me.owner,
62482             inputEl, value, max,
62483             curWidth, curHeight, calcHeight,
62484             result = [width, height];
62485
62486         if (owner.grow) {
62487             inputEl = owner.inputEl;
62488             curWidth = inputEl.getWidth(true); 
62489             curHeight = inputEl.getHeight();
62490
62491             
62492             value = inputEl.dom.value || '&#160;';
62493             value += owner.growAppend;
62494
62495             
62496             value = value.replace(/\n/g, '<br>');
62497
62498             
62499             calcHeight = Ext.util.TextMetrics.measure(inputEl, value, curWidth).height +
62500                          inputEl.getBorderWidth("tb") + inputEl.getPadding("tb");
62501
62502             
62503             max = owner.growMax;
62504             if (Ext.isNumber(height)) {
62505                 max = Math.min(max, height);
62506             }
62507             result[1] = Ext.Number.constrain(calcHeight, owner.growMin, max);
62508         }
62509
62510         return result;
62511     }
62512
62513 });
62514
62515
62516 Ext.define('Ext.layout.container.Anchor', {
62517
62518     
62519
62520     alias: 'layout.anchor',
62521     extend: 'Ext.layout.container.Container',
62522     alternateClassName: 'Ext.layout.AnchorLayout',
62523
62524     
62525
62526     
62527
62528     type: 'anchor',
62529
62530     
62531     defaultAnchor: '100%',
62532
62533     parseAnchorRE: /^(r|right|b|bottom)$/i,
62534
62535     
62536     onLayout: function() {
62537         this.callParent(arguments);
62538
62539         var me = this,
62540             size = me.getLayoutTargetSize(),
62541             owner = me.owner,
62542             target = me.getTarget(),
62543             ownerWidth = size.width,
62544             ownerHeight = size.height,
62545             overflow = target.getStyle('overflow'),
62546             components = me.getVisibleItems(owner),
62547             len = components.length,
62548             boxes = [],
62549             box, newTargetSize, anchorWidth, anchorHeight, component, anchorSpec, calcWidth, calcHeight,
62550             anchorsArray, anchor, i, el, cleaner;
62551
62552         if (ownerWidth < 20 && ownerHeight < 20) {
62553             return;
62554         }
62555
62556         
62557         
62558         
62559         if (!me.clearEl) {
62560             me.clearEl = target.createChild({
62561                 cls: Ext.baseCSSPrefix + 'clear',
62562                 role: 'presentation'
62563             });
62564         }
62565
62566         
62567         if (owner.anchorSize) {
62568             if (typeof owner.anchorSize == 'number') {
62569                 anchorWidth = owner.anchorSize;
62570             }
62571             else {
62572                 anchorWidth = owner.anchorSize.width;
62573                 anchorHeight = owner.anchorSize.height;
62574             }
62575         }
62576         else {
62577             anchorWidth = owner.initialConfig.width;
62578             anchorHeight = owner.initialConfig.height;
62579         }
62580
62581         
62582         if (!Ext.supports.RightMargin) {
62583             cleaner = Ext.core.Element.getRightMarginFixCleaner(target);
62584             target.addCls(Ext.baseCSSPrefix + 'inline-children');
62585         }
62586
62587         for (i = 0; i < len; i++) {
62588             component = components[i];
62589             el = component.el;
62590             anchor = component.anchor;
62591
62592             if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict)) {
62593                 component.anchor = anchor = me.defaultAnchor;
62594             }
62595
62596             if (anchor) {
62597                 anchorSpec = component.anchorSpec;
62598                 
62599                 if (!anchorSpec) {
62600                     anchorsArray = anchor.split(' ');
62601                     component.anchorSpec = anchorSpec = {
62602                         right: me.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
62603                         bottom: me.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
62604                     };
62605                 }
62606                 calcWidth = anchorSpec.right ? me.adjustWidthAnchor(anchorSpec.right(ownerWidth) - el.getMargin('lr'), component) : undefined;
62607                 calcHeight = anchorSpec.bottom ? me.adjustHeightAnchor(anchorSpec.bottom(ownerHeight) - el.getMargin('tb'), component) : undefined;
62608
62609                 boxes.push({
62610                     component: component,
62611                     anchor: true,
62612                     width: calcWidth || undefined,
62613                     height: calcHeight || undefined
62614                 });
62615             } else {
62616                 boxes.push({
62617                     component: component,
62618                     anchor: false
62619                 });
62620             }
62621         }
62622
62623         
62624         if (!Ext.supports.RightMargin) {
62625             target.removeCls(Ext.baseCSSPrefix + 'inline-children');
62626             cleaner();
62627         }
62628
62629         for (i = 0; i < len; i++) {
62630             box = boxes[i];
62631             me.setItemSize(box.component, box.width, box.height);
62632         }
62633
62634         if (overflow && overflow != 'hidden' && !me.adjustmentPass) {
62635             newTargetSize = me.getLayoutTargetSize();
62636             if (newTargetSize.width != size.width || newTargetSize.height != size.height) {
62637                 me.adjustmentPass = true;
62638                 me.onLayout();
62639             }
62640         }
62641
62642         delete me.adjustmentPass;
62643     },
62644
62645     
62646     parseAnchor: function(a, start, cstart) {
62647         if (a && a != 'none') {
62648             var ratio;
62649             
62650             if (this.parseAnchorRE.test(a)) {
62651                 var diff = cstart - start;
62652                 return function(v) {
62653                     return v - diff;
62654                 };
62655             }    
62656             
62657             else if (a.indexOf('%') != -1) {
62658                 ratio = parseFloat(a.replace('%', '')) * 0.01;
62659                 return function(v) {
62660                     return Math.floor(v * ratio);
62661                 };
62662             }    
62663             
62664             else {
62665                 a = parseInt(a, 10);
62666                 if (!isNaN(a)) {
62667                     return function(v) {
62668                         return v + a;
62669                     };
62670                 }
62671             }
62672         }
62673         return null;
62674     },
62675
62676     
62677     adjustWidthAnchor: function(value, comp) {
62678         return value;
62679     },
62680
62681     
62682     adjustHeightAnchor: function(value, comp) {
62683         return value;
62684     }
62685
62686 });
62687
62688 Ext.define('Ext.form.action.Load', {
62689     extend:'Ext.form.action.Action',
62690     requires: ['Ext.data.Connection'],
62691     alternateClassName: 'Ext.form.Action.Load',
62692     alias: 'formaction.load',
62693
62694     type: 'load',
62695
62696     
62697     run: function() {
62698         Ext.Ajax.request(Ext.apply(
62699             this.createCallback(),
62700             {
62701                 method: this.getMethod(),
62702                 url: this.getUrl(),
62703                 headers: this.headers,
62704                 params: this.getParams()
62705             }
62706         ));
62707     },
62708
62709     
62710     onSuccess: function(response){
62711         var result = this.processResponse(response),
62712             form = this.form;
62713         if (result === true || !result.success || !result.data) {
62714             this.failureType = Ext.form.action.Action.LOAD_FAILURE;
62715             form.afterAction(this, false);
62716             return;
62717         }
62718         form.clearInvalid();
62719         form.setValues(result.data);
62720         form.afterAction(this, true);
62721     },
62722
62723     
62724     handleResponse: function(response) {
62725         var reader = this.form.reader,
62726             rs, data;
62727         if (reader) {
62728             rs = reader.read(response);
62729             data = rs.records && rs.records[0] ? rs.records[0].data : null;
62730             return {
62731                 success : rs.success,
62732                 data : data
62733             };
62734         }
62735         return Ext.decode(response.responseText);
62736     }
62737 });
62738
62739
62740
62741 Ext.define('Ext.window.Window', {
62742     extend: 'Ext.panel.Panel',
62743
62744     alternateClassName: 'Ext.Window',
62745
62746     requires: ['Ext.util.ComponentDragger', 'Ext.util.Region', 'Ext.EventManager'],
62747
62748     alias: 'widget.window',
62749
62750     
62751     
62752     
62753     
62754     
62755     
62756     
62757     
62758
62759     
62760     baseCls: Ext.baseCSSPrefix + 'window',
62761
62762     
62763     resizable: true,
62764
62765     
62766     draggable: true,
62767
62768     
62769     constrain: false,
62770
62771     
62772     constrainHeader: false,
62773
62774     
62775     plain: false,
62776
62777     
62778     minimizable: false,
62779
62780     
62781     maximizable: false,
62782
62783     
62784     minHeight: 100,
62785
62786     
62787     minWidth: 200,
62788
62789     
62790     expandOnShow: true,
62791
62792     
62793     collapsible: false,
62794
62795     
62796     closable: true,
62797
62798     
62799     hidden: true,
62800
62801     
62802     autoRender: true,
62803
62804     
62805     hideMode: 'visibility',
62806
62807     
62808     floating: true,
62809
62810     ariaRole: 'alertdialog',
62811     
62812     itemCls: 'x-window-item',
62813
62814     overlapHeader: true,
62815     
62816     ignoreHeaderBorderManagement: true,
62817
62818     
62819     initComponent: function() {
62820         var me = this;
62821         me.callParent();
62822         me.addEvents(
62823             
62824             
62825             
62826             'resize',
62827             
62828             'maximize',
62829             
62830             'minimize',
62831             
62832             'restore'
62833         );
62834
62835         if (me.plain) {
62836             me.addClsWithUI('plain');
62837         }
62838
62839         if (me.modal) {
62840             me.ariaRole = 'dialog';
62841         }
62842     },
62843
62844     
62845     
62846
62847     initStateEvents: function(){
62848         var events = this.stateEvents;
62849         
62850         Ext.each(['maximize', 'restore', 'resize', 'dragend'], function(event){
62851             if (Ext.Array.indexOf(events, event)) {
62852                 events.push(event);
62853             }
62854         });
62855         this.callParent();
62856     },
62857
62858     getState: function() {
62859         var me = this,
62860             state = me.callParent() || {},
62861             maximized = !!me.maximized;
62862
62863         state.maximized = maximized;
62864         Ext.apply(state, {
62865             size: maximized ? me.restoreSize : me.getSize(),
62866             pos: maximized ? me.restorePos : me.getPosition()
62867         });
62868         return state;
62869     },
62870
62871     applyState: function(state){
62872         var me = this;
62873
62874         if (state) {
62875             me.maximized = state.maximized;
62876             if (me.maximized) {
62877                 me.hasSavedRestore = true;
62878                 me.restoreSize = state.size;
62879                 me.restorePos = state.pos;
62880             } else {
62881                 Ext.apply(me, {
62882                     width: state.size.width,
62883                     height: state.size.height,
62884                     x: state.pos[0],
62885                     y: state.pos[1]
62886                 });
62887             }
62888         }
62889     },
62890
62891     
62892     onMouseDown: function () {
62893         if (this.floating) {
62894             this.toFront();
62895         }
62896     },
62897
62898     
62899     onRender: function(ct, position) {
62900         var me = this;
62901         me.callParent(arguments);
62902         me.focusEl = me.el;
62903
62904         
62905         if (me.maximizable) {
62906             me.header.on({
62907                 dblclick: {
62908                     fn: me.toggleMaximize,
62909                     element: 'el',
62910                     scope: me
62911                 }
62912             });
62913         }
62914     },
62915
62916     
62917     afterRender: function() {
62918         var me = this,
62919             hidden = me.hidden,
62920             keyMap;
62921
62922         me.hidden = false;
62923         
62924         me.callParent();
62925         me.hidden = hidden;
62926
62927         
62928         me.proxy = me.getProxy();
62929
62930         
62931         me.mon(me.el, 'mousedown', me.onMouseDown, me);
62932
62933         
62934         if (me.maximized) {
62935             me.maximized = false;
62936             me.maximize();
62937         }
62938
62939         if (me.closable) {
62940             keyMap = me.getKeyMap();
62941             keyMap.on(27, me.onEsc, me);
62942
62943             
62944                 keyMap.disable();
62945             
62946         }
62947
62948         if (!hidden) {
62949             me.syncMonitorWindowResize();
62950             me.doConstrain();
62951         }
62952     },
62953
62954     
62955     initDraggable: function() {
62956         var me = this,
62957             ddConfig;
62958
62959         if (!me.header) {
62960             me.updateHeader(true);
62961         }
62962         
62963         
62964         if (me.header) {
62965             ddConfig = Ext.applyIf({
62966                 el: me.el,
62967                 delegate: '#' + me.header.id
62968             }, me.draggable);
62969
62970             
62971             if (me.constrain || me.constrainHeader) {
62972                 ddConfig.constrain = me.constrain;
62973                 ddConfig.constrainDelegate = me.constrainHeader;
62974                 ddConfig.constrainTo = me.constrainTo || me.container;
62975             }
62976
62977             
62978             me.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig);
62979             me.relayEvents(me.dd, ['dragstart', 'drag', 'dragend']);
62980         }
62981     },
62982
62983     
62984     onEsc: function(k, e) {
62985         e.stopEvent();
62986         this[this.closeAction]();
62987     },
62988
62989     
62990     beforeDestroy: function() {
62991         var me = this;
62992         if (me.rendered) {
62993             delete this.animateTarget;
62994             me.hide();
62995             Ext.destroy(
62996                 me.keyMap
62997             );
62998         }
62999         me.callParent();
63000     },
63001
63002     
63003     addTools: function() {
63004         var me = this;
63005
63006         
63007         me.callParent();
63008
63009         if (me.minimizable) {
63010             me.addTool({
63011                 type: 'minimize',
63012                 handler: Ext.Function.bind(me.minimize, me, [])
63013             });
63014         }
63015         if (me.maximizable) {
63016             me.addTool({
63017                 type: 'maximize',
63018                 handler: Ext.Function.bind(me.maximize, me, [])
63019             });
63020             me.addTool({
63021                 type: 'restore',
63022                 handler: Ext.Function.bind(me.restore, me, []),
63023                 hidden: true
63024             });
63025         }
63026     },
63027
63028     
63029     getFocusEl: function() {
63030         var me = this,
63031             f = me.focusEl,
63032             defaultComp = me.defaultButton || me.defaultFocus,
63033             t = typeof db,
63034             el,
63035             ct;
63036
63037         if (Ext.isDefined(defaultComp)) {
63038             if (Ext.isNumber(defaultComp)) {
63039                 f = me.query('button')[defaultComp];
63040             } else if (Ext.isString(defaultComp)) {
63041                 f = me.down('#' + defaultComp);
63042             } else {
63043                 f = defaultComp;
63044             }
63045         }
63046         return f || me.focusEl;
63047     },
63048
63049     
63050     beforeShow: function() {
63051         this.callParent();
63052
63053         if (this.expandOnShow) {
63054             this.expand(false);
63055         }
63056     },
63057
63058     
63059     afterShow: function(animateTarget) {
63060         var me = this;
63061
63062         
63063         
63064         me.callParent(arguments);
63065
63066         if (me.maximized) {
63067             me.fitContainer();
63068         }
63069
63070         me.syncMonitorWindowResize();
63071         me.doConstrain();
63072
63073         if (me.keyMap) {
63074             me.keyMap.enable();
63075         }
63076     },
63077
63078     
63079     doClose: function() {
63080         var me = this;
63081
63082         
63083         if (me.hidden) {
63084             me.fireEvent('close', me);
63085             me[me.closeAction]();
63086         } else {
63087             
63088             me.hide(me.animTarget, me.doClose, me);
63089         }
63090     },
63091
63092     
63093     afterHide: function() {
63094         var me = this;
63095
63096         
63097         me.syncMonitorWindowResize();
63098
63099         
63100         if (me.keyMap) {
63101             me.keyMap.disable();
63102         }
63103
63104         
63105         me.callParent(arguments);
63106     },
63107
63108     
63109     onWindowResize: function() {
63110         if (this.maximized) {
63111             this.fitContainer();
63112         }
63113         this.doConstrain();
63114     },
63115
63116     
63117     minimize: function() {
63118         this.fireEvent('minimize', this);
63119         return this;
63120     },
63121
63122     afterCollapse: function() {
63123         var me = this;
63124
63125         if (me.maximizable) {
63126             me.tools.maximize.hide();
63127             me.tools.restore.hide();
63128         }
63129         if (me.resizer) {
63130             me.resizer.disable();
63131         }
63132         me.callParent(arguments);
63133     },
63134
63135     afterExpand: function() {
63136         var me = this;
63137
63138         if (me.maximized) {
63139             me.tools.restore.show();
63140         } else if (me.maximizable) {
63141             me.tools.maximize.show();
63142         }
63143         if (me.resizer) {
63144             me.resizer.enable();
63145         }
63146         me.callParent(arguments);
63147     },
63148
63149     
63150     maximize: function() {
63151         var me = this;
63152
63153         if (!me.maximized) {
63154             me.expand(false);
63155             if (!me.hasSavedRestore) {
63156                 me.restoreSize = me.getSize();
63157                 me.restorePos = me.getPosition(true);
63158             }
63159             if (me.maximizable) {
63160                 me.tools.maximize.hide();
63161                 me.tools.restore.show();
63162             }
63163             me.maximized = true;
63164             me.el.disableShadow();
63165
63166             if (me.dd) {
63167                 me.dd.disable();
63168             }
63169             if (me.collapseTool) {
63170                 me.collapseTool.hide();
63171             }
63172             me.el.addCls(Ext.baseCSSPrefix + 'window-maximized');
63173             me.container.addCls(Ext.baseCSSPrefix + 'window-maximized-ct');
63174
63175             me.syncMonitorWindowResize();
63176             me.setPosition(0, 0);
63177             me.fitContainer();
63178             me.fireEvent('maximize', me);
63179         }
63180         return me;
63181     },
63182
63183     
63184     restore: function() {
63185         var me = this,
63186             tools = me.tools;
63187
63188         if (me.maximized) {
63189             delete me.hasSavedRestore;
63190             me.removeCls(Ext.baseCSSPrefix + 'window-maximized');
63191
63192             
63193             if (tools.restore) {
63194                 tools.restore.hide();
63195             }
63196             if (tools.maximize) {
63197                 tools.maximize.show();
63198             }
63199             if (me.collapseTool) {
63200                 me.collapseTool.show();
63201             }
63202
63203             
63204             me.setPosition(me.restorePos);
63205             me.setSize(me.restoreSize);
63206
63207             
63208             delete me.restorePos;
63209             delete me.restoreSize;
63210
63211             me.maximized = false;
63212
63213             me.el.enableShadow(true);
63214
63215             
63216             if (me.dd) {
63217                 me.dd.enable();
63218             }
63219
63220             me.container.removeCls(Ext.baseCSSPrefix + 'window-maximized-ct');
63221
63222             me.syncMonitorWindowResize();
63223             me.doConstrain();
63224             me.fireEvent('restore', me);
63225         }
63226         return me;
63227     },
63228
63229     
63230     syncMonitorWindowResize: function () {
63231         var me = this,
63232             currentlyMonitoring = me._monitoringResize,
63233             
63234             yes = me.monitorResize || me.constrain || me.constrainHeader || me.maximized,
63235             
63236             veto = me.hidden || me.destroying || me.isDestroyed;
63237
63238         if (yes && !veto) {
63239             
63240             if (!currentlyMonitoring) {
63241                 
63242                 Ext.EventManager.onWindowResize(me.onWindowResize, me);
63243                 me._monitoringResize = true;
63244             }
63245         } else if (currentlyMonitoring) {
63246             
63247             Ext.EventManager.removeResizeListener(me.onWindowResize, me);
63248             me._monitoringResize = false;
63249         }
63250     },
63251
63252     
63253     toggleMaximize: function() {
63254         return this[this.maximized ? 'restore': 'maximize']();
63255     }
63256
63257     
63258 });
63259
63260 Ext.define('Ext.form.field.Base', {
63261     extend: 'Ext.Component',
63262     mixins: {
63263         labelable: 'Ext.form.Labelable',
63264         field: 'Ext.form.field.Field'
63265     },
63266     alias: 'widget.field',
63267     alternateClassName: ['Ext.form.Field', 'Ext.form.BaseField'],
63268     requires: ['Ext.util.DelayedTask', 'Ext.XTemplate', 'Ext.layout.component.field.Field'],
63269
63270     fieldSubTpl: [
63271         '<input id="{id}" type="{type}" ',
63272         '<tpl if="name">name="{name}" </tpl>',
63273         '<tpl if="size">size="{size}" </tpl>',
63274         '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
63275         'class="{fieldCls} {typeCls}" autocomplete="off" />',
63276         {
63277             compiled: true,
63278             disableFormats: true
63279         }
63280     ],
63281
63282     
63283
63284     
63285     inputType: 'text',
63286
63287     
63288
63289     
63290     invalidText : 'The value in this field is invalid',
63291
63292     
63293     fieldCls : Ext.baseCSSPrefix + 'form-field',
63294
63295     
63296
63297     
63298     focusCls : Ext.baseCSSPrefix + 'form-focus',
63299
63300     
63301     dirtyCls : Ext.baseCSSPrefix + 'form-dirty',
63302
63303     
63304     checkChangeEvents: Ext.isIE && (!document.documentMode || document.documentMode < 9) ?
63305                         ['change', 'propertychange'] :
63306                         ['change', 'input', 'textInput', 'keyup', 'dragdrop'],
63307
63308     
63309     checkChangeBuffer: 50,
63310
63311     componentLayout: 'field',
63312
63313     
63314     readOnly : false,
63315
63316     
63317     readOnlyCls: Ext.baseCSSPrefix + 'form-readonly',
63318
63319     
63320
63321     
63322     validateOnBlur: true,
63323
63324     
63325     hasFocus : false,
63326     
63327     baseCls: Ext.baseCSSPrefix + 'field',
63328     
63329     maskOnDisable: false,
63330
63331     
63332     initComponent : function() {
63333         var me = this;
63334
63335         me.callParent();
63336
63337         me.subTplData = me.subTplData || {};
63338
63339         me.addEvents(
63340             
63341             'focus',
63342             
63343             'blur',
63344             
63345             'specialkey'
63346         );
63347
63348         
63349         me.initLabelable();
63350         me.initField();
63351
63352         
63353         if (!me.name) {
63354             me.name = me.getInputId();
63355         }
63356     },
63357
63358     
63359     getInputId: function() {
63360         return this.inputId || (this.inputId = Ext.id());
63361     },
63362
63363     
63364     getSubTplData: function() {
63365         var me = this,
63366             type = me.inputType,
63367             inputId = me.getInputId();
63368
63369         return Ext.applyIf(me.subTplData, {
63370             id: inputId,
63371             name: me.name || inputId,
63372             type: type,
63373             size: me.size || 20,
63374             cls: me.cls,
63375             fieldCls: me.fieldCls,
63376             tabIdx: me.tabIndex,
63377             typeCls: Ext.baseCSSPrefix + 'form-' + (type === 'password' ? 'text' : type)
63378         });
63379     },
63380
63381     
63382     getSubTplMarkup: function() {
63383         return this.getTpl('fieldSubTpl').apply(this.getSubTplData());
63384     },
63385
63386     initRenderTpl: function() {
63387         var me = this;
63388         if (!me.hasOwnProperty('renderTpl')) {
63389             me.renderTpl = me.getTpl('labelableRenderTpl');
63390         }
63391         return me.callParent();
63392     },
63393
63394     initRenderData: function() {
63395         return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
63396     },
63397
63398     
63399     setFieldStyle: function(style) {
63400         var me = this,
63401             inputEl = me.inputEl;
63402         if (inputEl) {
63403             inputEl.applyStyles(style);
63404         }
63405         me.fieldStyle = style;
63406     },
63407
63408     
63409     onRender : function() {
63410         var me = this,
63411             fieldStyle = me.fieldStyle,
63412             renderSelectors = me.renderSelectors;
63413
63414         Ext.applyIf(renderSelectors, me.getLabelableSelectors());
63415
63416         Ext.applyIf(renderSelectors, {
63417             
63418             inputEl: '.' + me.fieldCls
63419         });
63420
63421         me.callParent(arguments);
63422
63423         
63424         me.setRawValue(me.rawValue);
63425
63426         if (me.readOnly) {
63427             me.setReadOnly(true);
63428         }
63429         if (me.disabled) {
63430             me.disable();
63431         }
63432         if (fieldStyle) {
63433             me.setFieldStyle(fieldStyle);
63434         }
63435
63436         me.renderActiveError();
63437     },
63438
63439     initAria: function() {
63440         var me = this;
63441         me.callParent();
63442
63443         
63444         me.getActionEl().dom.setAttribute('aria-describedby', Ext.id(me.errorEl));
63445     },
63446
63447     getFocusEl: function() {
63448         return this.inputEl;
63449     },
63450
63451     isFileUpload: function() {
63452         return this.inputType === 'file';
63453     },
63454
63455     extractFileInput: function() {
63456         var me = this,
63457             fileInput = me.isFileUpload() ? me.inputEl.dom : null,
63458             clone;
63459         if (fileInput) {
63460             clone = fileInput.cloneNode(true);
63461             fileInput.parentNode.replaceChild(clone, fileInput);
63462             me.inputEl = Ext.get(clone);
63463         }
63464         return fileInput;
63465     },
63466
63467     
63468     getSubmitData: function() {
63469         var me = this,
63470             data = null,
63471             val;
63472         if (!me.disabled && me.submitValue && !me.isFileUpload()) {
63473             val = me.getSubmitValue();
63474             if (val !== null) {
63475                 data = {};
63476                 data[me.getName()] = val;
63477             }
63478         }
63479         return data;
63480     },
63481
63482     
63483     getSubmitValue: function() {
63484         return this.processRawValue(this.getRawValue());
63485     },
63486
63487     
63488     getRawValue: function() {
63489         var me = this,
63490             v = (me.inputEl ? me.inputEl.getValue() : Ext.value(me.rawValue, ''));
63491         me.rawValue = v;
63492         return v;
63493     },
63494
63495     
63496     setRawValue: function(value) {
63497         var me = this;
63498         value = Ext.value(value, '');
63499         me.rawValue = value;
63500
63501         
63502         if (me.inputEl) {
63503             me.inputEl.dom.value = value;
63504         }
63505         return value;
63506     },
63507
63508     
63509     valueToRaw: function(value) {
63510         return '' + Ext.value(value, '');
63511     },
63512
63513     
63514     rawToValue: function(rawValue) {
63515         return rawValue;
63516     },
63517
63518     
63519     processRawValue: function(value) {
63520         return value;
63521     },
63522
63523     
63524     getValue: function() {
63525         var me = this,
63526             val = me.rawToValue(me.processRawValue(me.getRawValue()));
63527         me.value = val;
63528         return val;
63529     },
63530
63531     
63532     setValue: function(value) {
63533         var me = this;
63534         me.setRawValue(me.valueToRaw(value));
63535         return me.mixins.field.setValue.call(me, value);
63536     },
63537
63538
63539     
63540     onDisable: function() {
63541         var me = this,
63542             inputEl = me.inputEl;
63543         me.callParent();
63544         if (inputEl) {
63545             inputEl.dom.disabled = true;
63546         }
63547     },
63548
63549     
63550     onEnable: function() {
63551         var me = this,
63552             inputEl = me.inputEl;
63553         me.callParent();
63554         if (inputEl) {
63555             inputEl.dom.disabled = false;
63556         }
63557     },
63558
63559     
63560     setReadOnly: function(readOnly) {
63561         var me = this,
63562             inputEl = me.inputEl;
63563         if (inputEl) {
63564             inputEl.dom.readOnly = readOnly;
63565             inputEl.dom.setAttribute('aria-readonly', readOnly);
63566         }
63567         me[readOnly ? 'addCls' : 'removeCls'](me.readOnlyCls);
63568         me.readOnly = readOnly;
63569     },
63570
63571     
63572     fireKey: function(e){
63573         if(e.isSpecialKey()){
63574             this.fireEvent('specialkey', this, Ext.create('Ext.EventObjectImpl', e));
63575         }
63576     },
63577
63578     
63579     initEvents : function(){
63580         var me = this,
63581             inputEl = me.inputEl,
63582             onChangeTask,
63583             onChangeEvent;
63584         if (inputEl) {
63585             me.mon(inputEl, Ext.EventManager.getKeyEvent(), me.fireKey,  me);
63586             me.mon(inputEl, 'focus', me.onFocus, me);
63587
63588             
63589             
63590             me.mon(inputEl, 'blur', me.onBlur, me, me.inEditor ? {buffer:10} : null);
63591
63592             
63593             onChangeTask = Ext.create('Ext.util.DelayedTask', me.checkChange, me);
63594             me.onChangeEvent = onChangeEvent = function() {
63595                 onChangeTask.delay(me.checkChangeBuffer);
63596             };
63597             Ext.each(me.checkChangeEvents, function(eventName) {
63598                 if (eventName === 'propertychange') {
63599                     me.usesPropertychange = true;
63600                 }
63601                 me.mon(inputEl, eventName, onChangeEvent);
63602             }, me);
63603         }
63604         me.callParent();
63605     },
63606
63607     doComponentLayout: function() {
63608         var me = this,
63609             inputEl = me.inputEl,
63610             usesPropertychange = me.usesPropertychange,
63611             ename = 'propertychange',
63612             onChangeEvent = me.onChangeEvent;
63613
63614         
63615         
63616         
63617         if (usesPropertychange) {
63618             me.mun(inputEl, ename, onChangeEvent);
63619         }
63620         me.callParent(arguments);
63621         if (usesPropertychange) {
63622             me.mon(inputEl, ename, onChangeEvent);
63623         }
63624     },
63625
63626     
63627     preFocus: Ext.emptyFn,
63628
63629     
63630     onFocus: function() {
63631         var me = this,
63632             focusCls = me.focusCls,
63633             inputEl = me.inputEl;
63634         me.preFocus();
63635         if (focusCls && inputEl) {
63636             inputEl.addCls(focusCls);
63637         }
63638         if (!me.hasFocus) {
63639             me.hasFocus = true;
63640             me.fireEvent('focus', me);
63641         }
63642     },
63643
63644     
63645     beforeBlur : Ext.emptyFn,
63646
63647     
63648     onBlur : function(){
63649         var me = this,
63650             focusCls = me.focusCls,
63651             inputEl = me.inputEl;
63652         me.beforeBlur();
63653         if (focusCls && inputEl) {
63654             inputEl.removeCls(focusCls);
63655         }
63656         if (me.validateOnBlur) {
63657             me.validate();
63658         }
63659         me.hasFocus = false;
63660         me.fireEvent('blur', me);
63661         me.postBlur();
63662     },
63663
63664     
63665     postBlur : Ext.emptyFn,
63666
63667
63668     
63669     onDirtyChange: function(isDirty) {
63670         this[isDirty ? 'addCls' : 'removeCls'](this.dirtyCls);
63671     },
63672
63673
63674     
63675     isValid : function() {
63676         var me = this;
63677         return me.disabled || me.validateValue(me.processRawValue(me.getRawValue()));
63678     },
63679
63680
63681     
63682     validateValue: function(value) {
63683         var me = this,
63684             errors = me.getErrors(value),
63685             isValid = Ext.isEmpty(errors);
63686         if (!me.preventMark) {
63687             if (isValid) {
63688                 me.clearInvalid();
63689             } else {
63690                 me.markInvalid(errors);
63691             }
63692         }
63693
63694         return isValid;
63695     },
63696
63697     
63698     markInvalid : function(errors) {
63699         
63700         var me = this,
63701             oldMsg = me.getActiveError();
63702         me.setActiveErrors(Ext.Array.from(errors));
63703         if (oldMsg !== me.getActiveError()) {
63704             me.doComponentLayout();
63705         }
63706     },
63707
63708     
63709     clearInvalid : function() {
63710         
63711         var me = this,
63712             hadError = me.hasActiveError();
63713         me.unsetActiveError();
63714         if (hadError) {
63715             me.doComponentLayout();
63716         }
63717     },
63718
63719     
63720     renderActiveError: function() {
63721         var me = this,
63722             hasError = me.hasActiveError();
63723         if (me.inputEl) {
63724             
63725             me.inputEl[hasError ? 'addCls' : 'removeCls'](me.invalidCls + '-field');
63726         }
63727         me.mixins.labelable.renderActiveError.call(me);
63728     },
63729
63730
63731     getActionEl: function() {
63732         return this.inputEl || this.el;
63733     }
63734
63735 });
63736
63737
63738 Ext.define('Ext.form.field.Text', {
63739     extend:'Ext.form.field.Base',
63740     alias: 'widget.textfield',
63741     requires: ['Ext.form.field.VTypes', 'Ext.layout.component.field.Text'],
63742     alternateClassName: ['Ext.form.TextField', 'Ext.form.Text'],
63743
63744     
63745     
63746     
63747
63748     
63749     size: 20,
63750
63751     
63752
63753     
63754     growMin : 30,
63755     
63756     
63757     growMax : 800,
63758
63759     
63760     growAppend: 'W',
63761     
63762     
63763
63764     
63765
63766     
63767
63768     
63769     allowBlank : true,
63770     
63771     
63772     minLength : 0,
63773     
63774     
63775     maxLength : Number.MAX_VALUE,
63776     
63777     
63778
63779     
63780     minLengthText : 'The minimum length for this field is {0}',
63781     
63782     
63783     maxLengthText : 'The maximum length for this field is {0}',
63784     
63785     
63786     
63787     
63788     blankText : 'This field is required',
63789     
63790     
63791
63792     
63793
63794     
63795     regexText : '',
63796     
63797     
63798
63799     
63800     emptyCls : Ext.baseCSSPrefix + 'form-empty-field',
63801
63802     ariaRole: 'textbox',
63803
63804     
63805
63806     componentLayout: 'textfield',
63807
63808     initComponent : function(){
63809         this.callParent();
63810         this.addEvents(
63811             
63812             'autosize',
63813
63814             
63815             'keydown',
63816             
63817             'keyup',
63818             
63819             'keypress'
63820         );
63821     },
63822
63823     
63824     initEvents : function(){
63825         var me = this,
63826             el = me.inputEl;
63827         
63828         me.callParent();
63829         if(me.selectOnFocus || me.emptyText){
63830             me.mon(el, 'mousedown', me.onMouseDown, me);
63831         }
63832         if(me.maskRe || (me.vtype && me.disableKeyFilter !== true && (me.maskRe = Ext.form.field.VTypes[me.vtype+'Mask']))){
63833             me.mon(el, 'keypress', me.filterKeys, me);
63834         }
63835
63836         if (me.enableKeyEvents) {
63837             me.mon(el, {
63838                 scope: me,
63839                 keyup: me.onKeyUp,
63840                 keydown: me.onKeyDown,
63841                 keypress: me.onKeyPress
63842             });
63843         }
63844     },
63845
63846     
63847     isEqual: function(value1, value2) {
63848         return String(Ext.value(value1, '')) === String(Ext.value(value2, ''));
63849     },
63850
63851     
63852     onChange: function() {
63853         this.callParent();
63854         this.autoSize();
63855     },
63856     
63857     afterRender: function(){
63858         var me = this;
63859         if (me.enforceMaxLength) {
63860             me.inputEl.dom.maxLength = me.maxLength;
63861         }
63862         me.applyEmptyText();
63863         me.autoSize();
63864         me.callParent();
63865     },
63866
63867     onMouseDown: function(e){
63868         var me = this;
63869         if(!me.hasFocus){
63870             me.mon(me.inputEl, 'mouseup', Ext.emptyFn, me, { single: true, preventDefault: true });
63871         }
63872     },
63873
63874     
63875     processRawValue: function(value) {
63876         var me = this,
63877             stripRe = me.stripCharsRe,
63878             newValue;
63879             
63880         if (stripRe) {
63881             newValue = value.replace(stripRe, '');
63882             if (newValue !== value) {
63883                 me.setRawValue(newValue);
63884                 value = newValue;
63885             }
63886         }
63887         return value;
63888     },
63889
63890     
63891     onDisable: function(){
63892         this.callParent();
63893         if (Ext.isIE) {
63894             this.inputEl.dom.unselectable = 'on';
63895         }
63896     },
63897
63898     
63899     onEnable: function(){
63900         this.callParent();
63901         if (Ext.isIE) {
63902             this.inputEl.dom.unselectable = '';
63903         }
63904     },
63905
63906     onKeyDown: function(e) {
63907         this.fireEvent('keydown', this, e);
63908     },
63909
63910     onKeyUp: function(e) {
63911         this.fireEvent('keyup', this, e);
63912     },
63913
63914     onKeyPress: function(e) {
63915         this.fireEvent('keypress', this, e);
63916     },
63917
63918     
63919     reset : function(){
63920         this.callParent();
63921         this.applyEmptyText();
63922     },
63923
63924     applyEmptyText : function(){
63925         var me = this,
63926             emptyText = me.emptyText,
63927             isEmpty;
63928
63929         if (me.rendered && emptyText) {
63930             isEmpty = me.getRawValue().length < 1 && !me.hasFocus;
63931             
63932             if (Ext.supports.Placeholder) {
63933                 me.inputEl.dom.placeholder = emptyText;
63934             } else if (isEmpty) {
63935                 me.setRawValue(emptyText);
63936             }
63937             
63938             
63939             
63940             if (isEmpty) {
63941                 me.inputEl.addCls(me.emptyCls);
63942             }
63943
63944             me.autoSize();
63945         }
63946     },
63947
63948     
63949     preFocus : function(){
63950         var me = this,
63951             inputEl = me.inputEl,
63952             emptyText = me.emptyText,
63953             isEmpty;
63954
63955         if (emptyText && !Ext.supports.Placeholder && inputEl.dom.value === emptyText) {
63956             me.setRawValue('');
63957             isEmpty = true;
63958             inputEl.removeCls(me.emptyCls);
63959         } else if (Ext.supports.Placeholder) {
63960             me.inputEl.removeCls(me.emptyCls);
63961         }
63962         if (me.selectOnFocus || isEmpty) {
63963             inputEl.dom.select();
63964         }
63965     },
63966
63967     onFocus: function() {
63968         var me = this;
63969         me.callParent(arguments);
63970         if (me.emptyText) {
63971             me.autoSize();
63972         }
63973     },
63974
63975     
63976     postBlur : function(){
63977         this.applyEmptyText();
63978     },
63979
63980     
63981     filterKeys : function(e){
63982         if(e.ctrlKey){
63983             return;
63984         }
63985         var key = e.getKey(),
63986             charCode = String.fromCharCode(e.getCharCode());
63987             
63988         if(Ext.isGecko && (e.isNavKeyPress() || key === e.BACKSPACE || (key === e.DELETE && e.button === -1))){
63989             return;
63990         }
63991         
63992         if(!Ext.isGecko && e.isSpecialKey() && !charCode){
63993             return;
63994         }
63995         if(!this.maskRe.test(charCode)){
63996             e.stopEvent();
63997         }
63998     },
63999
64000     
64001     getRawValue: function() {
64002         var me = this,
64003             v = me.callParent();
64004         if (v === me.emptyText) {
64005             v = '';
64006         }
64007         return v;
64008     },
64009
64010     
64011     setValue: function(value) {
64012         var me = this,
64013             inputEl = me.inputEl;
64014         
64015         if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
64016             inputEl.removeCls(me.emptyCls);
64017         }
64018         
64019         me.callParent(arguments);
64020
64021         me.applyEmptyText();
64022         return me;
64023     },
64024
64025     
64026     getErrors: function(value) {
64027         var me = this,
64028             errors = me.callParent(arguments),
64029             validator = me.validator,
64030             emptyText = me.emptyText,
64031             allowBlank = me.allowBlank,
64032             vtype = me.vtype,
64033             vtypes = Ext.form.field.VTypes,
64034             regex = me.regex,
64035             format = Ext.String.format,
64036             msg;
64037
64038         value = value || me.processRawValue(me.getRawValue());
64039
64040         if (Ext.isFunction(validator)) {
64041             msg = validator.call(me, value);
64042             if (msg !== true) {
64043                 errors.push(msg);
64044             }
64045         }
64046
64047         if (value.length < 1 || value === emptyText) {
64048             if (!allowBlank) {
64049                 errors.push(me.blankText);
64050             }
64051             
64052             return errors;
64053         }
64054
64055         if (value.length < me.minLength) {
64056             errors.push(format(me.minLengthText, me.minLength));
64057         }
64058
64059         if (value.length > me.maxLength) {
64060             errors.push(format(me.maxLengthText, me.maxLength));
64061         }
64062
64063         if (vtype) {
64064             if(!vtypes[vtype](value, me)){
64065                 errors.push(me.vtypeText || vtypes[vtype +'Text']);
64066             }
64067         }
64068
64069         if (regex && !regex.test(value)) {
64070             errors.push(me.regexText || me.invalidText);
64071         }
64072
64073         return errors;
64074     },
64075
64076     
64077     selectText : function(start, end){
64078         var me = this,
64079             v = me.getRawValue(),
64080             doFocus = true,
64081             el = me.inputEl.dom,
64082             undef,
64083             range;
64084             
64085         if (v.length > 0) {
64086             start = start === undef ? 0 : start;
64087             end = end === undef ? v.length : end;
64088             if (el.setSelectionRange) {
64089                 el.setSelectionRange(start, end);
64090             }
64091             else if(el.createTextRange) {
64092                 range = el.createTextRange();
64093                 range.moveStart('character', start);
64094                 range.moveEnd('character', end - v.length);
64095                 range.select();
64096             }
64097             doFocus = Ext.isGecko || Ext.isOpera;
64098         }
64099         if (doFocus) {
64100             me.focus();
64101         }
64102     },
64103
64104     
64105     autoSize: function() {
64106         var me = this,
64107             width;
64108         if (me.grow && me.rendered) {
64109             me.doComponentLayout();
64110             width = me.inputEl.getWidth();
64111             if (width !== me.lastInputWidth) {
64112                 me.fireEvent('autosize', width);
64113                 me.lastInputWidth = width;
64114             }
64115         }
64116     },
64117
64118     initAria: function() {
64119         this.callParent();
64120         this.getActionEl().dom.setAttribute('aria-required', this.allowBlank === false);
64121     },
64122
64123     
64124     getBodyNaturalWidth: function() {
64125         return Math.round(this.size * 6.5) + 20;
64126     }
64127
64128 });
64129
64130
64131 Ext.define('Ext.form.field.TextArea', {
64132     extend:'Ext.form.field.Text',
64133     alias: ['widget.textareafield', 'widget.textarea'],
64134     alternateClassName: 'Ext.form.TextArea',
64135     requires: ['Ext.XTemplate', 'Ext.layout.component.field.TextArea'],
64136
64137     fieldSubTpl: [
64138         '<textarea id="{id}" ',
64139             '<tpl if="name">name="{name}" </tpl>',
64140             '<tpl if="rows">rows="{rows}" </tpl>',
64141             '<tpl if="cols">cols="{cols}" </tpl>',
64142             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
64143             'class="{fieldCls} {typeCls}" ',
64144             'autocomplete="off">',
64145         '</textarea>',
64146         {
64147             compiled: true,
64148             disableFormats: true
64149         }
64150     ],
64151
64152     
64153     growMin: 60,
64154
64155     
64156     growMax: 1000,
64157
64158     
64159     growAppend: '\n-',
64160
64161     
64162     cols: 20,
64163
64164     
64165     rows: 4,
64166
64167     
64168     enterIsSpecial: false,
64169
64170     
64171     preventScrollbars: false,
64172
64173     
64174     componentLayout: 'textareafield',
64175
64176     
64177     onRender: function(ct, position) {
64178         var me = this;
64179         Ext.applyIf(me.subTplData, {
64180             cols: me.cols,
64181             rows: me.rows
64182         });
64183
64184         me.callParent(arguments);
64185     },
64186
64187     
64188     afterRender: function(){
64189         var me = this;
64190
64191         me.callParent(arguments);
64192
64193         if (me.grow) {
64194             if (me.preventScrollbars) {
64195                 me.inputEl.setStyle('overflow', 'hidden');
64196             }
64197             me.inputEl.setHeight(me.growMin);
64198         }
64199     },
64200
64201     
64202     fireKey: function(e) {
64203         if (e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() !== e.ENTER || e.hasModifier()))) {
64204             this.fireEvent('specialkey', this, e);
64205         }
64206     },
64207
64208     
64209     autoSize: function() {
64210         var me = this,
64211             height;
64212
64213         if (me.grow && me.rendered) {
64214             me.doComponentLayout();
64215             height = me.inputEl.getHeight();
64216             if (height !== me.lastInputHeight) {
64217                 me.fireEvent('autosize', height);
64218                 me.lastInputHeight = height;
64219             }
64220         }
64221     },
64222
64223     
64224     initAria: function() {
64225         this.callParent(arguments);
64226         this.getActionEl().dom.setAttribute('aria-multiline', true);
64227     },
64228
64229     
64230     getBodyNaturalWidth: function() {
64231         return Math.round(this.cols * 6.5) + 20;
64232     }
64233
64234 });
64235
64236
64237
64238 Ext.define('Ext.window.MessageBox', {
64239     extend: 'Ext.window.Window',
64240
64241     requires: [
64242         'Ext.toolbar.Toolbar',
64243         'Ext.form.field.Text',
64244         'Ext.form.field.TextArea',
64245         'Ext.button.Button',
64246         'Ext.layout.container.Anchor',
64247         'Ext.layout.container.HBox',
64248         'Ext.ProgressBar'
64249     ],
64250
64251     alternateClassName: 'Ext.MessageBox',
64252
64253     alias: 'widget.messagebox',
64254
64255     
64256     OK : 1,
64257     
64258     YES : 2,
64259     
64260     NO : 4,
64261     
64262     CANCEL : 8,
64263     
64264     OKCANCEL : 9,
64265     
64266     YESNO : 6,
64267     
64268     YESNOCANCEL : 14,
64269     
64270     INFO : 'ext-mb-info',
64271     
64272     WARNING : 'ext-mb-warning',
64273     
64274     QUESTION : 'ext-mb-question',
64275     
64276     ERROR : 'ext-mb-error',
64277
64278     
64279     hideMode: 'offsets',
64280     closeAction: 'hide',
64281     resizable: false,
64282     title: '&#160;',
64283
64284     width: 600,
64285     height: 500,
64286     minWidth: 250,
64287     maxWidth: 600,
64288     minHeight: 110,
64289     maxHeight: 500,
64290     constrain: true,
64291
64292     cls: Ext.baseCSSPrefix + 'message-box',
64293
64294     layout: {
64295         type: 'anchor'
64296     },
64297
64298     
64299     defaultTextHeight : 75,
64300     
64301     minProgressWidth : 250,
64302     
64303     minPromptWidth: 250,
64304     
64305     buttonText: {
64306         ok: 'OK',
64307         yes: 'Yes',
64308         no: 'No',
64309         cancel: 'Cancel'
64310     },
64311
64312     buttonIds: [
64313         'ok', 'yes', 'no', 'cancel'
64314     ],
64315
64316     titleText: {
64317         confirm: 'Confirm',
64318         prompt: 'Prompt',
64319         wait: 'Loading...',
64320         alert: 'Attention'
64321     },
64322
64323     iconHeight: 35,
64324
64325     makeButton: function(btnIdx) {
64326         var btnId = this.buttonIds[btnIdx];
64327         return Ext.create('Ext.button.Button', {
64328             handler: this.btnCallback,
64329             itemId: btnId,
64330             scope: this,
64331             text: this.buttonText[btnId],
64332             minWidth: 75
64333         });
64334     },
64335
64336     btnCallback: function(btn) {
64337         var me = this,
64338             value,
64339             field;
64340
64341         if (me.cfg.prompt || me.cfg.multiline) {
64342             if (me.cfg.multiline) {
64343                 field = me.textArea;
64344             } else {
64345                 field = me.textField;
64346             }
64347             value = field.getValue();
64348             field.reset();
64349         }
64350
64351         
64352         btn.blur();
64353         me.hide();
64354         me.userCallback(btn.itemId, value, me.cfg);
64355     },
64356
64357     hide: function() {
64358         var me = this;
64359         me.dd.endDrag();
64360         me.progressBar.reset();
64361         me.removeCls(me.cfg.cls);
64362         me.callParent();
64363     },
64364
64365     initComponent: function() {
64366         var me = this,
64367             i, button;
64368
64369         me.title = '&#160;';
64370
64371         me.topContainer = Ext.create('Ext.container.Container', {
64372             anchor: '100%',
64373             style: {
64374                 padding: '10px',
64375                 overflow: 'hidden'
64376             },
64377             items: [
64378                 me.iconComponent = Ext.create('Ext.Component', {
64379                     cls: 'ext-mb-icon',
64380                     width: 50,
64381                     height: me.iconHeight,
64382                     style: {
64383                         'float': 'left'
64384                     }
64385                 }),
64386                 me.promptContainer = Ext.create('Ext.container.Container', {
64387                     layout: {
64388                         type: 'anchor'
64389                     },
64390                     items: [
64391                         me.msg = Ext.create('Ext.Component', {
64392                             autoEl: { tag: 'span' },
64393                             cls: 'ext-mb-text'
64394                         }),
64395                         me.textField = Ext.create('Ext.form.field.Text', {
64396                             anchor: '100%',
64397                             enableKeyEvents: true,
64398                             listeners: {
64399                                 keydown: me.onPromptKey,
64400                                 scope: me
64401                             }
64402                         }),
64403                         me.textArea = Ext.create('Ext.form.field.TextArea', {
64404                             anchor: '100%',
64405                             height: 75
64406                         })
64407                     ]
64408                 })
64409             ]
64410         });
64411         me.progressBar = Ext.create('Ext.ProgressBar', {
64412             anchor: '-10',
64413             style: 'margin-left:10px'
64414         });
64415
64416         me.items = [me.topContainer, me.progressBar];
64417
64418         
64419         me.msgButtons = [];
64420         for (i = 0; i < 4; i++) {
64421             button = me.makeButton(i);
64422             me.msgButtons[button.itemId] = button;
64423             me.msgButtons.push(button);
64424         }
64425         me.bottomTb = Ext.create('Ext.toolbar.Toolbar', {
64426             ui: 'footer',
64427             dock: 'bottom',
64428             layout: {
64429                 pack: 'center'
64430             },
64431             items: [
64432                 me.msgButtons[0],
64433                 me.msgButtons[1],
64434                 me.msgButtons[2],
64435                 me.msgButtons[3]
64436             ]
64437         });
64438         me.dockedItems = [me.bottomTb];
64439
64440         me.callParent();
64441     },
64442
64443     onPromptKey: function(textField, e) {
64444         var me = this,
64445             blur;
64446
64447         if (e.keyCode === Ext.EventObject.RETURN || e.keyCode === 10) {
64448             if (me.msgButtons.ok.isVisible()) {
64449                 blur = true;
64450                 me.msgButtons.ok.handler.call(me, me.msgButtons.ok);
64451             } else if (me.msgButtons.yes.isVisible()) {
64452                 me.msgButtons.yes.handler.call(me, me.msgButtons.yes);
64453                 blur = true;
64454             }
64455
64456             if (blur) {
64457                 me.textField.blur();
64458             }
64459         }
64460     },
64461
64462     reconfigure: function(cfg) {
64463         var me = this,
64464             buttons = cfg.buttons || 0,
64465             hideToolbar = true,
64466             initialWidth = me.maxWidth,
64467             i;
64468
64469         cfg = cfg || {};
64470         me.cfg = cfg;
64471         if (cfg.width) {
64472             initialWidth = cfg.width;
64473         }
64474
64475         
64476         delete me.defaultFocus;
64477
64478         
64479         me.animateTarget = cfg.animateTarget || undefined;
64480
64481         
64482         me.modal = cfg.modal !== false;
64483
64484         
64485         if (cfg.title) {
64486             me.setTitle(cfg.title||'&#160;');
64487         }
64488
64489         if (!me.rendered) {
64490             me.width = initialWidth;
64491             me.render(Ext.getBody());
64492         } else {
64493             me.hidden = false;
64494             me.setSize(initialWidth, me.maxHeight);
64495         }
64496         me.setPosition(-10000, -10000);
64497
64498         
64499         me.closable = cfg.closable && !cfg.wait;
64500         if (cfg.closable === false) {
64501             me.tools.close.hide();
64502         } else {
64503             me.tools.close.show();
64504         }
64505
64506         
64507         if (!cfg.title && !me.closable) {
64508             me.header.hide();
64509         } else {
64510             me.header.show();
64511         }
64512
64513         
64514         me.liveDrag = !cfg.proxyDrag;
64515
64516         
64517         me.userCallback = Ext.Function.bind(cfg.callback ||cfg.fn || Ext.emptyFn, cfg.scope || Ext.global);
64518
64519         
64520         me.setIcon(cfg.icon);
64521
64522         
64523         if (cfg.msg) {
64524             me.msg.update(cfg.msg);
64525             me.msg.show();
64526         } else {
64527             me.msg.hide();
64528         }
64529
64530         
64531         if (cfg.prompt || cfg.multiline) {
64532             me.multiline = cfg.multiline;
64533             if (cfg.multiline) {
64534                 me.textArea.setValue(cfg.value);
64535                 me.textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight);
64536                 me.textArea.show();
64537                 me.textField.hide();
64538                 me.defaultFocus = me.textArea;
64539             } else {
64540                 me.textField.setValue(cfg.value);
64541                 me.textArea.hide();
64542                 me.textField.show();
64543                 me.defaultFocus = me.textField;
64544             }
64545         } else {
64546             me.textArea.hide();
64547             me.textField.hide();
64548         }
64549
64550         
64551         if (cfg.progress || cfg.wait) {
64552             me.progressBar.show();
64553             me.updateProgress(0, cfg.progressText);
64554             if(cfg.wait === true){
64555                 me.progressBar.wait(cfg.waitConfig);
64556             }
64557         } else {
64558             me.progressBar.hide();
64559         }
64560
64561         
64562         for (i = 0; i < 4; i++) {
64563             if (buttons & Math.pow(2, i)) {
64564
64565                 
64566                 if (!me.defaultFocus) {
64567                     me.defaultFocus = me.msgButtons[i];
64568                 }
64569                 me.msgButtons[i].show();
64570                 hideToolbar = false;
64571             } else {
64572                 me.msgButtons[i].hide();
64573             }
64574         }
64575
64576         
64577         if (hideToolbar) {
64578             me.bottomTb.hide();
64579         } else {
64580             me.bottomTb.show();
64581         }
64582         me.hidden = true;
64583     },
64584
64585     
64586     show: function(cfg) {
64587         var me = this;
64588
64589         me.reconfigure(cfg);
64590         me.addCls(cfg.cls);
64591         if (cfg.animateTarget) {
64592             me.doAutoSize(false);
64593             me.callParent();
64594         } else {
64595             me.callParent();
64596             me.doAutoSize(true);
64597         }
64598         return me;
64599     },
64600
64601     afterShow: function(){
64602         if (this.animateTarget) {
64603             this.center();
64604         }
64605         this.callParent(arguments);
64606     },
64607
64608     doAutoSize: function(center) {
64609         var me = this,
64610             icon = me.iconComponent,
64611             iconHeight = me.iconHeight;
64612
64613         if (!Ext.isDefined(me.frameWidth)) {
64614             me.frameWidth = me.el.getWidth() - me.body.getWidth();
64615         }
64616
64617         
64618         icon.setHeight(iconHeight);
64619
64620         
64621         me.minWidth = me.cfg.minWidth || Ext.getClass(this).prototype.minWidth;
64622
64623         
64624         
64625         me.topContainer.doLayout();
64626         if (Ext.isIE6 || Ext.isIEQuirks) {
64627             
64628             
64629             
64630             me.textField.setCalculatedSize(9);
64631             me.textArea.setCalculatedSize(9);
64632         }
64633         var width = me.cfg.width || me.msg.getWidth() + icon.getWidth() + 25, 
64634             height = (me.header.rendered ? me.header.getHeight() : 0) +
64635             Math.max(me.promptContainer.getHeight(), icon.getHeight()) +
64636             me.progressBar.getHeight() +
64637             (me.bottomTb.rendered ? me.bottomTb.getHeight() : 0) + 20 ;
64638
64639         
64640         icon.setHeight(Math.max(iconHeight, me.msg.getHeight()));
64641         me.setSize(width + me.frameWidth, height + me.frameWidth);
64642         if (center) {
64643             me.center();
64644         }
64645         return me;
64646     },
64647
64648     updateText: function(text) {
64649         this.msg.update(text);
64650         return this.doAutoSize(true);
64651     },
64652
64653     
64654     setIcon : function(icon) {
64655         var me = this;
64656         me.iconComponent.removeCls(me.iconCls);
64657         if (icon) {
64658             me.iconComponent.show();
64659             me.iconComponent.addCls(Ext.baseCSSPrefix + 'dlg-icon');
64660             me.iconComponent.addCls(me.iconCls = icon);
64661         } else {
64662             me.iconComponent.removeCls(Ext.baseCSSPrefix + 'dlg-icon');
64663             me.iconComponent.hide();
64664         }
64665         return me;
64666     },
64667
64668     
64669     updateProgress : function(value, progressText, msg){
64670         this.progressBar.updateProgress(value, progressText);
64671         if (msg){
64672             this.updateText(msg);
64673         }
64674         return this;
64675     },
64676
64677     onEsc: function() {
64678         if (this.closable !== false) {
64679             this.callParent(arguments);
64680         }
64681     },
64682
64683     
64684     confirm: function(cfg, msg, fn, scope) {
64685         if (Ext.isString(cfg)) {
64686             cfg = {
64687                 title: cfg,
64688                 icon: 'ext-mb-question',
64689                 msg: msg,
64690                 buttons: this.YESNO,
64691                 callback: fn,
64692                 scope: scope
64693             };
64694         }
64695         return this.show(cfg);
64696     },
64697
64698     
64699     prompt : function(cfg, msg, fn, scope, multiline, value){
64700         if (Ext.isString(cfg)) {
64701             cfg = {
64702                 prompt: true,
64703                 title: cfg,
64704                 minWidth: this.minPromptWidth,
64705                 msg: msg,
64706                 buttons: this.OKCANCEL,
64707                 callback: fn,
64708                 scope: scope,
64709                 multiline: multiline,
64710                 value: value
64711             };
64712         }
64713         return this.show(cfg);
64714     },
64715
64716     
64717     wait : function(cfg, title, config){
64718         if (Ext.isString(cfg)) {
64719             cfg = {
64720                 title : title,
64721                 msg : cfg,
64722                 closable: false,
64723                 wait: true,
64724                 modal: true,
64725                 minWidth: this.minProgressWidth,
64726                 waitConfig: config
64727             };
64728         }
64729         return this.show(cfg);
64730     },
64731
64732     
64733     alert: function(cfg, msg, fn, scope) {
64734         if (Ext.isString(cfg)) {
64735             cfg = {
64736                 title : cfg,
64737                 msg : msg,
64738                 buttons: this.OK,
64739                 fn: fn,
64740                 scope : scope,
64741                 minWidth: this.minWidth
64742             };
64743         }
64744         return this.show(cfg);
64745     },
64746
64747     
64748     progress : function(cfg, msg, progressText){
64749         if (Ext.isString(cfg)) {
64750             cfg = {
64751                 title: cfg,
64752                 msg: msg,
64753                 progressText: progressText
64754             };
64755         }
64756         return this.show(cfg);
64757     }
64758 }, function() {
64759     Ext.MessageBox = Ext.Msg = new this();
64760 });
64761
64762
64763
64764
64765 Ext.define('Ext.form.Basic', {
64766     extend: 'Ext.util.Observable',
64767     alternateClassName: 'Ext.form.BasicForm',
64768     requires: ['Ext.util.MixedCollection', 'Ext.form.action.Load', 'Ext.form.action.Submit',
64769                'Ext.window.MessageBox', 'Ext.data.Errors', 'Ext.util.DelayedTask'],
64770
64771     constructor: function(owner, config) {
64772         var me = this,
64773             onItemAddOrRemove = me.onItemAddOrRemove;
64774
64775         
64776         me.owner = owner;
64777
64778         
64779         me.mon(owner, {
64780             add: onItemAddOrRemove,
64781             remove: onItemAddOrRemove,
64782             scope: me
64783         });
64784
64785         Ext.apply(me, config);
64786
64787         
64788         if (Ext.isString(me.paramOrder)) {
64789             me.paramOrder = me.paramOrder.split(/[\s,|]/);
64790         }
64791
64792         me.checkValidityTask = Ext.create('Ext.util.DelayedTask', me.checkValidity, me);
64793
64794         me.addEvents(
64795             
64796             'beforeaction',
64797             
64798             'actionfailed',
64799             
64800             'actioncomplete',
64801             
64802             'validitychange',
64803             
64804             'dirtychange'
64805         );
64806         me.callParent();
64807     },
64808
64809     
64810     initialize: function(){
64811         this.initialized = true;
64812         this.onValidityChange(!this.hasInvalidField());
64813     },
64814
64815     
64816     
64817     
64818
64819     
64820
64821     
64822
64823     
64824     timeout: 30,
64825
64826     
64827
64828     
64829
64830     
64831     paramsAsHash: false,
64832
64833     
64834     waitTitle: 'Please Wait...',
64835
64836     
64837     trackResetOnLoad: false,
64838
64839     
64840
64841     
64842
64843
64844     
64845     wasDirty: false,
64846
64847
64848     
64849     destroy: function() {
64850         this.clearListeners();
64851         this.checkValidityTask.cancel();
64852     },
64853
64854     
64855     onItemAddOrRemove: function(parent, child) {
64856         var me = this,
64857             isAdding = !!child.ownerCt,
64858             isContainer = child.isContainer;
64859
64860         function handleField(field) {
64861             
64862             me[isAdding ? 'mon' : 'mun'](field, {
64863                 validitychange: me.checkValidity,
64864                 dirtychange: me.checkDirty,
64865                 scope: me,
64866                 buffer: 100 
64867             });
64868             
64869             delete me._fields;
64870         }
64871
64872         if (child.isFormField) {
64873             handleField(child);
64874         }
64875         else if (isContainer) {
64876             
64877             Ext.Array.forEach(child.query('[isFormField]'), handleField);
64878         }
64879
64880         
64881         delete this._boundItems;
64882
64883         
64884         
64885         if (me.initialized) {
64886             me.checkValidityTask.delay(10);
64887         }
64888     },
64889
64890     
64891     getFields: function() {
64892         var fields = this._fields;
64893         if (!fields) {
64894             fields = this._fields = Ext.create('Ext.util.MixedCollection');
64895             fields.addAll(this.owner.query('[isFormField]'));
64896         }
64897         return fields;
64898     },
64899
64900     getBoundItems: function() {
64901         var boundItems = this._boundItems;
64902         if (!boundItems) {
64903             boundItems = this._boundItems = Ext.create('Ext.util.MixedCollection');
64904             boundItems.addAll(this.owner.query('[formBind]'));
64905         }
64906         return boundItems;
64907     },
64908
64909     
64910     hasInvalidField: function() {
64911         return !!this.getFields().findBy(function(field) {
64912             var preventMark = field.preventMark,
64913                 isValid;
64914             field.preventMark = true;
64915             isValid = field.isValid();
64916             field.preventMark = preventMark;
64917             return !isValid;
64918         });
64919     },
64920
64921     
64922     isValid: function() {
64923         var me = this,
64924             invalid;
64925         me.batchLayouts(function() {
64926             invalid = me.getFields().filterBy(function(field) {
64927                 return !field.validate();
64928             });
64929         });
64930         return invalid.length < 1;
64931     },
64932
64933     
64934     checkValidity: function() {
64935         var me = this,
64936             valid = !me.hasInvalidField();
64937         if (valid !== me.wasValid) {
64938             me.onValidityChange(valid);
64939             me.fireEvent('validitychange', me, valid);
64940             me.wasValid = valid;
64941         }
64942     },
64943
64944     
64945     onValidityChange: function(valid) {
64946         var boundItems = this.getBoundItems();
64947         if (boundItems) {
64948             boundItems.each(function(cmp) {
64949                 if (cmp.disabled === valid) {
64950                     cmp.setDisabled(!valid);
64951                 }
64952             });
64953         }
64954     },
64955
64956     
64957     isDirty: function() {
64958         return !!this.getFields().findBy(function(f) {
64959             return f.isDirty();
64960         });
64961     },
64962
64963     
64964     checkDirty: function() {
64965         var dirty = this.isDirty();
64966         if (dirty !== this.wasDirty) {
64967             this.fireEvent('dirtychange', this, dirty);
64968             this.wasDirty = dirty;
64969         }
64970     },
64971
64972     
64973     hasUpload: function() {
64974         return !!this.getFields().findBy(function(f) {
64975             return f.isFileUpload();
64976         });
64977     },
64978
64979     
64980     doAction: function(action, options) {
64981         if (Ext.isString(action)) {
64982             action = Ext.ClassManager.instantiateByAlias('formaction.' + action, Ext.apply({}, options, {form: this}));
64983         }
64984         if (this.fireEvent('beforeaction', this, action) !== false) {
64985             this.beforeAction(action);
64986             Ext.defer(action.run, 100, action);
64987         }
64988         return this;
64989     },
64990
64991     
64992     submit: function(options) {
64993         return this.doAction(this.standardSubmit ? 'standardsubmit' : this.api ? 'directsubmit' : 'submit', options);
64994     },
64995
64996     
64997     load: function(options) {
64998         return this.doAction(this.api ? 'directload' : 'load', options);
64999     },
65000
65001     
65002     updateRecord: function(record) {
65003         var fields = record.fields,
65004             values = this.getFieldValues(),
65005             name,
65006             obj = {};
65007
65008         fields.each(function(f) {
65009             name = f.name;
65010             if (name in values) {
65011                 obj[name] = values[name];
65012             }
65013         });
65014
65015         record.beginEdit();
65016         record.set(obj);
65017         record.endEdit();
65018
65019         return this;
65020     },
65021
65022     
65023     loadRecord: function(record) {
65024         this._record = record;
65025         return this.setValues(record.data);
65026     },
65027     
65028     
65029     getRecord: function() {
65030         return this._record;
65031     },
65032
65033     
65034     beforeAction: function(action) {
65035         var waitMsg = action.waitMsg,
65036             maskCls = Ext.baseCSSPrefix + 'mask-loading',
65037             waitMsgTarget;
65038
65039         
65040         this.getFields().each(function(f) {
65041             if (f.isFormField && f.syncValue) {
65042                 f.syncValue();
65043             }
65044         });
65045
65046         if (waitMsg) {
65047             waitMsgTarget = this.waitMsgTarget;
65048             if (waitMsgTarget === true) {
65049                 this.owner.el.mask(waitMsg, maskCls);
65050             } else if (waitMsgTarget) {
65051                 waitMsgTarget = this.waitMsgTarget = Ext.get(waitMsgTarget);
65052                 waitMsgTarget.mask(waitMsg, maskCls);
65053             } else {
65054                 Ext.MessageBox.wait(waitMsg, action.waitTitle || this.waitTitle);
65055             }
65056         }
65057     },
65058
65059     
65060     afterAction: function(action, success) {
65061         if (action.waitMsg) {
65062             var MessageBox = Ext.MessageBox,
65063                 waitMsgTarget = this.waitMsgTarget;
65064             if (waitMsgTarget === true) {
65065                 this.owner.el.unmask();
65066             } else if (waitMsgTarget) {
65067                 waitMsgTarget.unmask();
65068             } else {
65069                 MessageBox.updateProgress(1);
65070                 MessageBox.hide();
65071             }
65072         }
65073         if (success) {
65074             if (action.reset) {
65075                 this.reset();
65076             }
65077             Ext.callback(action.success, action.scope || action, [this, action]);
65078             this.fireEvent('actioncomplete', this, action);
65079         } else {
65080             Ext.callback(action.failure, action.scope || action, [this, action]);
65081             this.fireEvent('actionfailed', this, action);
65082         }
65083     },
65084
65085
65086     
65087     findField: function(id) {
65088         return this.getFields().findBy(function(f) {
65089             return f.id === id || f.getName() === id;
65090         });
65091     },
65092
65093
65094     
65095     markInvalid: function(errors) {
65096         var me = this;
65097
65098         function mark(fieldId, msg) {
65099             var field = me.findField(fieldId);
65100             if (field) {
65101                 field.markInvalid(msg);
65102             }
65103         }
65104
65105         if (Ext.isArray(errors)) {
65106             Ext.each(errors, function(err) {
65107                 mark(err.id, err.msg);
65108             });
65109         }
65110         else if (errors instanceof Ext.data.Errors) {
65111             errors.each(function(err) {
65112                 mark(err.field, err.message);
65113             });
65114         }
65115         else {
65116             Ext.iterate(errors, mark);
65117         }
65118         return this;
65119     },
65120
65121     
65122     setValues: function(values) {
65123         var me = this;
65124
65125         function setVal(fieldId, val) {
65126             var field = me.findField(fieldId);
65127             if (field) {
65128                 field.setValue(val);
65129                 if (me.trackResetOnLoad) {
65130                     field.resetOriginalValue();
65131                 }
65132             }
65133         }
65134
65135         if (Ext.isArray(values)) {
65136             
65137             Ext.each(values, function(val) {
65138                 setVal(val.id, val.value);
65139             });
65140         } else {
65141             
65142             Ext.iterate(values, setVal);
65143         }
65144         return this;
65145     },
65146
65147     
65148     getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) {
65149         var values = {};
65150
65151         this.getFields().each(function(field) {
65152             if (!dirtyOnly || field.isDirty()) {
65153                 var data = field[useDataValues ? 'getModelData' : 'getSubmitData'](includeEmptyText);
65154                 if (Ext.isObject(data)) {
65155                     Ext.iterate(data, function(name, val) {
65156                         if (includeEmptyText && val === '') {
65157                             val = field.emptyText || '';
65158                         }
65159                         if (name in values) {
65160                             var bucket = values[name],
65161                                 isArray = Ext.isArray;
65162                             if (!isArray(bucket)) {
65163                                 bucket = values[name] = [bucket];
65164                             }
65165                             if (isArray(val)) {
65166                                 values[name] = bucket.concat(val);
65167                             } else {
65168                                 bucket.push(val);
65169                             }
65170                         } else {
65171                             values[name] = val;
65172                         }
65173                     });
65174                 }
65175             }
65176         });
65177
65178         if (asString) {
65179             values = Ext.Object.toQueryString(values);
65180         }
65181         return values;
65182     },
65183
65184     
65185     getFieldValues: function(dirtyOnly) {
65186         return this.getValues(false, dirtyOnly, false, true);
65187     },
65188
65189     
65190     clearInvalid: function() {
65191         var me = this;
65192         me.batchLayouts(function() {
65193             me.getFields().each(function(f) {
65194                 f.clearInvalid();
65195             });
65196         });
65197         return me;
65198     },
65199
65200     
65201     reset: function() {
65202         var me = this;
65203         me.batchLayouts(function() {
65204             me.getFields().each(function(f) {
65205                 f.reset();
65206             });
65207         });
65208         return me;
65209     },
65210
65211     
65212     applyToFields: function(obj) {
65213         this.getFields().each(function(f) {
65214             Ext.apply(f, obj);
65215         });
65216         return this;
65217     },
65218
65219     
65220     applyIfToFields: function(obj) {
65221         this.getFields().each(function(f) {
65222             Ext.applyIf(f, obj);
65223         });
65224         return this;
65225     },
65226
65227     
65228     batchLayouts: function(fn) {
65229         var me = this,
65230             suspended = new Ext.util.HashMap();
65231
65232         
65233         me.getFields().each(function(field) {
65234             var ownerCt = field.ownerCt;
65235             if (!suspended.contains(ownerCt)) {
65236                 suspended.add(ownerCt);
65237                 ownerCt.oldSuspendLayout = ownerCt.suspendLayout;
65238                 ownerCt.suspendLayout = true;
65239             }
65240         });
65241
65242         
65243         fn();
65244
65245         
65246         suspended.each(function(id, ct) {
65247             ct.suspendLayout = ct.oldSuspendLayout;
65248             delete ct.oldSuspendLayout;
65249         });
65250
65251         
65252         me.owner.doComponentLayout();
65253     }
65254 });
65255
65256
65257 Ext.define('Ext.form.FieldAncestor', {
65258
65259     
65260
65261
65262     
65263     initFieldAncestor: function() {
65264         var me = this,
65265             onSubtreeChange = me.onFieldAncestorSubtreeChange;
65266
65267         me.addEvents(
65268             
65269             'fieldvaliditychange',
65270
65271             
65272             'fielderrorchange'
65273         );
65274
65275         
65276         me.on('add', onSubtreeChange, me);
65277         me.on('remove', onSubtreeChange, me);
65278
65279         me.initFieldDefaults();
65280     },
65281
65282     
65283     initFieldDefaults: function() {
65284         if (!this.fieldDefaults) {
65285             this.fieldDefaults = {};
65286         }
65287     },
65288
65289     
65290     onFieldAncestorSubtreeChange: function(parent, child) {
65291         var me = this,
65292             isAdding = !!child.ownerCt;
65293
65294         function handleCmp(cmp) {
65295             var isLabelable = cmp.isFieldLabelable,
65296                 isField = cmp.isFormField;
65297             if (isLabelable || isField) {
65298                 if (isLabelable) {
65299                     me['onLabelable' + (isAdding ? 'Added' : 'Removed')](cmp);
65300                 }
65301                 if (isField) {
65302                     me['onField' + (isAdding ? 'Added' : 'Removed')](cmp);
65303                 }
65304             }
65305             else if (cmp.isContainer) {
65306                 Ext.Array.forEach(cmp.getRefItems(), handleCmp);
65307             }
65308         }
65309         handleCmp(child);
65310     },
65311
65312     
65313     onLabelableAdded: function(labelable) {
65314         var me = this;
65315
65316         
65317         me.mon(labelable, 'errorchange', me.handleFieldErrorChange, me, {buffer: 10});
65318
65319         labelable.setFieldDefaults(me.fieldDefaults);
65320     },
65321
65322     
65323     onFieldAdded: function(field) {
65324         var me = this;
65325         me.mon(field, 'validitychange', me.handleFieldValidityChange, me);
65326     },
65327
65328     
65329     onLabelableRemoved: function(labelable) {
65330         var me = this;
65331         me.mun(labelable, 'errorchange', me.handleFieldErrorChange, me);
65332     },
65333
65334     
65335     onFieldRemoved: function(field) {
65336         var me = this;
65337         me.mun(field, 'validitychange', me.handleFieldValidityChange, me);
65338     },
65339
65340     
65341     handleFieldValidityChange: function(field, isValid) {
65342         var me = this;
65343         me.fireEvent('fieldvaliditychange', me, field, isValid);
65344         me.onFieldValidityChange();
65345     },
65346
65347     
65348     handleFieldErrorChange: function(labelable, activeError) {
65349         var me = this;
65350         me.fireEvent('fielderrorchange', me, labelable, activeError);
65351         me.onFieldErrorChange();
65352     },
65353
65354     
65355     onFieldValidityChange: Ext.emptyFn,
65356
65357     
65358     onFieldErrorChange: Ext.emptyFn
65359
65360 });
65361
65362 Ext.define('Ext.layout.container.CheckboxGroup', {
65363     extend: 'Ext.layout.container.Container',
65364     alias: ['layout.checkboxgroup'],
65365
65366
65367     onLayout: function() {
65368         var numCols = this.getColCount(),
65369             shadowCt = this.getShadowCt(),
65370             owner = this.owner,
65371             items = owner.items,
65372             shadowItems = shadowCt.items,
65373             numItems = items.length,
65374             colIndex = 0,
65375             i, numRows;
65376
65377         
65378         
65379         
65380         
65381
65382         shadowItems.each(function(col) {
65383             col.items.clear();
65384         });
65385
65386         
65387         
65388         while (shadowItems.length > numCols) {
65389             shadowCt.remove(shadowItems.last());
65390         }
65391         while (shadowItems.length < numCols) {
65392             shadowCt.add({
65393                 xtype: 'container',
65394                 cls: owner.groupCls,
65395                 flex: 1
65396             });
65397         }
65398
65399         if (owner.vertical) {
65400             numRows = Math.ceil(numItems / numCols);
65401             for (i = 0; i < numItems; i++) {
65402                 if (i > 0 && i % numRows === 0) {
65403                     colIndex++;
65404                 }
65405                 shadowItems.getAt(colIndex).items.add(items.getAt(i));
65406             }
65407         } else {
65408             for (i = 0; i < numItems; i++) {
65409                 colIndex = i % numCols;
65410                 shadowItems.getAt(colIndex).items.add(items.getAt(i));
65411             }
65412         }
65413
65414         if (!shadowCt.rendered) {
65415             shadowCt.render(this.getRenderTarget());
65416         } else {
65417             
65418             
65419             shadowItems.each(function(col) {
65420                 var layout = col.getLayout();
65421                 layout.renderItems(layout.getLayoutItems(), layout.getRenderTarget());
65422             });
65423         }
65424
65425         shadowCt.doComponentLayout();
65426     },
65427
65428
65429     
65430     renderItems: Ext.emptyFn,
65431
65432
65433     
65434     getShadowCt: function() {
65435         var me = this,
65436             shadowCt = me.shadowCt,
65437             owner, items, item, columns, columnsIsArray, numCols, i;
65438
65439         if (!shadowCt) {
65440             
65441             owner = me.owner;
65442             columns = owner.columns;
65443             columnsIsArray = Ext.isArray(columns);
65444             numCols = me.getColCount();
65445             items = [];
65446             for(i = 0; i < numCols; i++) {
65447                 item = {
65448                     xtype: 'container',
65449                     cls: owner.groupCls
65450                 };
65451                 if (columnsIsArray) {
65452                     
65453                     
65454                     if (columns[i] < 1) {
65455                         item.flex = columns[i];
65456                     } else {
65457                         item.width = columns[i];
65458                     }
65459                 }
65460                 else {
65461                     
65462                     item.flex = 1;
65463                 }
65464                 items.push(item);
65465             }
65466
65467             
65468             shadowCt = me.shadowCt = Ext.createWidget('container', {
65469                 layout: 'hbox',
65470                 items: items,
65471                 ownerCt: owner
65472             });
65473         }
65474         
65475         return shadowCt;
65476     },
65477
65478
65479     
65480     getColCount: function() {
65481         var owner = this.owner,
65482             colsCfg = owner.columns;
65483         return Ext.isArray(colsCfg) ? colsCfg.length : (Ext.isNumber(colsCfg) ? colsCfg : owner.items.length);
65484     }
65485
65486 });
65487
65488
65489 Ext.define('Ext.form.FieldContainer', {
65490     extend: 'Ext.container.Container',
65491     mixins: {
65492         labelable: 'Ext.form.Labelable',
65493         fieldAncestor: 'Ext.form.FieldAncestor'
65494     },
65495     alias: 'widget.fieldcontainer',
65496
65497     componentLayout: 'field',
65498
65499     
65500     combineLabels: false,
65501
65502     
65503     labelConnector: ', ',
65504
65505     
65506     combineErrors: false,
65507     
65508     maskOnDisable: false,
65509
65510     initComponent: function() {
65511         var me = this,
65512             onSubCmpAddOrRemove = me.onSubCmpAddOrRemove;
65513
65514         
65515         me.initLabelable();
65516         me.initFieldAncestor();
65517
65518         me.callParent();
65519     },
65520
65521     
65522     onLabelableAdded: function(labelable) {
65523         var me = this;
65524         me.mixins.fieldAncestor.onLabelableAdded.call(this, labelable);
65525         me.updateLabel();
65526     },
65527
65528     
65529     onLabelableRemoved: function(labelable) {
65530         var me = this;
65531         me.mixins.fieldAncestor.onLabelableRemoved.call(this, labelable);
65532         me.updateLabel();
65533     },
65534
65535     onRender: function() {
65536         var me = this,
65537             renderSelectors = me.renderSelectors,
65538             applyIf = Ext.applyIf;
65539
65540         applyIf(renderSelectors, me.getLabelableSelectors());
65541
65542         me.callParent(arguments);
65543     },
65544
65545     initRenderTpl: function() {
65546         var me = this;
65547         if (!me.hasOwnProperty('renderTpl')) {
65548             me.renderTpl = me.getTpl('labelableRenderTpl');
65549         }
65550         return me.callParent();
65551     },
65552
65553     initRenderData: function() {
65554         return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
65555     },
65556
65557     
65558     getFieldLabel: function() {
65559         var label = this.fieldLabel || '';
65560         if (!label && this.combineLabels) {
65561             label = Ext.Array.map(this.query('[isFieldLabelable]'), function(field) {
65562                 return field.getFieldLabel();
65563             }).join(this.labelConnector);
65564         }
65565         return label;
65566     },
65567
65568     
65569     updateLabel: function() {
65570         var me = this,
65571             label = me.labelEl;
65572         if (label) {
65573             label.update(me.getFieldLabel());
65574         }
65575     },
65576
65577
65578     
65579     onFieldErrorChange: function(field, activeError) {
65580         if (this.combineErrors) {
65581             var me = this,
65582                 oldError = me.getActiveError(),
65583                 invalidFields = Ext.Array.filter(me.query('[isFormField]'), function(field) {
65584                     return field.hasActiveError();
65585                 }),
65586                 newErrors = me.getCombinedErrors(invalidFields);
65587
65588             if (newErrors) {
65589                 me.setActiveErrors(newErrors);
65590             } else {
65591                 me.unsetActiveError();
65592             }
65593
65594             if (oldError !== me.getActiveError()) {
65595                 me.doComponentLayout();
65596             }
65597         }
65598     },
65599
65600     
65601     getCombinedErrors: function(invalidFields) {
65602         var forEach = Ext.Array.forEach,
65603             errors = [];
65604         forEach(invalidFields, function(field) {
65605             forEach(field.getActiveErrors(), function(error) {
65606                 var label = field.getFieldLabel();
65607                 errors.push((label ? label + ': ' : '') + error);
65608             });
65609         });
65610         return errors;
65611     },
65612
65613     getTargetEl: function() {
65614         return this.bodyEl || this.callParent();
65615     }
65616 });
65617
65618
65619 Ext.define('Ext.form.CheckboxGroup', {
65620     extend:'Ext.form.FieldContainer',
65621     mixins: {
65622         field: 'Ext.form.field.Field'
65623     },
65624     alias: 'widget.checkboxgroup',
65625     requires: ['Ext.layout.container.CheckboxGroup', 'Ext.form.field.Base'],
65626
65627     
65628
65629     
65630
65631     
65632     columns : 'auto',
65633
65634     
65635     vertical : false,
65636
65637     
65638     allowBlank : true,
65639
65640     
65641     blankText : "You must select at least one item in this group",
65642
65643     
65644     defaultType : 'checkboxfield',
65645
65646     
65647     groupCls : Ext.baseCSSPrefix + 'form-check-group',
65648
65649     
65650     fieldBodyCls: Ext.baseCSSPrefix + 'form-checkboxgroup-body',
65651
65652     
65653     layout: 'checkboxgroup',
65654
65655     initComponent: function() {
65656         var me = this;
65657         me.callParent();
65658         me.initField();
65659     },
65660
65661     
65662     initValue: function() {
65663         var me = this,
65664             valueCfg = me.value;
65665         me.originalValue = me.lastValue = valueCfg || me.getValue();
65666         if (valueCfg) {
65667             me.setValue(valueCfg);
65668         }
65669     },
65670
65671     
65672     onFieldAdded: function(field) {
65673         var me = this;
65674         if (field.isCheckbox) {
65675             me.mon(field, 'change', me.checkChange, me);
65676         }
65677         me.callParent(arguments);
65678     },
65679
65680     onFieldRemoved: function(field) {
65681         var me = this;
65682         if (field.isCheckbox) {
65683             me.mun(field, 'change', me.checkChange, me);
65684         }
65685         me.callParent(arguments);
65686     },
65687
65688     
65689     isEqual: function(value1, value2) {
65690         var toQueryString = Ext.Object.toQueryString;
65691         return toQueryString(value1) === toQueryString(value2);
65692     },
65693
65694     
65695     getErrors: function() {
65696         var errors = [];
65697         if (!this.allowBlank && Ext.isEmpty(this.getChecked())) {
65698             errors.push(this.blankText);
65699         }
65700         return errors;
65701     },
65702
65703     
65704     getBoxes: function() {
65705         return this.query('[isCheckbox]');
65706     },
65707
65708     
65709     eachBox: function(fn, scope) {
65710         Ext.Array.forEach(this.getBoxes(), fn, scope || this);
65711     },
65712
65713     
65714     getChecked: function() {
65715         return Ext.Array.filter(this.getBoxes(), function(cb) {
65716             return cb.getValue();
65717         });
65718     },
65719
65720     
65721     isDirty: function(){
65722         return Ext.Array.some(this.getBoxes(), function(cb) {
65723             return cb.isDirty();
65724         });
65725     },
65726
65727     
65728     setReadOnly: function(readOnly) {
65729         this.eachBox(function(cb) {
65730             cb.setReadOnly(readOnly);
65731         });
65732         this.readOnly = readOnly;
65733     },
65734
65735     
65736     reset: function() {
65737         var me = this,
65738             hadError = me.hasActiveError(),
65739             preventMark = me.preventMark;
65740         me.preventMark = true;
65741         me.batchChanges(function() {
65742             me.eachBox(function(cb) {
65743                 cb.reset();
65744             });
65745         });
65746         me.preventMark = preventMark;
65747         me.unsetActiveError();
65748         if (hadError) {
65749             me.doComponentLayout();
65750         }
65751     },
65752
65753     
65754     resetOriginalValue: function() {
65755         
65756         
65757         Ext.defer(function() {
65758             this.callParent();
65759         }, 1, this);
65760     },
65761
65762
65763     
65764     setValue: function(value) {
65765         var me = this;
65766         me.batchChanges(function() {
65767             me.eachBox(function(cb) {
65768                 var name = cb.getName(),
65769                     cbValue = false;
65770                 if (value && name in value) {
65771                     if (Ext.isArray(value[name])) {
65772                         cbValue = Ext.Array.contains(value[name], cb.inputValue);
65773                     } else {
65774                         
65775                         cbValue = value[name];
65776                     }
65777                 }
65778                 cb.setValue(cbValue);
65779             });
65780         });
65781         return me;
65782     },
65783
65784
65785     
65786     getValue: function() {
65787         var values = {};
65788         this.eachBox(function(cb) {
65789             var name = cb.getName(),
65790                 inputValue = cb.inputValue,
65791                 bucket;
65792             if (cb.getValue()) {
65793                 if (name in values) {
65794                     bucket = values[name];
65795                     if (!Ext.isArray(bucket)) {
65796                         bucket = values[name] = [bucket];
65797                     }
65798                     bucket.push(inputValue);
65799                 } else {
65800                     values[name] = inputValue;
65801                 }
65802             }
65803         });
65804         return values;
65805     },
65806
65807     
65808     getSubmitData: function() {
65809         return null;
65810     },
65811
65812     
65813     getModelData: function() {
65814         return null;
65815     },
65816
65817     validate: function() {
65818         var me = this,
65819             errors = me.getErrors(),
65820             isValid = Ext.isEmpty(errors),
65821             wasValid = !me.hasActiveError();
65822
65823         if (isValid) {
65824             me.unsetActiveError();
65825         } else {
65826             me.setActiveError(errors);
65827         }
65828         if (isValid !== wasValid) {
65829             me.fireEvent('validitychange', me, isValid);
65830             me.doComponentLayout();
65831         }
65832
65833         return isValid;
65834     }
65835
65836 }, function() {
65837
65838     this.borrow(Ext.form.field.Base, ['markInvalid', 'clearInvalid']);
65839
65840 });
65841
65842
65843
65844 Ext.define('Ext.form.CheckboxManager', {
65845     extend: 'Ext.util.MixedCollection',
65846     singleton: true,
65847
65848     getByName: function(name) {
65849         return this.filterBy(function(item) {
65850             return item.name == name;
65851         });
65852     },
65853
65854     getWithValue: function(name, value) {
65855         return this.filterBy(function(item) {
65856             return item.name == name && item.inputValue == value;
65857         });
65858     },
65859
65860     getChecked: function(name) {
65861         return this.filterBy(function(item) {
65862             return item.name == name && item.checked;
65863         });
65864     }
65865 });
65866
65867
65868 Ext.define('Ext.form.FieldSet', {
65869     extend: 'Ext.container.Container',
65870     alias: 'widget.fieldset',
65871     uses: ['Ext.form.field.Checkbox', 'Ext.panel.Tool', 'Ext.layout.container.Anchor', 'Ext.layout.component.FieldSet'],
65872
65873     
65874
65875     
65876
65877     
65878
65879     
65880
65881     
65882     collapsed: false,
65883
65884     
65885
65886     
65887     baseCls: Ext.baseCSSPrefix + 'fieldset',
65888
65889     
65890     layout: 'anchor',
65891
65892     componentLayout: 'fieldset',
65893
65894     
65895     ariaRole: '',
65896
65897     renderTpl: ['<div class="{baseCls}-body"></div>'],
65898     
65899     maskOnDisable: false,
65900
65901     getElConfig: function(){
65902         return {tag: 'fieldset', id: this.id};
65903     },
65904
65905     initComponent: function() {
65906         var me = this,
65907             baseCls = me.baseCls;
65908
65909         me.callParent();
65910
65911         
65912         me.initLegend();
65913
65914         
65915         Ext.applyIf(me.renderSelectors, {
65916             body: '.' + baseCls + '-body'
65917         });
65918
65919         if (me.collapsed) {
65920             me.addCls(baseCls + '-collapsed');
65921             me.collapse();
65922         }
65923     },
65924
65925     
65926     onRender: function(container, position) {
65927         this.callParent(arguments);
65928         
65929         this.initLegend();
65930     },
65931
65932     
65933     initLegend: function() {
65934         var me = this,
65935             legendItems,
65936             legend = me.legend;
65937
65938         
65939         if (!legend && (me.title || me.checkboxToggle || me.collapsible)) {
65940             legendItems = [];
65941
65942             
65943             if (me.checkboxToggle) {
65944                 legendItems.push(me.createCheckboxCmp());
65945             }
65946             
65947             else if (me.collapsible) {
65948                 legendItems.push(me.createToggleCmp());
65949             }
65950
65951             
65952             legendItems.push(me.createTitleCmp());
65953
65954             legend = me.legend = Ext.create('Ext.container.Container', {
65955                 baseCls: me.baseCls + '-header',
65956                 ariaRole: '',
65957                 getElConfig: function(){
65958                     return {tag: 'legend', cls: this.baseCls};
65959                 },
65960                 items: legendItems
65961             });
65962         }
65963
65964         
65965         if (legend && !legend.rendered && me.rendered) {
65966             me.legend.render(me.el, me.body); 
65967         }
65968     },
65969
65970     
65971     createTitleCmp: function() {
65972         var me = this;
65973         me.titleCmp = Ext.create('Ext.Component', {
65974             html: me.title,
65975             cls: me.baseCls + '-header-text'
65976         });
65977         return me.titleCmp;
65978         
65979     },
65980
65981     
65982
65983     
65984     createCheckboxCmp: function() {
65985         var me = this,
65986             suffix = '-checkbox';
65987             
65988         me.checkboxCmp = Ext.create('Ext.form.field.Checkbox', {
65989             name: me.checkboxName || me.id + suffix,
65990             cls: me.baseCls + '-header' + suffix,
65991             checked: !me.collapsed,
65992             listeners: {
65993                 change: me.onCheckChange,
65994                 scope: me
65995             }
65996         });
65997         return me.checkboxCmp;
65998     },
65999
66000     
66001
66002     
66003     createToggleCmp: function() {
66004         var me = this;
66005         me.toggleCmp = Ext.create('Ext.panel.Tool', {
66006             type: 'toggle',
66007             handler: me.toggle,
66008             scope: me
66009         });
66010         return me.toggleCmp;
66011     },
66012     
66013     
66014     setTitle: function(title) {
66015         var me = this;
66016         me.title = title;
66017         me.initLegend();
66018         me.titleCmp.update(title);
66019         return me;
66020     },
66021     
66022     getTargetEl : function() {
66023         return this.body || this.frameBody || this.el;
66024     },
66025     
66026     getContentTarget: function() {
66027         return this.body;
66028     },
66029     
66030     
66031     getRefItems: function(deep) {
66032         var refItems = this.callParent(arguments),
66033             legend = this.legend;
66034
66035         
66036         if (legend) {
66037             refItems.unshift(legend);
66038             if (deep) {
66039                 refItems.unshift.apply(refItems, legend.getRefItems(true));
66040             }
66041         }
66042         return refItems;
66043     },
66044
66045     
66046     expand : function(){
66047         return this.setExpanded(true);
66048     },
66049     
66050     
66051     collapse : function() {
66052         return this.setExpanded(false);
66053     },
66054
66055     
66056     setExpanded: function(expanded) {
66057         var me = this,
66058             checkboxCmp = me.checkboxCmp;
66059
66060         expanded = !!expanded;
66061         
66062         if (checkboxCmp) {
66063             checkboxCmp.setValue(expanded);
66064         }
66065         
66066         if (expanded) {
66067             me.removeCls(me.baseCls + '-collapsed');
66068         } else {
66069             me.addCls(me.baseCls + '-collapsed');
66070         }
66071         me.collapsed = !expanded;
66072         if (expanded) {
66073             
66074             me.getComponentLayout().childrenChanged = true;
66075         }
66076         me.doComponentLayout();
66077         return me;
66078     },
66079
66080     
66081     toggle: function() {
66082         this.setExpanded(!!this.collapsed);
66083     },
66084
66085     
66086     onCheckChange: function(cmp, checked) {
66087         this.setExpanded(checked);
66088     },
66089
66090     beforeDestroy : function() {
66091         var legend = this.legend;
66092         if (legend) {
66093             legend.destroy();
66094         }
66095         this.callParent();
66096     }
66097 });
66098
66099
66100 Ext.define('Ext.form.Label', {
66101     extend:'Ext.Component',
66102     alias: 'widget.label',
66103     requires: ['Ext.util.Format'],
66104
66105     
66106     
66107     
66108     
66109     maskOnDisable: false,
66110     getElConfig: function(){
66111         var me = this;
66112         return {
66113             tag: 'label', 
66114             id: me.id, 
66115             htmlFor: me.forId || '',
66116             html: me.text ? Ext.util.Format.htmlEncode(me.text) : (me.html || '') 
66117         };
66118     },
66119
66120     
66121     setText : function(text, encode){
66122         var me = this;
66123         
66124         encode = encode !== false;
66125         if(encode) {
66126             me.text = text;
66127             delete me.html;
66128         } else {
66129             me.html = text;
66130             delete me.text;
66131         }
66132         
66133         if(me.rendered){
66134             me.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(text) : text;
66135         }
66136         return this;
66137     }
66138 });
66139
66140
66141
66142 Ext.define('Ext.form.Panel', {
66143     extend:'Ext.panel.Panel',
66144     mixins: {
66145         fieldAncestor: 'Ext.form.FieldAncestor'
66146     },
66147     alias: 'widget.form',
66148     alternateClassName: ['Ext.FormPanel', 'Ext.form.FormPanel'],
66149     requires: ['Ext.form.Basic', 'Ext.util.TaskRunner'],
66150
66151     
66152
66153     
66154
66155     
66156     layout: 'anchor',
66157
66158     ariaRole: 'form',
66159
66160     initComponent: function() {
66161         var me = this;
66162         
66163         if (me.frame) {
66164             me.border = false;
66165         }
66166         
66167         me.initFieldAncestor();
66168         me.callParent();
66169
66170         me.relayEvents(me.form, [
66171             'beforeaction',
66172             'actionfailed',
66173             'actioncomplete',
66174             'validitychange',
66175             'dirtychange'
66176         ]);
66177
66178         
66179         if (me.pollForChanges) {
66180             me.startPolling(me.pollInterval || 500);
66181         }
66182     },
66183
66184     initItems: function() {
66185         
66186         var me = this;
66187         
66188         me.form = me.createForm();
66189         me.callParent();
66190         me.form.initialize();
66191     },
66192
66193     
66194     createForm: function() {
66195         return Ext.create('Ext.form.Basic', this, Ext.applyIf({listeners: {}}, this.initialConfig));
66196     },
66197
66198     
66199     getForm: function() {
66200         return this.form;
66201     },
66202     
66203     
66204     loadRecord: function(record) {
66205         return this.getForm().loadRecord(record);
66206     },
66207     
66208     
66209     getRecord: function() {
66210         return this.getForm().getRecord();
66211     },
66212     
66213     
66214     getValues: function() {
66215         return this.getForm().getValues();
66216     },
66217
66218     beforeDestroy: function() {
66219         this.stopPolling();
66220         this.form.destroy();
66221         this.callParent();
66222     },
66223
66224     
66225     load: function(options) {
66226         this.form.load(options);
66227     },
66228
66229     
66230     submit: function(options) {
66231         this.form.submit(options);
66232     },
66233
66234     
66235     disable: function(silent) {
66236         this.callParent(arguments);
66237         this.form.getFields().each(function(field) {
66238             field.disable();
66239         });
66240     },
66241
66242     
66243     enable: function(silent) {
66244         this.callParent(arguments);
66245         this.form.getFields().each(function(field) {
66246             field.enable();
66247         });
66248     },
66249
66250     
66251     startPolling: function(interval) {
66252         this.stopPolling();
66253         var task = Ext.create('Ext.util.TaskRunner', interval);
66254         task.start({
66255             interval: 0,
66256             run: this.checkChange,
66257             scope: this
66258         });
66259         this.pollTask = task;
66260     },
66261
66262     
66263     stopPolling: function() {
66264         var task = this.pollTask;
66265         if (task) {
66266             task.stopAll();
66267             delete this.pollTask;
66268         }
66269     },
66270
66271     
66272     checkChange: function() {
66273         this.form.getFields().each(function(field) {
66274             field.checkChange();
66275         });
66276     }
66277 });
66278
66279
66280 Ext.define('Ext.form.RadioGroup', {
66281     extend: 'Ext.form.CheckboxGroup',
66282     alias: 'widget.radiogroup',
66283
66284     
66285     
66286     allowBlank : true,
66287     
66288     blankText : 'You must select one item in this group',
66289     
66290     
66291     defaultType : 'radiofield',
66292     
66293     
66294     groupCls : Ext.baseCSSPrefix + 'form-radio-group',
66295
66296     getBoxes: function() {
66297         return this.query('[isRadio]');
66298     }
66299
66300 });
66301
66302
66303 Ext.define('Ext.form.RadioManager', {
66304     extend: 'Ext.util.MixedCollection',
66305     singleton: true,
66306
66307     getByName: function(name) {
66308         return this.filterBy(function(item) {
66309             return item.name == name;
66310         });
66311     },
66312
66313     getWithValue: function(name, value) {
66314         return this.filterBy(function(item) {
66315             return item.name == name && item.inputValue == value;
66316         });
66317     },
66318
66319     getChecked: function(name) {
66320         return this.findBy(function(item) {
66321             return item.name == name && item.checked;
66322         });
66323     }
66324 });
66325
66326
66327 Ext.define('Ext.form.action.DirectLoad', {
66328     extend:'Ext.form.action.Load',
66329     requires: ['Ext.direct.Manager'],
66330     alternateClassName: 'Ext.form.Action.DirectLoad',
66331     alias: 'formaction.directload',
66332
66333     type: 'directload',
66334
66335     run: function() {
66336         this.form.api.load.apply(window, this.getArgs());
66337     },
66338
66339     
66340     getArgs: function() {
66341         var me = this,
66342             args = [],
66343             form = me.form,
66344             paramOrder = form.paramOrder,
66345             params = me.getParams(),
66346             i, len;
66347
66348         
66349         if (paramOrder) {
66350             for (i = 0, len = paramOrder.length; i < len; i++) {
66351                 args.push(params[paramOrder[i]]);
66352             }
66353         }
66354         
66355         else if (form.paramsAsHash) {
66356             args.push(params);
66357         }
66358
66359         
66360         args.push(me.onSuccess, me);
66361
66362         return args;
66363     },
66364
66365     
66366     
66367     
66368     processResponse: function(result) {
66369         return (this.result = result);
66370     },
66371
66372     onSuccess: function(result, trans) {
66373         if (trans.type == Ext.direct.Manager.self.exceptions.SERVER) {
66374             result = {};
66375         }
66376         this.callParent([result]);
66377     }
66378 });
66379
66380
66381
66382
66383 Ext.define('Ext.form.action.DirectSubmit', {
66384     extend:'Ext.form.action.Submit',
66385     requires: ['Ext.direct.Manager'],
66386     alternateClassName: 'Ext.form.Action.DirectSubmit',
66387     alias: 'formaction.directsubmit',
66388
66389     type: 'directsubmit',
66390
66391     doSubmit: function() {
66392         var me = this,
66393             callback = Ext.Function.bind(me.onSuccess, me),
66394             formEl = me.buildForm();
66395         me.form.api.submit(formEl, callback, me);
66396         Ext.removeNode(formEl);
66397     },
66398
66399     
66400     
66401     
66402     processResponse: function(result) {
66403         return (this.result = result);
66404     },
66405
66406     onSuccess: function(response, trans) {
66407         if (trans.type === Ext.direct.Manager.self.exceptions.SERVER) {
66408             response = {};
66409         }
66410         this.callParent([response]);
66411     }
66412 });
66413
66414
66415 Ext.define('Ext.form.action.StandardSubmit', {
66416     extend:'Ext.form.action.Submit',
66417     alias: 'formaction.standardsubmit',
66418
66419     
66420
66421     
66422     doSubmit: function() {
66423         var form = this.buildForm();
66424         form.submit();
66425         Ext.removeNode(form);
66426     }
66427
66428 });
66429
66430
66431 Ext.define('Ext.form.field.Checkbox', {
66432     extend: 'Ext.form.field.Base',
66433     alias: ['widget.checkboxfield', 'widget.checkbox'],
66434     alternateClassName: 'Ext.form.Checkbox',
66435     requires: ['Ext.XTemplate', 'Ext.form.CheckboxManager'],
66436
66437     fieldSubTpl: [
66438         '<tpl if="boxLabel && boxLabelAlign == \'before\'">',
66439             '<label class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
66440         '</tpl>',
66441         
66442         
66443         
66444         '<input type="button" id="{id}" ',
66445             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
66446             'class="{fieldCls} {typeCls}" autocomplete="off" hidefocus="true" />',
66447         '<tpl if="boxLabel && boxLabelAlign == \'after\'">',
66448             '<label class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
66449         '</tpl>',
66450         {
66451             disableFormats: true,
66452             compiled: true
66453         }
66454     ],
66455
66456     isCheckbox: true,
66457
66458     
66459     focusCls: Ext.baseCSSPrefix + 'form-cb-focus',
66460
66461     
66462
66463     
66464     fieldBodyCls: Ext.baseCSSPrefix + 'form-cb-wrap',
66465
66466     
66467     checked: false,
66468
66469     
66470     checkedCls: Ext.baseCSSPrefix + 'form-cb-checked',
66471
66472     
66473
66474     
66475     boxLabelCls: Ext.baseCSSPrefix + 'form-cb-label',
66476
66477     
66478     boxLabelAlign: 'after',
66479
66480     
66481     inputValue: 'on',
66482
66483     
66484
66485     
66486
66487     
66488
66489     
66490     checkChangeEvents: [],
66491     inputType: 'checkbox',
66492     ariaRole: 'checkbox',
66493
66494     
66495     onRe: /^on$/i,
66496
66497     initComponent: function(){
66498         this.callParent(arguments);
66499         this.getManager().add(this);
66500     },
66501
66502     initValue: function() {
66503         var me = this,
66504             checked = !!me.checked;
66505
66506         
66507         me.originalValue = me.lastValue = checked;
66508
66509         
66510         me.setValue(checked);
66511     },
66512
66513     
66514     onRender : function(ct, position) {
66515         var me = this;
66516         Ext.applyIf(me.renderSelectors, {
66517             
66518             boxLabelEl: 'label.' + me.boxLabelCls
66519         });
66520         Ext.applyIf(me.subTplData, {
66521             boxLabel: me.boxLabel,
66522             boxLabelCls: me.boxLabelCls,
66523             boxLabelAlign: me.boxLabelAlign
66524         });
66525
66526         me.callParent(arguments);
66527     },
66528
66529     initEvents: function() {
66530         var me = this;
66531         me.callParent();
66532         me.mon(me.inputEl, 'click', me.onBoxClick, me);
66533     },
66534
66535     
66536     onBoxClick: function(e) {
66537         var me = this;
66538         if (!me.disabled && !me.readOnly) {
66539             this.setValue(!this.checked);
66540         }
66541     },
66542
66543     
66544     getRawValue: function() {
66545         return this.checked;
66546     },
66547
66548     
66549     getValue: function() {
66550         return this.checked;
66551     },
66552
66553     
66554     getSubmitValue: function() {
66555         var unchecked = this.uncheckedValue,
66556             uncheckedVal = Ext.isDefined(unchecked) ? unchecked : null;
66557         return this.checked ? this.inputValue : uncheckedVal;
66558     },
66559
66560     
66561     setRawValue: function(value) {
66562         var me = this,
66563             inputEl = me.inputEl,
66564             inputValue = me.inputValue,
66565             checked = (value === true || value === 'true' || value === '1' ||
66566                       ((Ext.isString(value) && inputValue) ? value == inputValue : me.onRe.test(value)));
66567
66568         if (inputEl) {
66569             inputEl.dom.setAttribute('aria-checked', checked);
66570             me[checked ? 'addCls' : 'removeCls'](me.checkedCls);
66571         }
66572
66573         me.checked = me.rawValue = checked;
66574         return checked;
66575     },
66576
66577     
66578     setValue: function(checked) {
66579         var me = this;
66580
66581         
66582         
66583         
66584         
66585         if (Ext.isArray(checked)) {
66586             me.getManager().getByName(me.name).each(function(cb) {
66587                 cb.setValue(Ext.Array.contains(checked, cb.inputValue));
66588             });
66589         } else {
66590             me.callParent(arguments);
66591         }
66592
66593         return me;
66594     },
66595
66596     
66597     valueToRaw: function(value) {
66598         
66599         return value;
66600     },
66601
66602     
66603     onChange: function(newVal, oldVal) {
66604         var me = this,
66605             handler = me.handler;
66606         if (handler) {
66607             handler.call(me.scope || me, me, newVal);
66608         }
66609         me.callParent(arguments);
66610     },
66611
66612     
66613     getManager: function() {
66614         return Ext.form.CheckboxManager;
66615     },
66616
66617     onEnable: function() {
66618         var me = this,
66619             inputEl = me.inputEl;
66620         me.callParent();
66621         if (inputEl) {
66622             
66623             inputEl.dom.disabled = me.readOnly;
66624         }
66625     },
66626
66627     setReadOnly: function(readOnly) {
66628         var me = this,
66629             inputEl = me.inputEl;
66630         if (inputEl) {
66631             
66632             inputEl.dom.disabled = readOnly || me.disabled;
66633         }
66634         me.readOnly = readOnly;
66635     },
66636
66637     
66638     getBodyNaturalWidth: function() {
66639         var me = this,
66640             bodyEl = me.bodyEl,
66641             ws = 'white-space',
66642             width;
66643         bodyEl.setStyle(ws, 'nowrap');
66644         width = bodyEl.getWidth();
66645         bodyEl.setStyle(ws, '');
66646         return width;
66647     }
66648
66649 });
66650
66651
66652
66653 Ext.define('Ext.layout.component.field.Trigger', {
66654
66655     
66656
66657     alias: ['layout.triggerfield'],
66658
66659     extend: 'Ext.layout.component.field.Field',
66660
66661     
66662
66663     type: 'triggerfield',
66664
66665     sizeBodyContents: function(width, height) {
66666         var me = this,
66667             owner = me.owner,
66668             inputEl = owner.inputEl,
66669             triggerWrap = owner.triggerWrap,
66670             triggerWidth = owner.getTriggerWidth();
66671
66672         
66673         
66674         if (owner.hideTrigger || owner.readOnly || triggerWidth > 0) {
66675             
66676             
66677             me.setElementSize(inputEl, Ext.isNumber(width) ? width - triggerWidth : width);
66678     
66679             
66680             triggerWrap.setWidth(triggerWidth);
66681         }
66682     }
66683 });
66684
66685 Ext.define('Ext.view.View', {
66686     extend: 'Ext.view.AbstractView',
66687     alternateClassName: 'Ext.view.View',
66688     alias: 'widget.dataview',
66689
66690     inheritableStatics: {
66691         EventMap: {
66692             mousedown: 'MouseDown',
66693             mouseup: 'MouseUp',
66694             click: 'Click',
66695             dblclick: 'DblClick',
66696             contextmenu: 'ContextMenu',
66697             mouseover: 'MouseOver',
66698             mouseout: 'MouseOut',
66699             mouseenter: 'MouseEnter',
66700             mouseleave: 'MouseLeave',
66701             keydown: 'KeyDown'
66702         }
66703     },
66704
66705     addCmpEvents: function() {
66706         this.addEvents(
66707             
66708             'beforeitemmousedown',
66709             
66710             'beforeitemmouseup',
66711             
66712             'beforeitemmouseenter',
66713             
66714             'beforeitemmouseleave',
66715             
66716             'beforeitemclick',
66717             
66718             'beforeitemdblclick',
66719             
66720             'beforeitemcontextmenu',
66721             
66722             'beforeitemkeydown',
66723             
66724             'itemmousedown',
66725             
66726             'itemmouseup',
66727             
66728             'itemmouseenter',
66729             
66730             'itemmouseleave',
66731             
66732             'itemclick',
66733             
66734             'itemdblclick',
66735             
66736             'itemcontextmenu',
66737             
66738             'itemkeydown',
66739             
66740             'beforecontainermousedown',
66741             
66742             'beforecontainermouseup',
66743             
66744             'beforecontainermouseover',
66745             
66746             'beforecontainermouseout',
66747             
66748             'beforecontainerclick',
66749             
66750             'beforecontainerdblclick',
66751             
66752             'beforecontainercontextmenu',
66753             
66754             'beforecontainerkeydown',
66755             
66756             'containermouseup',
66757             
66758             'containermouseover',
66759             
66760             'containermouseout',
66761             
66762             'containerclick',
66763             
66764             'containerdblclick',
66765             
66766             'containercontextmenu',
66767             
66768             'containerkeydown',
66769
66770             
66771             'selectionchange',
66772             
66773             'beforeselect'
66774         );
66775     },
66776     
66777     afterRender: function(){
66778         var me = this,
66779             listeners;
66780
66781         me.callParent();
66782
66783         listeners = {
66784             scope: me,
66785             click: me.handleEvent,
66786             mousedown: me.handleEvent,
66787             mouseup: me.handleEvent,
66788             dblclick: me.handleEvent,
66789             contextmenu: me.handleEvent,
66790             mouseover: me.handleEvent,
66791             mouseout: me.handleEvent,
66792             keydown: me.handleEvent
66793         };
66794
66795         me.mon(me.getTargetEl(), listeners);
66796
66797         if (me.store) {
66798             me.bindStore(me.store, true);
66799         }
66800     },
66801
66802     handleEvent: function(e) {
66803         if (this.processUIEvent(e) !== false) {
66804             this.processSpecialEvent(e);
66805         }
66806     },
66807
66808     
66809     processItemEvent: Ext.emptyFn,
66810     processContainerEvent: Ext.emptyFn,
66811     processSpecialEvent: Ext.emptyFn,
66812
66813     
66814     stillOverItem: function (event, overItem) {
66815         var nowOver;
66816
66817         
66818         
66819         
66820         
66821         
66822         
66823         if (overItem && typeof(overItem.offsetParent) === "object") {
66824             
66825             
66826             nowOver = (event.type == 'mouseout') ? event.getRelatedTarget() : event.getTarget();
66827             return Ext.fly(overItem).contains(nowOver);
66828         }
66829
66830         return false;
66831     },
66832
66833     processUIEvent: function(e) {
66834         var me = this,
66835             item = e.getTarget(me.getItemSelector(), me.getTargetEl()),
66836             map = this.statics().EventMap,
66837             index, record,
66838             type = e.type,
66839             overItem = me.mouseOverItem,
66840             newType;
66841
66842         if (!item) {
66843             if (type == 'mouseover' && me.stillOverItem(e, overItem)) {
66844                 item = overItem;
66845             }
66846
66847             
66848             if (type == 'keydown') {
66849                 record = me.getSelectionModel().getLastSelected();
66850                 if (record) {
66851                     item = me.getNode(record);
66852                 }
66853             }
66854         }
66855
66856         if (item) {
66857             index = me.indexOf(item);
66858             if (!record) {
66859                 record = me.getRecord(item);
66860             }
66861
66862             if (me.processItemEvent(record, item, index, e) === false) {
66863                 return false;
66864             }
66865
66866             newType = me.isNewItemEvent(item, e);
66867             if (newType === false) {
66868                 return false;
66869             }
66870
66871             if (
66872                 (me['onBeforeItem' + map[newType]](record, item, index, e) === false) ||
66873                 (me.fireEvent('beforeitem' + newType, me, record, item, index, e) === false) ||
66874                 (me['onItem' + map[newType]](record, item, index, e) === false)
66875             ) {
66876                 return false;
66877             }
66878
66879             me.fireEvent('item' + newType, me, record, item, index, e);
66880         }
66881         else {
66882             if (
66883                 (me.processContainerEvent(e) === false) ||
66884                 (me['onBeforeContainer' + map[type]](e) === false) ||
66885                 (me.fireEvent('beforecontainer' + type, me, e) === false) ||
66886                 (me['onContainer' + map[type]](e) === false)
66887             ) {
66888                 return false;
66889             }
66890
66891             me.fireEvent('container' + type, me, e);
66892         }
66893
66894         return true;
66895     },
66896
66897     isNewItemEvent: function (item, e) {
66898         var me = this,
66899             overItem = me.mouseOverItem,
66900             type = e.type;
66901
66902         switch (type) {
66903             case 'mouseover':
66904                 if (item === overItem) {
66905                     return false;
66906                 }
66907                 me.mouseOverItem = item;
66908                 return 'mouseenter';
66909
66910             case 'mouseout':
66911                 
66912                 if (me.stillOverItem(e, overItem)) {
66913                     return false;
66914                 }
66915                 me.mouseOverItem = null;
66916                 return 'mouseleave';
66917         }
66918         return type;
66919     },
66920
66921     
66922     onItemMouseEnter: function(record, item, index, e) {
66923         if (this.trackOver) {
66924             this.highlightItem(item);
66925         }
66926     },
66927
66928     
66929     onItemMouseLeave : function(record, item, index, e) {
66930         if (this.trackOver) {
66931             this.clearHighlight();
66932         }
66933     },
66934
66935     
66936     onItemMouseDown: Ext.emptyFn,
66937     onItemMouseUp: Ext.emptyFn,
66938     onItemClick: Ext.emptyFn,
66939     onItemDblClick: Ext.emptyFn,
66940     onItemContextMenu: Ext.emptyFn,
66941     onItemKeyDown: Ext.emptyFn,
66942     onBeforeItemMouseDown: Ext.emptyFn,
66943     onBeforeItemMouseUp: Ext.emptyFn,
66944     onBeforeItemMouseEnter: Ext.emptyFn,
66945     onBeforeItemMouseLeave: Ext.emptyFn,
66946     onBeforeItemClick: Ext.emptyFn,
66947     onBeforeItemDblClick: Ext.emptyFn,
66948     onBeforeItemContextMenu: Ext.emptyFn,
66949     onBeforeItemKeyDown: Ext.emptyFn,
66950
66951     
66952     onContainerMouseDown: Ext.emptyFn,
66953     onContainerMouseUp: Ext.emptyFn,
66954     onContainerMouseOver: Ext.emptyFn,
66955     onContainerMouseOut: Ext.emptyFn,
66956     onContainerClick: Ext.emptyFn,
66957     onContainerDblClick: Ext.emptyFn,
66958     onContainerContextMenu: Ext.emptyFn,
66959     onContainerKeyDown: Ext.emptyFn,
66960     onBeforeContainerMouseDown: Ext.emptyFn,
66961     onBeforeContainerMouseUp: Ext.emptyFn,
66962     onBeforeContainerMouseOver: Ext.emptyFn,
66963     onBeforeContainerMouseOut: Ext.emptyFn,
66964     onBeforeContainerClick: Ext.emptyFn,
66965     onBeforeContainerDblClick: Ext.emptyFn,
66966     onBeforeContainerContextMenu: Ext.emptyFn,
66967     onBeforeContainerKeyDown: Ext.emptyFn,
66968
66969     
66970     highlightItem: function(item) {
66971         var me = this;
66972         me.clearHighlight();
66973         me.highlightedItem = item;
66974         Ext.fly(item).addCls(me.overItemCls);
66975     },
66976
66977     
66978     clearHighlight: function() {
66979         var me = this,
66980             highlighted = me.highlightedItem;
66981
66982         if (highlighted) {
66983             Ext.fly(highlighted).removeCls(me.overItemCls);
66984             delete me.highlightedItem;
66985         }
66986     },
66987
66988     refresh: function() {
66989         this.clearHighlight();
66990         this.callParent(arguments);
66991     }
66992 });
66993
66994 Ext.define('Ext.layout.component.BoundList', {
66995     extend: 'Ext.layout.component.Component',
66996     alias: 'layout.boundlist',
66997
66998     type: 'component',
66999
67000     beforeLayout: function() {
67001         return this.callParent(arguments) || this.owner.refreshed > 0;
67002     },
67003
67004     onLayout : function(width, height) {
67005         var me = this,
67006             owner = me.owner,
67007             floating = owner.floating,
67008             el = owner.el,
67009             xy = el.getXY(),
67010             isNumber = Ext.isNumber,
67011             minWidth, maxWidth, minHeight, maxHeight,
67012             naturalWidth, naturalHeight, constrainedWidth, constrainedHeight, undef;
67013
67014         if (floating) {
67015             
67016             el.setXY([-9999,-9999]);
67017         }
67018
67019         
67020         me.setTargetSize(width, height);
67021
67022         
67023         if (!isNumber(width)) {
67024             minWidth = owner.minWidth;
67025             maxWidth = owner.maxWidth;
67026             if (isNumber(minWidth) || isNumber(maxWidth)) {
67027                 naturalWidth = el.getWidth();
67028                 if (naturalWidth < minWidth) {
67029                     constrainedWidth = minWidth;
67030                 }
67031                 else if (naturalWidth > maxWidth) {
67032                     constrainedWidth = maxWidth;
67033                 }
67034                 if (constrainedWidth) {
67035                     me.setTargetSize(constrainedWidth);
67036                 }
67037             }
67038         }
67039         
67040         if (!isNumber(height)) {
67041             minHeight = owner.minHeight;
67042             maxHeight = owner.maxHeight;
67043             if (isNumber(minHeight) || isNumber(maxHeight)) {
67044                 naturalHeight = el.getHeight();
67045                 if (naturalHeight < minHeight) {
67046                     constrainedHeight = minHeight;
67047                 }
67048                 else if (naturalHeight > maxHeight) {
67049                     constrainedHeight = maxHeight;
67050                 }
67051                 if (constrainedHeight) {
67052                     me.setTargetSize(undef, constrainedHeight);
67053                 }
67054             }
67055         }
67056
67057         if (floating) {
67058             
67059             el.setXY(xy);
67060         }
67061     },
67062
67063     afterLayout: function() {
67064         var me = this,
67065             toolbar = me.owner.pagingToolbar;
67066         me.callParent();
67067         if (toolbar) {
67068             toolbar.doComponentLayout();
67069         }
67070     },
67071
67072     setTargetSize : function(width, height) {
67073         var me = this,
67074             owner = me.owner,
67075             listHeight = null,
67076             toolbar;
67077
67078         
67079         if (Ext.isNumber(height)) {
67080             listHeight = height - owner.el.getFrameWidth('tb');
67081             toolbar = owner.pagingToolbar;
67082             if (toolbar) {
67083                 listHeight -= toolbar.getHeight();
67084             }
67085         }
67086         me.setElementSize(owner.listEl, null, listHeight);
67087
67088         me.callParent(arguments);
67089     }
67090
67091 });
67092
67093
67094 Ext.define('Ext.toolbar.TextItem', {
67095     extend: 'Ext.toolbar.Item',
67096     requires: ['Ext.XTemplate'],
67097     alias: 'widget.tbtext',
67098     alternateClassName: 'Ext.Toolbar.TextItem',
67099     
67100     
67101     text: '',
67102     
67103     renderTpl: '{text}',
67104     
67105     baseCls: Ext.baseCSSPrefix + 'toolbar-text',
67106     
67107     onRender : function() {
67108         Ext.apply(this.renderData, {
67109             text: this.text
67110         });
67111         this.callParent(arguments);
67112     },
67113
67114     
67115     setText : function(t) {
67116         if (this.rendered) {
67117             this.el.update(t);
67118             this.ownerCt.doLayout(); 
67119         } else {
67120             this.text = t;
67121         }
67122     }
67123 });
67124
67125 Ext.define('Ext.form.field.Trigger', {
67126     extend:'Ext.form.field.Text',
67127     alias: ['widget.triggerfield', 'widget.trigger'],
67128     requires: ['Ext.core.DomHelper', 'Ext.util.ClickRepeater', 'Ext.layout.component.field.Trigger'],
67129     alternateClassName: ['Ext.form.TriggerField', 'Ext.form.TwinTriggerField', 'Ext.form.Trigger'],
67130
67131     fieldSubTpl: [
67132         '<input id="{id}" type="{type}" ',
67133             '<tpl if="name">name="{name}" </tpl>',
67134             '<tpl if="size">size="{size}" </tpl>',
67135             '<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
67136             'class="{fieldCls} {typeCls}" autocomplete="off" />',
67137         '<div class="{triggerWrapCls}" role="presentation">',
67138             '{triggerEl}',
67139             '<div class="{clearCls}" role="presentation"></div>',
67140         '</div>',
67141         {
67142             compiled: true,
67143             disableFormats: true
67144         }
67145     ],
67146
67147     
67148
67149     
67150     triggerBaseCls: Ext.baseCSSPrefix + 'form-trigger',
67151
67152     
67153     triggerWrapCls: Ext.baseCSSPrefix + 'form-trigger-wrap',
67154
67155     
67156     hideTrigger: false,
67157
67158     
67159     editable: true,
67160
67161     
67162     readOnly: false,
67163
67164     
67165
67166     
67167     repeatTriggerClick: false,
67168
67169
67170     
67171     autoSize: Ext.emptyFn,
67172     
67173     monitorTab: true,
67174     
67175     mimicing: false,
67176     
67177     triggerIndexRe: /trigger-index-(\d+)/,
67178
67179     componentLayout: 'triggerfield',
67180
67181     initComponent: function() {
67182         this.wrapFocusCls = this.triggerWrapCls + '-focus';
67183         this.callParent(arguments);
67184     },
67185
67186     
67187     onRender: function(ct, position) {
67188         var me = this,
67189             triggerCls,
67190             triggerBaseCls = me.triggerBaseCls,
67191             triggerWrapCls = me.triggerWrapCls,
67192             triggerConfigs = [],
67193             i;
67194
67195         
67196         
67197         
67198         
67199         if (!me.trigger1Cls) {
67200             me.trigger1Cls = me.triggerCls;
67201         }
67202
67203         
67204         for (i = 0; (triggerCls = me['trigger' + (i + 1) + 'Cls']) || i < 1; i++) {
67205             triggerConfigs.push({
67206                 cls: [Ext.baseCSSPrefix + 'trigger-index-' + i, triggerBaseCls, triggerCls].join(' '),
67207                 role: 'button'
67208             });
67209         }
67210         triggerConfigs[i - 1].cls += ' ' + triggerBaseCls + '-last';
67211
67212         Ext.applyIf(me.renderSelectors, {
67213             
67214             triggerWrap: '.' + triggerWrapCls
67215         });
67216         Ext.applyIf(me.subTplData, {
67217             triggerWrapCls: triggerWrapCls,
67218             triggerEl: Ext.core.DomHelper.markup(triggerConfigs),
67219             clearCls: me.clearCls
67220         });
67221
67222         me.callParent(arguments);
67223
67224         
67225         me.triggerEl = Ext.select('.' + triggerBaseCls, true, me.triggerWrap.dom);
67226
67227         me.doc = Ext.isIE ? Ext.getBody() : Ext.getDoc();
67228         me.initTrigger();
67229     },
67230
67231     onEnable: function() {
67232         this.callParent();
67233         this.triggerWrap.unmask();
67234     },
67235     
67236     onDisable: function() {
67237         this.callParent();
67238         this.triggerWrap.mask();
67239     },
67240     
67241     afterRender: function() {
67242         this.callParent();
67243         this.updateEditState();
67244     },
67245
67246     updateEditState: function() {
67247         var me = this,
67248             inputEl = me.inputEl,
67249             triggerWrap = me.triggerWrap,
67250             noeditCls = Ext.baseCSSPrefix + 'trigger-noedit',
67251             displayed,
67252             readOnly;
67253
67254         if (me.rendered) {
67255             if (me.readOnly) {
67256                 inputEl.addCls(noeditCls);
67257                 readOnly = true;
67258                 displayed = false;
67259             } else {
67260                 if (me.editable) {
67261                     inputEl.removeCls(noeditCls);
67262                     readOnly = false;
67263                 } else {
67264                     inputEl.addCls(noeditCls);
67265                     readOnly = true;
67266                 }
67267                 displayed = !me.hideTrigger;
67268             }
67269
67270             triggerWrap.setDisplayed(displayed);
67271             inputEl.dom.readOnly = readOnly;
67272             me.doComponentLayout();
67273         }
67274     },
67275
67276     
67277     getTriggerWidth: function() {
67278         var me = this,
67279             triggerWrap = me.triggerWrap,
67280             totalTriggerWidth = 0;
67281         if (triggerWrap && !me.hideTrigger && !me.readOnly) {
67282             me.triggerEl.each(function(trigger) {
67283                 totalTriggerWidth += trigger.getWidth();
67284             });
67285             totalTriggerWidth += me.triggerWrap.getFrameWidth('lr');
67286         }
67287         return totalTriggerWidth;
67288     },
67289
67290     setHideTrigger: function(hideTrigger) {
67291         if (hideTrigger != this.hideTrigger) {
67292             this.hideTrigger = hideTrigger;
67293             this.updateEditState();
67294         }
67295     },
67296
67297     
67298     setEditable: function(editable) {
67299         if (editable != this.editable) {
67300             this.editable = editable;
67301             this.updateEditState();
67302         }
67303     },
67304
67305     
67306     setReadOnly: function(readOnly) {
67307         if (readOnly != this.readOnly) {
67308             this.readOnly = readOnly;
67309             this.updateEditState();
67310         }
67311     },
67312
67313     
67314     initTrigger: function() {
67315         var me = this,
67316             triggerWrap = me.triggerWrap,
67317             triggerEl = me.triggerEl;
67318
67319         if (me.repeatTriggerClick) {
67320             me.triggerRepeater = Ext.create('Ext.util.ClickRepeater', triggerWrap, {
67321                 preventDefault: true,
67322                 handler: function(cr, e) {
67323                     me.onTriggerWrapClick(e);
67324                 }
67325             });
67326         } else {
67327             me.mon(me.triggerWrap, 'click', me.onTriggerWrapClick, me);
67328         }
67329
67330         triggerEl.addClsOnOver(me.triggerBaseCls + '-over');
67331         triggerEl.each(function(el, c, i) {
67332             el.addClsOnOver(me['trigger' + (i + 1) + 'Cls'] + '-over');
67333         });
67334         triggerEl.addClsOnClick(me.triggerBaseCls + '-click');
67335         triggerEl.each(function(el, c, i) {
67336             el.addClsOnClick(me['trigger' + (i + 1) + 'Cls'] + '-click');
67337         });
67338     },
67339
67340     
67341     onDestroy: function() {
67342         var me = this;
67343         Ext.destroyMembers(me, 'triggerRepeater', 'triggerWrap', 'triggerEl');
67344         delete me.doc;
67345         me.callParent();
67346     },
67347
67348     
67349     onFocus: function() {
67350         var me = this;
67351         this.callParent();
67352         if (!me.mimicing) {
67353             me.bodyEl.addCls(me.wrapFocusCls);
67354             me.mimicing = true;
67355             me.mon(me.doc, 'mousedown', me.mimicBlur, me, {
67356                 delay: 10
67357             });
67358             if (me.monitorTab) {
67359                 me.on('specialkey', me.checkTab, me);
67360             }
67361         }
67362     },
67363
67364     
67365     checkTab: function(me, e) {
67366         if (!this.ignoreMonitorTab && e.getKey() == e.TAB) {
67367             this.triggerBlur();
67368         }
67369     },
67370
67371     
67372     onBlur: Ext.emptyFn,
67373
67374     
67375     mimicBlur: function(e) {
67376         if (!this.isDestroyed && !this.bodyEl.contains(e.target) && this.validateBlur(e)) {
67377             this.triggerBlur();
67378         }
67379     },
67380
67381     
67382     triggerBlur: function() {
67383         var me = this;
67384         me.mimicing = false;
67385         me.mun(me.doc, 'mousedown', me.mimicBlur, me);
67386         if (me.monitorTab && me.inputEl) {
67387             me.un('specialkey', me.checkTab, me);
67388         }
67389         Ext.form.field.Trigger.superclass.onBlur.call(me);
67390         if (me.bodyEl) {
67391             me.bodyEl.removeCls(me.wrapFocusCls);
67392         }
67393     },
67394
67395     beforeBlur: Ext.emptyFn,
67396
67397     
67398     
67399     validateBlur: function(e) {
67400         return true;
67401     },
67402
67403     
67404     
67405     
67406     onTriggerWrapClick: function(e) {
67407         var me = this,
67408             t = e && e.getTarget('.' + Ext.baseCSSPrefix + 'form-trigger', null),
67409             match = t && t.className.match(me.triggerIndexRe),
67410             idx,
67411             triggerClickMethod;
67412
67413         if (match && !me.readOnly) {
67414             idx = parseInt(match[1], 10);
67415             triggerClickMethod = me['onTrigger' + (idx + 1) + 'Click'] || me.onTriggerClick;
67416             if (triggerClickMethod) {
67417                 triggerClickMethod.call(me, e);
67418             }
67419         }
67420     },
67421
67422     
67423     onTriggerClick: Ext.emptyFn
67424
67425     
67426     
67427     
67428 });
67429
67430
67431 Ext.define('Ext.form.field.Picker', {
67432     extend: 'Ext.form.field.Trigger',
67433     alias: 'widget.pickerfield',
67434     alternateClassName: 'Ext.form.Picker',
67435     requires: ['Ext.util.KeyNav'],
67436
67437     
67438     matchFieldWidth: true,
67439
67440     
67441     pickerAlign: 'tl-bl?',
67442
67443     
67444
67445     
67446     openCls: Ext.baseCSSPrefix + 'pickerfield-open',
67447
67448     
67449
67450     
67451     editable: true,
67452
67453
67454     initComponent: function() {
67455         this.callParent();
67456
67457         
67458         this.addEvents(
67459             
67460             'expand',
67461             
67462             'collapse',
67463             
67464             'select'
67465         );
67466     },
67467
67468
67469     initEvents: function() {
67470         var me = this;
67471         me.callParent();
67472
67473         
67474         me.keyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
67475             down: function() {
67476                 if (!me.isExpanded) {
67477                     
67478                     
67479                     me.onTriggerClick();
67480                 }
67481             },
67482             esc: me.collapse,
67483             scope: me,
67484             forceKeyDown: true
67485         });
67486
67487         
67488         if (!me.editable) {
67489             me.mon(me.inputEl, 'click', me.onTriggerClick, me);
67490         }
67491
67492         
67493         if (Ext.isGecko) {
67494             me.inputEl.dom.setAttribute('autocomplete', 'off');
67495         }
67496     },
67497
67498
67499     
67500     expand: function() {
67501         var me = this,
67502             bodyEl, picker, collapseIf;
67503
67504         if (me.rendered && !me.isExpanded && !me.isDestroyed) {
67505             bodyEl = me.bodyEl;
67506             picker = me.getPicker();
67507             collapseIf = me.collapseIf;
67508
67509             
67510             picker.show();
67511             me.isExpanded = true;
67512             me.alignPicker();
67513             bodyEl.addCls(me.openCls);
67514
67515             
67516             me.mon(Ext.getDoc(), {
67517                 mousewheel: collapseIf,
67518                 mousedown: collapseIf,
67519                 scope: me
67520             });
67521             Ext.EventManager.onWindowResize(me.alignPicker, me);
67522             me.fireEvent('expand', me);
67523             me.onExpand();
67524         }
67525     },
67526
67527     onExpand: Ext.emptyFn,
67528
67529     
67530     alignPicker: function() {
67531         var me = this,
67532             picker, isAbove,
67533             aboveSfx = '-above';
67534
67535         if (this.isExpanded) {
67536             picker = me.getPicker();
67537             if (me.matchFieldWidth) {
67538                 
67539                 picker.setSize(me.bodyEl.getWidth(), picker.store && picker.store.getCount() ? null : 0);
67540             }
67541             if (picker.isFloating()) {
67542                 picker.alignTo(me.inputEl, me.pickerAlign, me.pickerOffset);
67543
67544                 
67545                 
67546                 isAbove = picker.el.getY() < me.inputEl.getY();
67547                 me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls + aboveSfx);
67548                 picker.el[isAbove ? 'addCls' : 'removeCls'](picker.baseCls + aboveSfx);
67549             }
67550         }
67551     },
67552
67553     
67554     collapse: function() {
67555         if (this.isExpanded && !this.isDestroyed) {
67556             var me = this,
67557                 openCls = me.openCls,
67558                 picker = me.picker,
67559                 doc = Ext.getDoc(),
67560                 collapseIf = me.collapseIf,
67561                 aboveSfx = '-above';
67562
67563             
67564             picker.hide();
67565             me.isExpanded = false;
67566
67567             
67568             me.bodyEl.removeCls([openCls, openCls + aboveSfx]);
67569             picker.el.removeCls(picker.baseCls + aboveSfx);
67570
67571             
67572             doc.un('mousewheel', collapseIf, me);
67573             doc.un('mousedown', collapseIf, me);
67574             Ext.EventManager.removeResizeListener(me.alignPicker, me);
67575             me.fireEvent('collapse', me);
67576             me.onCollapse();
67577         }
67578     },
67579
67580     onCollapse: Ext.emptyFn,
67581
67582
67583     
67584     collapseIf: function(e) {
67585         var me = this;
67586         if (!me.isDestroyed && !e.within(me.bodyEl, false, true) && !e.within(me.picker.el, false, true)) {
67587             me.collapse();
67588         }
67589     },
67590
67591     
67592     getPicker: function() {
67593         var me = this;
67594         return me.picker || (me.picker = me.createPicker());
67595     },
67596
67597     
67598     createPicker: Ext.emptyFn,
67599
67600     
67601     onTriggerClick: function() {
67602         var me = this;
67603         if (!me.readOnly && !me.disabled) {
67604             if (me.isExpanded) {
67605                 me.collapse();
67606             } else {
67607                 me.expand();
67608             }
67609             me.inputEl.focus();
67610         }
67611     },
67612
67613     mimicBlur: function(e) {
67614         var me = this,
67615             picker = me.picker;
67616         
67617         if (!picker || !e.within(picker.el, false, true)) {
67618             me.callParent(arguments);
67619         }
67620     },
67621
67622     onDestroy : function(){
67623         var me = this;
67624         Ext.EventManager.removeResizeListener(me.alignPicker, me);
67625         Ext.destroy(me.picker, me.keyNav);
67626         me.callParent();
67627     }
67628
67629 });
67630
67631
67632
67633 Ext.define('Ext.form.field.Spinner', {
67634     extend: 'Ext.form.field.Trigger',
67635     alias: 'widget.spinnerfield',
67636     alternateClassName: 'Ext.form.Spinner',
67637     requires: ['Ext.util.KeyNav'],
67638
67639     trigger1Cls: Ext.baseCSSPrefix + 'form-spinner-up',
67640     trigger2Cls: Ext.baseCSSPrefix + 'form-spinner-down',
67641
67642     
67643     spinUpEnabled: true,
67644
67645     
67646     spinDownEnabled: true,
67647
67648     
67649     keyNavEnabled: true,
67650
67651     
67652     mouseWheelEnabled: true,
67653
67654     
67655     repeatTriggerClick: true,
67656
67657     
67658     onSpinUp: Ext.emptyFn,
67659
67660     
67661     onSpinDown: Ext.emptyFn,
67662
67663     initComponent: function() {
67664         this.callParent();
67665
67666         this.addEvents(
67667             
67668             'spin',
67669
67670             
67671             'spinup',
67672
67673             
67674             'spindown'
67675         );
67676     },
67677
67678     
67679     onRender: function() {
67680         var me = this,
67681             triggers;
67682
67683         me.callParent(arguments);
67684         triggers = me.triggerEl;
67685
67686         
67687         me.spinUpEl = triggers.item(0);
67688         
67689         me.spinDownEl = triggers.item(1);
67690
67691         
67692         me.setSpinUpEnabled(me.spinUpEnabled);
67693         me.setSpinDownEnabled(me.spinDownEnabled);
67694
67695         
67696         if (me.keyNavEnabled) {
67697             me.spinnerKeyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
67698                 scope: me,
67699                 up: me.spinUp,
67700                 down: me.spinDown
67701             });
67702         }
67703
67704         
67705         if (me.mouseWheelEnabled) {
67706             me.mon(me.bodyEl, 'mousewheel', me.onMouseWheel, me);
67707         }
67708     },
67709
67710     
67711     getTriggerWidth: function() {
67712         return this.hideTrigger || this.readOnly ? 0 : this.spinUpEl.getWidth() + this.triggerWrap.getFrameWidth('lr');
67713     },
67714
67715     
67716     onTrigger1Click: function() {
67717         this.spinUp();
67718     },
67719
67720     
67721     onTrigger2Click: function() {
67722         this.spinDown();
67723     },
67724
67725     
67726     spinUp: function() {
67727         var me = this;
67728         if (me.spinUpEnabled && !me.disabled) {
67729             me.fireEvent('spin', me, 'up');
67730             me.fireEvent('spinup', me);
67731             me.onSpinUp();
67732         }
67733     },
67734
67735     
67736     spinDown: function() {
67737         var me = this;
67738         if (me.spinDownEnabled && !me.disabled) {
67739             me.fireEvent('spin', me, 'down');
67740             me.fireEvent('spindown', me);
67741             me.onSpinDown();
67742         }
67743     },
67744
67745     
67746     setSpinUpEnabled: function(enabled) {
67747         var me = this,
67748             wasEnabled = me.spinUpEnabled;
67749         me.spinUpEnabled = enabled;
67750         if (wasEnabled !== enabled && me.rendered) {
67751             me.spinUpEl[enabled ? 'removeCls' : 'addCls'](me.trigger1Cls + '-disabled');
67752         }
67753     },
67754
67755     
67756     setSpinDownEnabled: function(enabled) {
67757         var me = this,
67758             wasEnabled = me.spinDownEnabled;
67759         me.spinDownEnabled = enabled;
67760         if (wasEnabled !== enabled && me.rendered) {
67761             me.spinDownEl[enabled ? 'removeCls' : 'addCls'](me.trigger2Cls + '-disabled');
67762         }
67763     },
67764
67765     
67766     onMouseWheel: function(e) {
67767         var me = this,
67768             delta;
67769         if (me.hasFocus) {
67770             delta = e.getWheelDelta();
67771             if (delta > 0) {
67772                 me.spinUp();
67773             }
67774             else if (delta < 0) {
67775                 me.spinDown();
67776             }
67777             e.stopEvent();
67778         }
67779     },
67780
67781     onDestroy: function() {
67782         Ext.destroyMembers(this, 'spinnerKeyNav', 'spinUpEl', 'spinDownEl');
67783         this.callParent();
67784     }
67785
67786 });
67787
67788 Ext.define('Ext.form.field.Number', {
67789     extend:'Ext.form.field.Spinner',
67790     alias: 'widget.numberfield',
67791     alternateClassName: ['Ext.form.NumberField', 'Ext.form.Number'],
67792
67793     
67794     
67795
67796     
67797     allowDecimals : true,
67798
67799     
67800     decimalSeparator : '.',
67801
67802     
67803     decimalPrecision : 2,
67804
67805     
67806     minValue: Number.NEGATIVE_INFINITY,
67807
67808     
67809     maxValue: Number.MAX_VALUE,
67810
67811     
67812     step: 1,
67813
67814     
67815     minText : 'The minimum value for this field is {0}',
67816
67817     
67818     maxText : 'The maximum value for this field is {0}',
67819
67820     
67821     nanText : '{0} is not a valid number',
67822
67823     
67824     negativeText : 'The value cannot be negative',
67825
67826     
67827     baseChars : '0123456789',
67828
67829     
67830     autoStripChars: false,
67831
67832     initComponent: function() {
67833         var me = this,
67834             allowed;
67835
67836         me.callParent();
67837
67838         me.setMinValue(me.minValue);
67839         me.setMaxValue(me.maxValue);
67840
67841         
67842         if (me.disableKeyFilter !== true) {
67843             allowed = me.baseChars + '';
67844             if (me.allowDecimals) {
67845                 allowed += me.decimalSeparator;
67846             }
67847             if (me.minValue < 0) {
67848                 allowed += '-';
67849             }
67850             allowed = Ext.String.escapeRegex(allowed);
67851             me.maskRe = new RegExp('[' + allowed + ']');
67852             if (me.autoStripChars) {
67853                 me.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi');
67854             }
67855         }
67856     },
67857
67858     
67859     getErrors: function(value) {
67860         var me = this,
67861             errors = me.callParent(arguments),
67862             format = Ext.String.format,
67863             num;
67864
67865         value = Ext.isDefined(value) ? value : this.processRawValue(this.getRawValue());
67866
67867         if (value.length < 1) { 
67868              return errors;
67869         }
67870
67871         value = String(value).replace(me.decimalSeparator, '.');
67872
67873         if(isNaN(value)){
67874             errors.push(format(me.nanText, value));
67875         }
67876
67877         num = me.parseValue(value);
67878
67879         if (me.minValue === 0 && num < 0) {
67880             errors.push(this.negativeText);
67881         }
67882         else if (num < me.minValue) {
67883             errors.push(format(me.minText, me.minValue));
67884         }
67885
67886         if (num > me.maxValue) {
67887             errors.push(format(me.maxText, me.maxValue));
67888         }
67889
67890
67891         return errors;
67892     },
67893
67894     rawToValue: function(rawValue) {
67895         return this.fixPrecision(this.parseValue(rawValue)) || rawValue || null;
67896     },
67897
67898     valueToRaw: function(value) {
67899         var me = this,
67900             decimalSeparator = me.decimalSeparator;
67901         value = me.parseValue(value);
67902         value = me.fixPrecision(value);
67903         value = Ext.isNumber(value) ? value : parseFloat(String(value).replace(decimalSeparator, '.'));
67904         value = isNaN(value) ? '' : String(value).replace('.', decimalSeparator);
67905         return value;
67906     },
67907
67908     onChange: function() {
67909         var me = this,
67910             value = me.getValue(),
67911             valueIsNull = value === null;
67912
67913         me.callParent(arguments);
67914
67915         
67916         me.setSpinUpEnabled(valueIsNull || value < me.maxValue);
67917         me.setSpinDownEnabled(valueIsNull || value > me.minValue);
67918     },
67919
67920     
67921     setMinValue : function(value) {
67922         this.minValue = Ext.Number.from(value, Number.NEGATIVE_INFINITY);
67923     },
67924
67925     
67926     setMaxValue: function(value) {
67927         this.maxValue = Ext.Number.from(value, Number.MAX_VALUE);
67928     },
67929
67930     
67931     parseValue : function(value) {
67932         value = parseFloat(String(value).replace(this.decimalSeparator, '.'));
67933         return isNaN(value) ? null : value;
67934     },
67935
67936     
67937     fixPrecision : function(value) {
67938         var me = this,
67939             nan = isNaN(value),
67940             precision = me.decimalPrecision;
67941
67942         if (nan || !value) {
67943             return nan ? '' : value;
67944         } else if (!me.allowDecimals || precision <= 0) {
67945             precision = 0;
67946         }
67947
67948         return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
67949     },
67950
67951     beforeBlur : function() {
67952         var me = this,
67953             v = me.parseValue(me.getRawValue());
67954
67955         if (!Ext.isEmpty(v)) {
67956             me.setValue(v);
67957         }
67958     },
67959
67960     onSpinUp: function() {
67961         var me = this;
67962         if (!me.readOnly) {
67963             me.setValue(Ext.Number.constrain(me.getValue() + me.step, me.minValue, me.maxValue));
67964         }
67965     },
67966
67967     onSpinDown: function() {
67968         var me = this;
67969         if (!me.readOnly) {
67970             me.setValue(Ext.Number.constrain(me.getValue() - me.step, me.minValue, me.maxValue));
67971         }
67972     }
67973 });
67974
67975
67976 Ext.define('Ext.toolbar.Paging', {
67977     extend: 'Ext.toolbar.Toolbar',
67978     alias: 'widget.pagingtoolbar',
67979     alternateClassName: 'Ext.PagingToolbar',
67980     requires: ['Ext.toolbar.TextItem', 'Ext.form.field.Number'],
67981     
67982     
67983     displayInfo: false,
67984     
67985     prependButtons: false,
67986     
67987     displayMsg : 'Displaying {0} - {1} of {2}',
67988     
67989     emptyMsg : 'No data to display',
67990     
67991     beforePageText : 'Page',
67992     
67993     afterPageText : 'of {0}',
67994     
67995     firstText : 'First Page',
67996     
67997     prevText : 'Previous Page',
67998     
67999     nextText : 'Next Page',
68000     
68001     lastText : 'Last Page',
68002     
68003     refreshText : 'Refresh',
68004     
68005     inputItemWidth : 30,
68006     
68007     
68008     getPagingItems: function() {
68009         var me = this;
68010         
68011         return [{
68012             itemId: 'first',
68013             tooltip: me.firstText,
68014             overflowText: me.firstText,
68015             iconCls: Ext.baseCSSPrefix + 'tbar-page-first',
68016             disabled: true,
68017             handler: me.moveFirst,
68018             scope: me
68019         },{
68020             itemId: 'prev',
68021             tooltip: me.prevText,
68022             overflowText: me.prevText,
68023             iconCls: Ext.baseCSSPrefix + 'tbar-page-prev',
68024             disabled: true,
68025             handler: me.movePrevious,
68026             scope: me
68027         },
68028         '-',
68029         me.beforePageText,
68030         {
68031             xtype: 'numberfield',
68032             itemId: 'inputItem',
68033             name: 'inputItem',
68034             cls: Ext.baseCSSPrefix + 'tbar-page-number',
68035             allowDecimals: false,
68036             minValue: 1,
68037             hideTrigger: true,
68038             enableKeyEvents: true,
68039             selectOnFocus: true,
68040             submitValue: false,
68041             width: me.inputItemWidth,
68042             margins: '-1 2 3 2',
68043             listeners: {
68044                 scope: me,
68045                 keydown: me.onPagingKeyDown,
68046                 blur: me.onPagingBlur
68047             }
68048         },{
68049             xtype: 'tbtext',
68050             itemId: 'afterTextItem',
68051             text: Ext.String.format(me.afterPageText, 1)
68052         },
68053         '-',
68054         {
68055             itemId: 'next',
68056             tooltip: me.nextText,
68057             overflowText: me.nextText,
68058             iconCls: Ext.baseCSSPrefix + 'tbar-page-next',
68059             disabled: true,
68060             handler: me.moveNext,
68061             scope: me
68062         },{
68063             itemId: 'last',
68064             tooltip: me.lastText,
68065             overflowText: me.lastText,
68066             iconCls: Ext.baseCSSPrefix + 'tbar-page-last',
68067             disabled: true,
68068             handler: me.moveLast,
68069             scope: me
68070         },
68071         '-',
68072         {
68073             itemId: 'refresh',
68074             tooltip: me.refreshText,
68075             overflowText: me.refreshText,
68076             iconCls: Ext.baseCSSPrefix + 'tbar-loading',
68077             handler: me.doRefresh,
68078             scope: me
68079         }];
68080     },
68081
68082     initComponent : function(){
68083         var me = this,
68084             pagingItems = me.getPagingItems(),
68085             userItems   = me.items || me.buttons || [];
68086             
68087         if (me.prependButtons) {
68088             me.items = userItems.concat(pagingItems);
68089         } else {
68090             me.items = pagingItems.concat(userItems);
68091         }
68092         delete me.buttons;
68093         
68094         if (me.displayInfo) {
68095             me.items.push('->');
68096             me.items.push({xtype: 'tbtext', itemId: 'displayItem'});
68097         }
68098         
68099         me.callParent();
68100         
68101         me.addEvents(
68102             
68103             'change',
68104             
68105             'beforechange'
68106         );
68107         me.on('afterlayout', me.onLoad, me, {single: true});
68108
68109         me.bindStore(me.store, true);
68110     },
68111     
68112     updateInfo : function(){
68113         var me = this,
68114             displayItem = me.child('#displayItem'),
68115             store = me.store,
68116             pageData = me.getPageData(),
68117             count, msg;
68118
68119         if (displayItem) {
68120             count = store.getCount();
68121             if (count === 0) {
68122                 msg = me.emptyMsg;
68123             } else {
68124                 msg = Ext.String.format(
68125                     me.displayMsg,
68126                     pageData.fromRecord,
68127                     pageData.toRecord,
68128                     pageData.total
68129                 );
68130             }
68131             displayItem.setText(msg);
68132             me.doComponentLayout();
68133         }
68134     },
68135
68136     
68137     onLoad : function(){
68138         var me = this,
68139             pageData,
68140             currPage,
68141             pageCount,
68142             afterText;
68143             
68144         if (!me.rendered) {
68145             return;
68146         }
68147
68148         pageData = me.getPageData();
68149         currPage = pageData.currentPage;
68150         pageCount = pageData.pageCount;
68151         afterText = Ext.String.format(me.afterPageText, isNaN(pageCount) ? 1 : pageCount);
68152
68153         me.child('#afterTextItem').setText(afterText);
68154         me.child('#inputItem').setValue(currPage);
68155         me.child('#first').setDisabled(currPage === 1);
68156         me.child('#prev').setDisabled(currPage === 1);
68157         me.child('#next').setDisabled(currPage === pageCount);
68158         me.child('#last').setDisabled(currPage === pageCount);
68159         me.child('#refresh').enable();
68160         me.updateInfo();
68161         me.fireEvent('change', me, pageData);
68162     },
68163
68164     
68165     getPageData : function(){
68166         var store = this.store,
68167             totalCount = store.getTotalCount();
68168             
68169         return {
68170             total : totalCount,
68171             currentPage : store.currentPage,
68172             pageCount: Math.ceil(totalCount / store.pageSize),
68173             
68174             fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
68175             toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
68176             
68177         };
68178     },
68179
68180     
68181     onLoadError : function(){
68182         if (!this.rendered) {
68183             return;
68184         }
68185         this.child('#refresh').enable();
68186     },
68187
68188     
68189     readPageFromInput : function(pageData){
68190         var v = this.child('#inputItem').getValue(),
68191             pageNum = parseInt(v, 10);
68192             
68193         if (!v || isNaN(pageNum)) {
68194             this.child('#inputItem').setValue(pageData.currentPage);
68195             return false;
68196         }
68197         return pageNum;
68198     },
68199
68200     onPagingFocus : function(){
68201         this.child('#inputItem').select();
68202     },
68203
68204     
68205     onPagingBlur : function(e){
68206         var curPage = this.getPageData().currentPage;
68207         this.child('#inputItem').setValue(curPage);
68208     },
68209
68210     
68211     onPagingKeyDown : function(field, e){
68212         var k = e.getKey(),
68213             pageData = this.getPageData(),
68214             increment = e.shiftKey ? 10 : 1,
68215             pageNum,
68216             me = this;
68217
68218         if (k == e.RETURN) {
68219             e.stopEvent();
68220             pageNum = me.readPageFromInput(pageData);
68221             if (pageNum !== false) {
68222                 pageNum = Math.min(Math.max(1, pageNum), pageData.total);
68223                 if(me.fireEvent('beforechange', me, pageNum) !== false){
68224                     me.store.loadPage(pageNum);
68225                 }
68226             }
68227         } else if (k == e.HOME || k == e.END) {
68228             e.stopEvent();
68229             pageNum = k == e.HOME ? 1 : pageData.pageCount;
68230             field.setValue(pageNum);
68231         } else if (k == e.UP || k == e.PAGEUP || k == e.DOWN || k == e.PAGEDOWN) {
68232             e.stopEvent();
68233             pageNum = me.readPageFromInput(pageData);
68234             if (pageNum) {
68235                 if (k == e.DOWN || k == e.PAGEDOWN) {
68236                     increment *= -1;
68237                 }
68238                 pageNum += increment;
68239                 if (pageNum >= 1 && pageNum <= pageData.pages) {
68240                     field.setValue(pageNum);
68241                 }
68242             }
68243         }
68244     },
68245
68246     
68247     beforeLoad : function(){
68248         if(this.rendered && this.refresh){
68249             this.refresh.disable();
68250         }
68251     },
68252
68253     
68254     doLoad : function(start){
68255         if(this.fireEvent('beforechange', this, o) !== false){
68256             this.store.load();
68257         }
68258     },
68259
68260     
68261     moveFirst : function(){
68262         var me = this;
68263         if(me.fireEvent('beforechange', me, 1) !== false){
68264             me.store.loadPage(1);
68265         }
68266     },
68267
68268     
68269     movePrevious : function(){
68270         var me = this,
68271             prev = me.store.currentPage - 1;
68272         
68273         if(me.fireEvent('beforechange', me, prev) !== false){
68274             me.store.previousPage();
68275         }
68276     },
68277
68278     
68279     moveNext : function(){
68280         var me = this;        
68281         if(me.fireEvent('beforechange', me, me.store.currentPage + 1) !== false){
68282             me.store.nextPage();
68283         }
68284     },
68285
68286     
68287     moveLast : function(){
68288         var me = this, 
68289             last = this.getPageData().pageCount;
68290         
68291         if(me.fireEvent('beforechange', me, last) !== false){
68292             me.store.loadPage(last);
68293         }
68294     },
68295
68296     
68297     doRefresh : function(){
68298         var me = this,
68299             current = me.store.currentPage;
68300         
68301         if(me.fireEvent('beforechange', me, current) !== false){
68302             me.store.loadPage(current);
68303         }
68304     },
68305
68306     
68307     bindStore : function(store, initial){
68308         var me = this;
68309         
68310         if (!initial && me.store) {
68311             if(store !== me.store && me.store.autoDestroy){
68312                 me.store.destroy();
68313             }else{
68314                 me.store.un('beforeload', me.beforeLoad, me);
68315                 me.store.un('load', me.onLoad, me);
68316                 me.store.un('exception', me.onLoadError, me);
68317             }
68318             if(!store){
68319                 me.store = null;
68320             }
68321         }
68322         if (store) {
68323             store = Ext.data.StoreManager.lookup(store);
68324             store.on({
68325                 scope: me,
68326                 beforeload: me.beforeLoad,
68327                 load: me.onLoad,
68328                 exception: me.onLoadError
68329             });
68330         }
68331         me.store = store;
68332     },
68333
68334     
68335     unbind : function(store){
68336         this.bindStore(null);
68337     },
68338
68339     
68340     bind : function(store){
68341         this.bindStore(store);
68342     },
68343
68344     
68345     onDestroy : function(){
68346         this.bindStore(null);
68347         this.callParent();
68348     }
68349 });
68350
68351
68352 Ext.define('Ext.view.BoundList', {
68353     extend: 'Ext.view.View',
68354     alias: 'widget.boundlist',
68355     alternateClassName: 'Ext.BoundList',
68356     requires: ['Ext.layout.component.BoundList', 'Ext.toolbar.Paging'],
68357
68358     
68359     pageSize: 0,
68360
68361     
68362
68363     
68364     autoScroll: true,
68365     baseCls: Ext.baseCSSPrefix + 'boundlist',
68366     listItemCls: '',
68367     shadow: false,
68368     trackOver: true,
68369     refreshed: 0,
68370
68371     ariaRole: 'listbox',
68372
68373     componentLayout: 'boundlist',
68374
68375     renderTpl: ['<div class="list-ct"></div>'],
68376
68377     initComponent: function() {
68378         var me = this,
68379             baseCls = me.baseCls,
68380             itemCls = baseCls + '-item';
68381         me.itemCls = itemCls;
68382         me.selectedItemCls = baseCls + '-selected';
68383         me.overItemCls = baseCls + '-item-over';
68384         me.itemSelector = "." + itemCls;
68385
68386         if (me.floating) {
68387             me.addCls(baseCls + '-floating');
68388         }
68389
68390         
68391         
68392         me.tpl = Ext.create('Ext.XTemplate', 
68393             '<ul><tpl for=".">',
68394                 '<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
68395             '</tpl></ul>'
68396         );
68397
68398         if (me.pageSize) {
68399             me.pagingToolbar = me.createPagingToolbar();
68400         }
68401
68402         me.callParent();
68403
68404         Ext.applyIf(me.renderSelectors, {
68405             listEl: '.list-ct'
68406         });
68407     },
68408
68409     createPagingToolbar: function() {
68410         return Ext.widget('pagingtoolbar', {
68411             pageSize: this.pageSize,
68412             store: this.store,
68413             border: false
68414         });
68415     },
68416
68417     onRender: function() {
68418         var me = this,
68419             toolbar = me.pagingToolbar;
68420         me.callParent(arguments);
68421         if (toolbar) {
68422             toolbar.render(me.el);
68423         }
68424     },
68425
68426     bindStore : function(store, initial) {
68427         var me = this,
68428             toolbar = me.pagingToolbar;
68429         me.callParent(arguments);
68430         if (toolbar) {
68431             toolbar.bindStore(store, initial);
68432         }
68433     },
68434
68435     getTargetEl: function() {
68436         return this.listEl || this.el;
68437     },
68438
68439     getInnerTpl: function(displayField) {
68440         return '{' + displayField + '}';
68441     },
68442
68443     refresh: function() {
68444         var me = this;
68445         me.callParent();
68446         if (me.isVisible()) {
68447             me.refreshed++;
68448             me.doComponentLayout();
68449             me.refreshed--;
68450         }
68451     },
68452     
68453     initAria: function() {
68454         this.callParent();
68455         
68456         var selModel = this.getSelectionModel(),
68457             mode     = selModel.getSelectionMode(),
68458             actionEl = this.getActionEl();
68459         
68460         
68461         if (mode !== 'SINGLE') {
68462             actionEl.dom.setAttribute('aria-multiselectable', true);
68463         }
68464     },
68465
68466     onDestroy: function() {
68467         Ext.destroyMembers(this, 'pagingToolbar', 'listEl');
68468         this.callParent();
68469     }
68470 });
68471
68472
68473 Ext.define('Ext.view.BoundListKeyNav', {
68474     extend: 'Ext.util.KeyNav',
68475     requires: 'Ext.view.BoundList',
68476
68477     
68478
68479     constructor: function(el, config) {
68480         var me = this;
68481         me.boundList = config.boundList;
68482         me.callParent([el, Ext.apply({}, config, me.defaultHandlers)]);
68483     },
68484
68485     defaultHandlers: {
68486         up: function() {
68487             var me = this,
68488                 boundList = me.boundList,
68489                 allItems = boundList.all,
68490                 oldItem = boundList.highlightedItem,
68491                 oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1,
68492                 newItemIdx = oldItemIdx > 0 ? oldItemIdx - 1 : allItems.getCount() - 1; 
68493             me.highlightAt(newItemIdx);
68494         },
68495
68496         down: function() {
68497             var me = this,
68498                 boundList = me.boundList,
68499                 allItems = boundList.all,
68500                 oldItem = boundList.highlightedItem,
68501                 oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1,
68502                 newItemIdx = oldItemIdx < allItems.getCount() - 1 ? oldItemIdx + 1 : 0; 
68503             me.highlightAt(newItemIdx);
68504         },
68505
68506         pageup: function() {
68507             
68508         },
68509
68510         pagedown: function() {
68511             
68512         },
68513
68514         home: function() {
68515             this.highlightAt(0);
68516         },
68517
68518         end: function() {
68519             var me = this;
68520             me.highlightAt(me.boundList.all.getCount() - 1);
68521         },
68522
68523         enter: function(e) {
68524             this.selectHighlighted(e);
68525         }
68526     },
68527
68528     
68529     highlightAt: function(index) {
68530         var boundList = this.boundList,
68531             item = boundList.all.item(index);
68532         if (item) {
68533             item = item.dom;
68534             boundList.highlightItem(item);
68535             boundList.getTargetEl().scrollChildIntoView(item, false);
68536         }
68537     },
68538
68539     
68540     selectHighlighted: function(e) {
68541         var me = this,
68542             boundList = me.boundList,
68543             highlighted = boundList.highlightedItem,
68544             selModel = boundList.getSelectionModel();
68545         if (highlighted) {
68546             selModel.selectWithEvent(boundList.getRecord(highlighted), e);
68547         }
68548     }
68549
68550 });
68551
68552 Ext.define('Ext.form.field.ComboBox', {
68553     extend:'Ext.form.field.Picker',
68554     requires: ['Ext.util.DelayedTask', 'Ext.EventObject', 'Ext.view.BoundList', 'Ext.view.BoundListKeyNav', 'Ext.data.StoreManager'],
68555     alternateClassName: 'Ext.form.ComboBox',
68556     alias: ['widget.combobox', 'widget.combo'],
68557
68558     
68559     triggerCls: Ext.baseCSSPrefix + 'form-arrow-trigger',
68560
68561     
68562
68563     
68564     multiSelect: false,
68565
68566     
68567     delimiter: ', ',
68568
68569     
68570     displayField: 'text',
68571
68572     
68573
68574     
68575     triggerAction: 'all',
68576
68577     
68578     allQuery: '',
68579
68580     
68581     queryParam: 'query',
68582
68583     
68584     queryMode: 'remote',
68585
68586     queryCaching: true,
68587
68588     
68589     pageSize: 0,
68590
68591     
68592
68593     
68594
68595     
68596     autoSelect: true,
68597
68598     
68599     typeAhead: false,
68600
68601     
68602     typeAheadDelay: 250,
68603
68604     
68605     selectOnTab: true,
68606
68607     
68608     forceSelection: false,
68609
68610     
68611
68612     
68613
68614     
68615     defaultListConfig: {
68616         emptyText: '',
68617         loadingText: 'Loading...',
68618         loadingHeight: 70,
68619         minWidth: 70,
68620         maxHeight: 300,
68621         shadow: 'sides'
68622     },
68623
68624     
68625
68626     
68627
68628     
68629     ignoreSelection: 0,
68630
68631     initComponent: function() {
68632         var me = this,
68633             isDefined = Ext.isDefined,
68634             store = me.store,
68635             transform = me.transform,
68636             transformSelect, isLocalMode;
68637
68638         if (!store && !transform) {
68639             Ext.Error.raise('Either a valid store, or a HTML select to transform, must be configured on the combo.');
68640         }
68641         if (me.typeAhead && me.multiSelect) {
68642             Ext.Error.raise('typeAhead and multiSelect are mutually exclusive options -- please remove one of them.');
68643         }
68644         if (me.typeAhead && !me.editable) {
68645             Ext.Error.raise('If typeAhead is enabled the combo must be editable: true -- please change one of those settings.');
68646         }
68647         if (me.selectOnFocus && !me.editable) {
68648             Ext.Error.raise('If selectOnFocus is enabled the combo must be editable: true -- please change one of those settings.');
68649         }
68650
68651         this.addEvents(
68652             
68653
68654             
68655             'beforequery',
68656
68657             
68658             'select'
68659         );
68660
68661         
68662         if (!store && transform) {
68663             transformSelect = Ext.getDom(transform);
68664             if (transformSelect) {
68665                 store = Ext.Array.map(Ext.Array.from(transformSelect.options), function(option) {
68666                     return [option.value, option.text];
68667                 });
68668                 if (!me.name) {
68669                     me.name = transformSelect.name;
68670                 }
68671                 if (!('value' in me)) {
68672                     me.value = transformSelect.value;
68673                 }
68674             }
68675         }
68676
68677         me.bindStore(store, true);
68678         store = me.store;
68679         if (store.autoCreated) {
68680             me.queryMode = 'local';
68681             me.valueField = me.displayField = 'field1';
68682             if (!store.expanded) {
68683                 me.displayField = 'field2';
68684             }
68685         }
68686
68687
68688         if (!isDefined(me.valueField)) {
68689             me.valueField = me.displayField;
68690         }
68691
68692         isLocalMode = me.queryMode === 'local';
68693         if (!isDefined(me.queryDelay)) {
68694             me.queryDelay = isLocalMode ? 10 : 500;
68695         }
68696         if (!isDefined(me.minChars)) {
68697             me.minChars = isLocalMode ? 0 : 4;
68698         }
68699
68700         if (!me.displayTpl) {
68701             me.displayTpl = Ext.create('Ext.XTemplate',
68702                 '<tpl for=".">' +
68703                     '{[typeof values === "string" ? values : values.' + me.displayField + ']}' +
68704                     '<tpl if="xindex < xcount">' + me.delimiter + '</tpl>' +
68705                 '</tpl>'
68706             );
68707         } else if (Ext.isString(me.displayTpl)) {
68708             me.displayTpl = Ext.create('Ext.XTemplate', me.displayTpl);
68709         }
68710
68711         me.callParent();
68712
68713         me.doQueryTask = Ext.create('Ext.util.DelayedTask', me.doRawQuery, me);
68714
68715         
68716         if (me.store.getCount() > 0) {
68717             me.setValue(me.value);
68718         }
68719
68720         
68721         if (transformSelect) {
68722             me.render(transformSelect.parentNode, transformSelect);
68723             Ext.removeNode(transformSelect);
68724             delete me.renderTo;
68725         }
68726     },
68727
68728     beforeBlur: function() {
68729         var me = this;
68730         me.doQueryTask.cancel();
68731         if (me.forceSelection) {
68732             me.assertValue();
68733         } else {
68734             me.collapse();
68735         }
68736     },
68737
68738     
68739     assertValue: function() {
68740         var me = this,
68741             value = me.getRawValue(),
68742             rec;
68743
68744         if (me.multiSelect) {
68745             
68746             
68747             if (value !== me.getDisplayValue()) {
68748                 me.setValue(me.lastSelection);
68749             }
68750         } else {
68751             
68752             
68753             rec = me.findRecordByDisplay(value);
68754             if (rec) {
68755                 me.select(rec);
68756             } else {
68757                 me.setValue(me.lastSelection);
68758             }
68759         }
68760         me.collapse();
68761     },
68762
68763     onTypeAhead: function() {
68764         var me = this,
68765             displayField = me.displayField,
68766             record = me.store.findRecord(displayField, me.getRawValue()),
68767             boundList = me.getPicker(),
68768             newValue, len, selStart;
68769
68770         if (record) {
68771             newValue = record.get(displayField);
68772             len = newValue.length;
68773             selStart = me.getRawValue().length;
68774
68775             boundList.highlightItem(boundList.getNode(record));
68776
68777             if (selStart !== 0 && selStart !== len) {
68778                 me.setRawValue(newValue);
68779                 me.selectText(selStart, newValue.length);
68780             }
68781         }
68782     },
68783
68784     
68785     
68786     resetToDefault: function() {
68787
68788     },
68789
68790     bindStore: function(store, initial) {
68791         var me = this,
68792             oldStore = me.store;
68793
68794         
68795         
68796         if (oldStore && !initial) {
68797             if (oldStore !== store && oldStore.autoDestroy) {
68798                 oldStore.destroy();
68799             } else {
68800                 oldStore.un({
68801                     scope: me,
68802                     load: me.onLoad,
68803                     exception: me.collapse
68804                 });
68805             }
68806             if (!store) {
68807                 me.store = null;
68808                 if (me.picker) {
68809                     me.picker.bindStore(null);
68810                 }
68811             }
68812         }
68813         if (store) {
68814             if (!initial) {
68815                 me.resetToDefault();
68816             }
68817
68818             me.store = Ext.data.StoreManager.lookup(store);
68819             me.store.on({
68820                 scope: me,
68821                 load: me.onLoad,
68822                 exception: me.collapse
68823             });
68824
68825             if (me.picker) {
68826                 me.picker.bindStore(store);
68827             }
68828         }
68829     },
68830
68831     onLoad: function() {
68832         var me = this,
68833             value = me.value;
68834
68835         me.syncSelection();
68836         if (me.picker && !me.picker.getSelectionModel().hasSelection()) {
68837             me.doAutoSelect();
68838         }
68839     },
68840
68841     
68842     doRawQuery: function() {
68843         this.doQuery(this.getRawValue());
68844     },
68845
68846     
68847     doQuery: function(queryString, forceAll) {
68848         queryString = queryString || '';
68849
68850         
68851         
68852         var me = this,
68853             qe = {
68854                 query: queryString,
68855                 forceAll: forceAll,
68856                 combo: me,
68857                 cancel: false
68858             },
68859             store = me.store,
68860             isLocalMode = me.queryMode === 'local';
68861
68862         if (me.fireEvent('beforequery', qe) === false || qe.cancel) {
68863             return false;
68864         }
68865
68866         
68867         queryString = qe.query;
68868         forceAll = qe.forceAll;
68869
68870         
68871         if (forceAll || (queryString.length >= me.minChars)) {
68872             
68873             me.expand();
68874
68875             
68876             if (!me.queryCaching || me.lastQuery !== queryString) {
68877                 me.lastQuery = queryString;
68878                 store.clearFilter(!forceAll);
68879                 if (isLocalMode) {
68880                     if (!forceAll) {
68881                         store.filter(me.displayField, queryString);
68882                     }
68883                 } else {
68884                     store.load({
68885                         params: me.getParams(queryString)
68886                     });
68887                 }
68888             }
68889
68890             
68891             if (me.getRawValue() !== me.getDisplayValue()) {
68892                 me.ignoreSelection++;
68893                 me.picker.getSelectionModel().deselectAll();
68894                 me.ignoreSelection--;
68895             }
68896
68897             if (isLocalMode) {
68898                 me.doAutoSelect();
68899             }
68900             if (me.typeAhead) {
68901                 me.doTypeAhead();
68902             }
68903         }
68904         return true;
68905     },
68906
68907     
68908     getParams: function(queryString) {
68909         var p = {},
68910             pageSize = this.pageSize,
68911             param = this.queryParam;
68912             
68913         if (param) {
68914             p[param] = queryString;
68915         }
68916         
68917         if (pageSize) {
68918             p.start = 0;
68919             p.limit = pageSize;
68920         }
68921         return p;
68922     },
68923
68924     
68925     doAutoSelect: function() {
68926         var me = this,
68927             picker = me.picker,
68928             lastSelected, itemNode;
68929         if (picker && me.autoSelect && me.store.getCount() > 0) {
68930             
68931             lastSelected = picker.getSelectionModel().lastSelected;
68932             itemNode = picker.getNode(lastSelected || 0);
68933             if (itemNode) {
68934                 picker.highlightItem(itemNode);
68935                 picker.listEl.scrollChildIntoView(itemNode, false);
68936             }
68937         }
68938     },
68939
68940     doTypeAhead: function() {
68941         if (!this.typeAheadTask) {
68942             this.typeAheadTask = Ext.create('Ext.util.DelayedTask', this.onTypeAhead, this);
68943         }
68944         if (this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE) {
68945             this.typeAheadTask.delay(this.typeAheadDelay);
68946         }
68947     },
68948
68949     onTriggerClick: function() {
68950         var me = this;
68951         if (!me.readOnly && !me.disabled) {
68952             if (me.isExpanded) {
68953                 me.collapse();
68954             } else {
68955                 me.onFocus({});
68956                 if (me.triggerAction === 'all') {
68957                     me.doQuery(me.allQuery, true);
68958                 } else {
68959                     me.doQuery(me.getRawValue());
68960                 }
68961             }
68962             me.inputEl.focus();
68963         }
68964     },
68965
68966
68967     
68968     onKeyUp: function(e, t) {
68969         var me = this,
68970             key = e.getKey();
68971
68972         if (!me.readOnly && !me.disabled && me.editable) {
68973             me.lastKey = key;
68974             
68975             
68976
68977             
68978             if (!e.isSpecialKey() || key == e.BACKSPACE || key == e.DELETE) {
68979                 me.doQueryTask.delay(me.queryDelay);
68980             }
68981         }
68982         
68983         if (me.enableKeyEvents) {
68984             me.callParent(arguments);
68985         }
68986     },
68987
68988     initEvents: function() {
68989         var me = this;
68990         me.callParent();
68991
68992         
68993         if (!me.enableKeyEvents) {
68994             me.mon(me.inputEl, 'keyup', me.onKeyUp, me);
68995         }
68996     },
68997
68998     createPicker: function() {
68999         var me = this,
69000             picker,
69001             menuCls = Ext.baseCSSPrefix + 'menu',
69002             opts = Ext.apply({
69003                 selModel: {
69004                     mode: me.multiSelect ? 'SIMPLE' : 'SINGLE'
69005                 },
69006                 floating: true,
69007                 hidden: true,
69008                 ownerCt: me.ownerCt,
69009                 cls: me.el.up('.' + menuCls) ? menuCls : '',
69010                 store: me.store,
69011                 displayField: me.displayField,
69012                 focusOnToFront: false,
69013                 pageSize: me.pageSize
69014             }, me.listConfig, me.defaultListConfig);
69015
69016         picker = me.picker = Ext.create('Ext.view.BoundList', opts);
69017
69018         me.mon(picker, {
69019             itemclick: me.onItemClick,
69020             refresh: me.onListRefresh,
69021             scope: me
69022         });
69023
69024         me.mon(picker.getSelectionModel(), {
69025             selectionChange: me.onListSelectionChange,
69026             scope: me
69027         });
69028
69029         return picker;
69030     },
69031
69032     onListRefresh: function() {
69033         this.alignPicker();
69034         this.syncSelection();
69035     },
69036     
69037     onItemClick: function(picker, record){
69038         
69039         var me = this,
69040             lastSelection = me.lastSelection,
69041             valueField = me.valueField,
69042             selected;
69043         
69044         if (!me.multiSelect && lastSelection) {
69045             selected = lastSelection[0];
69046             if (record.get(valueField) === selected.get(valueField)) {
69047                 me.collapse();
69048             }
69049         }   
69050     },
69051
69052     onListSelectionChange: function(list, selectedRecords) {
69053         var me = this;
69054         
69055         
69056         if (!me.ignoreSelection && me.isExpanded) {
69057             if (!me.multiSelect) {
69058                 Ext.defer(me.collapse, 1, me);
69059             }
69060             me.setValue(selectedRecords, false);
69061             if (selectedRecords.length > 0) {
69062                 me.fireEvent('select', me, selectedRecords);
69063             }
69064             me.inputEl.focus();
69065         }
69066     },
69067
69068     
69069     onExpand: function() {
69070         var me = this,
69071             keyNav = me.listKeyNav,
69072             selectOnTab = me.selectOnTab,
69073             picker = me.getPicker();
69074
69075         
69076         if (keyNav) {
69077             keyNav.enable();
69078         } else {
69079             keyNav = me.listKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
69080                 boundList: picker,
69081                 forceKeyDown: true,
69082                 tab: function(e) {
69083                     if (selectOnTab) {
69084                         this.selectHighlighted(e);
69085                         me.triggerBlur();
69086                     }
69087                     
69088                     return true;
69089                 }
69090             });
69091         }
69092
69093         
69094         if (selectOnTab) {
69095             me.ignoreMonitorTab = true;
69096         }
69097
69098         Ext.defer(keyNav.enable, 1, keyNav); 
69099         me.inputEl.focus();
69100     },
69101
69102     
69103     onCollapse: function() {
69104         var me = this,
69105             keyNav = me.listKeyNav;
69106         if (keyNav) {
69107             keyNav.disable();
69108             me.ignoreMonitorTab = false;
69109         }
69110     },
69111
69112     
69113     select: function(r) {
69114         this.setValue(r, true);
69115     },
69116
69117     
69118     findRecord: function(field, value) {
69119         var ds = this.store,
69120             idx = ds.findExact(field, value);
69121         return idx !== -1 ? ds.getAt(idx) : false;
69122     },
69123     findRecordByValue: function(value) {
69124         return this.findRecord(this.valueField, value);
69125     },
69126     findRecordByDisplay: function(value) {
69127         return this.findRecord(this.displayField, value);
69128     },
69129
69130     
69131     setValue: function(value, doSelect) {
69132         var me = this,
69133             valueNotFoundText = me.valueNotFoundText,
69134             inputEl = me.inputEl,
69135             i, len, record,
69136             models = [],
69137             displayTplData = [],
69138             processedValue = [];
69139
69140         if (me.store.loading) {
69141             
69142             me.value = value;
69143             return me;
69144         }
69145
69146         
69147         value = Ext.Array.from(value);
69148
69149         
69150         for (i = 0, len = value.length; i < len; i++) {
69151             record = value[i];
69152             if (!record || !record.isModel) {
69153                 record = me.findRecordByValue(record);
69154             }
69155             
69156             if (record) {
69157                 models.push(record);
69158                 displayTplData.push(record.data);
69159                 processedValue.push(record.get(me.valueField));
69160             }
69161             
69162             
69163             else {
69164                 
69165                 if (Ext.isDefined(valueNotFoundText)) {
69166                     displayTplData.push(valueNotFoundText);
69167                 }
69168                 processedValue.push(value[i]);
69169             }
69170         }
69171
69172         
69173         me.value = me.multiSelect ? processedValue : processedValue[0];
69174         if (!Ext.isDefined(me.value)) {
69175             me.value = null;
69176         }
69177         me.displayTplData = displayTplData; 
69178         me.lastSelection = me.valueModels = models;
69179
69180         if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
69181             inputEl.removeCls(me.emptyCls);
69182         }
69183
69184         
69185         me.setRawValue(me.getDisplayValue());
69186         me.checkChange();
69187
69188         if (doSelect !== false) {
69189             me.syncSelection();
69190         }
69191         me.applyEmptyText();
69192
69193         return me;
69194     },
69195
69196     
69197     getDisplayValue: function() {
69198         return this.displayTpl.apply(this.displayTplData);
69199     },
69200
69201     getValue: function() {
69202         
69203         
69204         
69205         var me = this,
69206             picker = me.picker,
69207             rawValue = me.getRawValue(), 
69208             value = me.value; 
69209
69210         if (me.getDisplayValue() !== rawValue) {
69211             value = rawValue;
69212             me.value = me.displayTplData = me.valueModels = null;
69213             if (picker) {
69214                 me.ignoreSelection++;
69215                 picker.getSelectionModel().deselectAll();
69216                 me.ignoreSelection--;
69217             }
69218         }
69219
69220         return value;
69221     },
69222
69223     getSubmitValue: function() {
69224         return this.getValue();
69225     },
69226
69227     isEqual: function(v1, v2) {
69228         var fromArray = Ext.Array.from,
69229             i, len;
69230
69231         v1 = fromArray(v1);
69232         v2 = fromArray(v2);
69233         len = v1.length;
69234
69235         if (len !== v2.length) {
69236             return false;
69237         }
69238
69239         for(i = 0; i < len; i++) {
69240             if (v2[i] !== v1[i]) {
69241                 return false;
69242             }
69243         }
69244
69245         return true;
69246     },
69247
69248     
69249     clearValue: function() {
69250         this.setValue([]);
69251     },
69252
69253     
69254     syncSelection: function() {
69255         var me = this,
69256             ExtArray = Ext.Array,
69257             picker = me.picker,
69258             selection, selModel;
69259         if (picker) {
69260             
69261             selection = [];
69262             ExtArray.forEach(me.valueModels || [], function(value) {
69263                 if (value && value.isModel && me.store.indexOf(value) >= 0) {
69264                     selection.push(value);
69265                 }
69266             });
69267
69268             
69269             me.ignoreSelection++;
69270             selModel = picker.getSelectionModel();
69271             selModel.deselectAll();
69272             if (selection.length) {
69273                 selModel.select(selection);
69274             }
69275             me.ignoreSelection--;
69276         }
69277     }
69278 });
69279
69280
69281 Ext.define('Ext.picker.Month', {
69282     extend: 'Ext.Component',
69283     requires: ['Ext.XTemplate', 'Ext.util.ClickRepeater', 'Ext.Date', 'Ext.button.Button'],
69284     alias: 'widget.monthpicker',
69285     alternateClassName: 'Ext.MonthPicker',
69286
69287     renderTpl: [
69288         '<div class="{baseCls}-body">',
69289           '<div class="{baseCls}-months">',
69290               '<tpl for="months">',
69291                   '<div class="{parent.baseCls}-item {parent.baseCls}-month"><a href="#" hidefocus="on">{.}</a></div>',
69292               '</tpl>',
69293           '</div>',
69294           '<div class="{baseCls}-years">',
69295               '<div class="{baseCls}-yearnav">',
69296                   '<button class="{baseCls}-yearnav-prev"></button>',
69297                   '<button class="{baseCls}-yearnav-next"></button>',
69298               '</div>',
69299               '<tpl for="years">',
69300                   '<div class="{parent.baseCls}-item {parent.baseCls}-year"><a href="#" hidefocus="on">{.}</a></div>',
69301               '</tpl>',
69302           '</div>',
69303         '</div>',
69304         '<div class="' + Ext.baseCSSPrefix + 'clear"></div>',
69305         '<tpl if="showButtons">',
69306           '<div class="{baseCls}-buttons"></div>',
69307         '</tpl>'
69308     ],
69309
69310     
69311     okText: 'OK',
69312
69313     
69314     cancelText: 'Cancel',
69315
69316     
69317     baseCls: Ext.baseCSSPrefix + 'monthpicker',
69318
69319     
69320     showButtons: true,
69321
69322     
69323
69324     
69325
69326     width: 175,
69327
69328     height: 195,
69329
69330
69331     
69332     totalYears: 10,
69333     yearOffset: 5, 
69334     monthOffset: 6, 
69335
69336     
69337     initComponent: function(){
69338         var me = this;
69339
69340         me.selectedCls = me.baseCls + '-selected';
69341         me.addEvents(
69342             
69343             'cancelclick',
69344
69345             
69346             'monthclick',
69347
69348             
69349             'monthdblclick',
69350
69351             
69352             'okclick',
69353
69354             
69355             'select',
69356
69357             
69358             'yearclick',
69359
69360             
69361             'yeardblclick'
69362         );
69363
69364         me.setValue(me.value);
69365         me.activeYear = me.getYear(new Date().getFullYear() - 4, -4);
69366         this.callParent();
69367     },
69368
69369     
69370     onRender: function(ct, position){
69371         var me = this,
69372             i = 0,
69373             months = [],
69374             shortName = Ext.Date.getShortMonthName,
69375             monthLen = me.monthOffset;
69376
69377         for (; i < monthLen; ++i) {
69378             months.push(shortName(i), shortName(i + monthLen));
69379         }
69380
69381         Ext.apply(me.renderData, {
69382             months: months,
69383             years: me.getYears(),
69384             showButtons: me.showButtons
69385         });
69386
69387         Ext.apply(me.renderSelectors, {
69388             bodyEl: '.' + me.baseCls + '-body',
69389             prevEl: '.' + me.baseCls + '-yearnav-prev',
69390             nextEl: '.' + me.baseCls + '-yearnav-next',
69391             buttonsEl: '.' + me.baseCls + '-buttons'
69392         });
69393         this.callParent([ct, position]);
69394     },
69395
69396     
69397     afterRender: function(){
69398         var me = this,
69399             body = me.bodyEl,
69400             buttonsEl = me.buttonsEl;
69401
69402         me.callParent();
69403
69404         me.mon(body, 'click', me.onBodyClick, me);
69405         me.mon(body, 'dblclick', me.onBodyClick, me);
69406
69407         
69408         me.years = body.select('.' + me.baseCls + '-year a');
69409         me.months = body.select('.' + me.baseCls + '-month a');
69410
69411         if (me.showButtons) {
69412             me.okBtn = Ext.create('Ext.button.Button', {
69413                 text: me.okText,
69414                 renderTo: buttonsEl,
69415                 handler: me.onOkClick,
69416                 scope: me
69417             });
69418             me.cancelBtn = Ext.create('Ext.button.Button', {
69419                 text: me.cancelText,
69420                 renderTo: buttonsEl,
69421                 handler: me.onCancelClick,
69422                 scope: me
69423             });
69424         }
69425
69426         me.backRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
69427             handler: Ext.Function.bind(me.adjustYear, me, [-me.totalYears])
69428         });
69429
69430         me.prevEl.addClsOnOver(me.baseCls + '-yearnav-prev-over');
69431         me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
69432             handler: Ext.Function.bind(me.adjustYear, me, [me.totalYears])
69433         });
69434         me.nextEl.addClsOnOver(me.baseCls + '-yearnav-next-over');
69435         me.updateBody();
69436     },
69437
69438     
69439     setValue: function(value){
69440         var me = this,
69441             active = me.activeYear,
69442             offset = me.monthOffset,
69443             year,
69444             index;
69445
69446         if (!value) {
69447             me.value = [null, null];
69448         } else if (Ext.isDate(value)) {
69449             me.value = [value.getMonth(), value.getFullYear()];
69450         } else {
69451             me.value = [value[0], value[1]];
69452         }
69453
69454         if (me.rendered) {
69455             year = me.value[1];
69456             if (year !== null) {
69457                 if ((year < active || year > active + me.yearOffset)) {
69458                     me.activeYear = year - me.yearOffset + 1;
69459                 }
69460             }
69461             me.updateBody();
69462         }
69463
69464         return me;
69465     },
69466
69467     
69468     getValue: function(){
69469         return this.value;
69470     },
69471
69472     
69473     hasSelection: function(){
69474         var value = this.value;
69475         return value[0] !== null && value[1] !== null;
69476     },
69477
69478     
69479     getYears: function(){
69480         var me = this,
69481             offset = me.yearOffset,
69482             start = me.activeYear, 
69483             end = start + offset,
69484             i = start,
69485             years = [];
69486
69487         for (; i < end; ++i) {
69488             years.push(i, i + offset);
69489         }
69490
69491         return years;
69492     },
69493
69494     
69495     updateBody: function(){
69496         var me = this,
69497             years = me.years,
69498             months = me.months,
69499             yearNumbers = me.getYears(),
69500             cls = me.selectedCls,
69501             value = me.getYear(null),
69502             month = me.value[0],
69503             monthOffset = me.monthOffset,
69504             year;
69505
69506         if (me.rendered) {
69507             years.removeCls(cls);
69508             months.removeCls(cls);
69509             years.each(function(el, all, index){
69510                 year = yearNumbers[index];
69511                 el.dom.innerHTML = year;
69512                 if (year == value) {
69513                     el.dom.className = cls;
69514                 }
69515             });
69516             if (month !== null) {
69517                 if (month < monthOffset) {
69518                     month = month * 2;
69519                 } else {
69520                     month = (month - monthOffset) * 2 + 1;
69521                 }
69522                 months.item(month).addCls(cls);
69523             }
69524         }
69525     },
69526
69527     
69528     getYear: function(defaultValue, offset) {
69529         var year = this.value[1];
69530         offset = offset || 0;
69531         return year === null ? defaultValue : year + offset;
69532     },
69533
69534     
69535     onBodyClick: function(e, t) {
69536         var me = this,
69537             isDouble = e.type == 'dblclick';
69538
69539         if (e.getTarget('.' + me.baseCls + '-month')) {
69540             e.stopEvent();
69541             me.onMonthClick(t, isDouble);
69542         } else if (e.getTarget('.' + me.baseCls + '-year')) {
69543             e.stopEvent();
69544             me.onYearClick(t, isDouble);
69545         }
69546     },
69547
69548     
69549     adjustYear: function(offset){
69550         if (typeof offset != 'number') {
69551             offset = this.totalYears;
69552         }
69553         this.activeYear += offset;
69554         this.updateBody();
69555     },
69556
69557     
69558     onOkClick: function(){
69559         this.fireEvent('okclick', this, this.value);
69560     },
69561
69562     
69563     onCancelClick: function(){
69564         this.fireEvent('cancelclick', this);
69565     },
69566
69567     
69568     onMonthClick: function(target, isDouble){
69569         var me = this;
69570         me.value[0] = me.resolveOffset(me.months.indexOf(target), me.monthOffset);
69571         me.updateBody();
69572         me.fireEvent('month' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
69573         me.fireEvent('select', me, me.value);
69574     },
69575
69576     
69577     onYearClick: function(target, isDouble){
69578         var me = this;
69579         me.value[1] = me.activeYear + me.resolveOffset(me.years.indexOf(target), me.yearOffset);
69580         me.updateBody();
69581         me.fireEvent('year' + (isDouble ? 'dbl' : '') + 'click', me, me.value);
69582         me.fireEvent('select', me, me.value);
69583
69584     },
69585
69586     
69587     resolveOffset: function(index, offset){
69588         if (index % 2 === 0) {
69589             return (index / 2);
69590         } else {
69591             return offset + Math.floor(index / 2);
69592         }
69593     },
69594
69595     
69596     beforeDestroy: function(){
69597         var me = this;
69598         me.years = me.months = null;
69599         Ext.destroyMembers('backRepeater', 'nextRepeater', 'okBtn', 'cancelBtn');
69600         this.callParent();
69601     }
69602 });
69603
69604
69605 Ext.define('Ext.picker.Date', {
69606     extend: 'Ext.Component',
69607     requires: [
69608         'Ext.XTemplate',
69609         'Ext.button.Button',
69610         'Ext.button.Split',
69611         'Ext.util.ClickRepeater',
69612         'Ext.util.KeyNav',
69613         'Ext.EventObject',
69614         'Ext.fx.Manager',
69615         'Ext.picker.Month'
69616     ],
69617     alias: 'widget.datepicker',
69618     alternateClassName: 'Ext.DatePicker',
69619
69620     renderTpl: [
69621         '<div class="{cls}" id="{id}" role="grid" title="{ariaTitle} {value:this.longDay}">',
69622             '<div role="presentation" class="{baseCls}-header">',
69623                 '<div class="{baseCls}-prev"><a href="#" role="button" title="{prevText}"></a></div>',
69624                 '<div class="{baseCls}-month"></div>',
69625                 '<div class="{baseCls}-next"><a href="#" role="button" title="{nextText}"></a></div>',
69626             '</div>',
69627             '<table class="{baseCls}-inner" cellspacing="0" role="presentation">',
69628                 '<thead role="presentation"><tr role="presentation">',
69629                     '<tpl for="dayNames">',
69630                         '<th role="columnheader" title="{.}"><span>{.:this.firstInitial}</span></th>',
69631                     '</tpl>',
69632                 '</tr></thead>',
69633                 '<tbody role="presentation"><tr role="presentation">',
69634                     '<tpl for="days">',
69635                         '{#:this.isEndOfWeek}',
69636                         '<td role="gridcell" id="{[Ext.id()]}">',
69637                             '<a role="presentation" href="#" hidefocus="on" class="{parent.baseCls}-date" tabIndex="1">',
69638                                 '<em role="presentation"><span role="presentation"></span></em>',
69639                             '</a>',
69640                         '</td>',
69641                     '</tpl>',
69642                 '</tr></tbody>',
69643             '</table>',
69644             '<tpl if="showToday">',
69645                 '<div role="presentation" class="{baseCls}-footer"></div>',
69646             '</tpl>',
69647         '</div>',
69648         {
69649             firstInitial: function(value) {
69650                 return value.substr(0,1);
69651             },
69652             isEndOfWeek: function(value) {
69653                 
69654                 
69655                 value--;
69656                 var end = value % 7 === 0 && value !== 0;
69657                 return end ? '</tr><tr role="row">' : '';
69658             },
69659             longDay: function(value){
69660                 return Ext.Date.format(value, this.longDayFormat);
69661             }
69662         }
69663     ],
69664
69665     ariaTitle: 'Date Picker',
69666     
69667     todayText : 'Today',
69668     
69669     
69670     
69671     todayTip : '{0} (Spacebar)',
69672     
69673     minText : 'This date is before the minimum date',
69674     
69675     maxText : 'This date is after the maximum date',
69676     
69677     
69678     disabledDaysText : 'Disabled',
69679     
69680     disabledDatesText : 'Disabled',
69681     
69682     
69683     
69684     nextText : 'Next Month (Control+Right)',
69685     
69686     prevText : 'Previous Month (Control+Left)',
69687     
69688     monthYearText : 'Choose a month (Control+Up/Down to move years)',
69689     
69690     startDay : 0,
69691     
69692     showToday : true,
69693     
69694     
69695     
69696     
69697     
69698
69699     
69700     disableAnim: true,
69701
69702     
69703     baseCls: Ext.baseCSSPrefix + 'datepicker',
69704
69705     
69706
69707     
69708
69709     
69710     longDayFormat: 'F d, Y',
69711
69712     
69713
69714     
69715     focusOnShow: false,
69716
69717     
69718     
69719     focusOnSelect: true,
69720
69721     width: 178,
69722
69723     
69724     
69725     initHour: 12, 
69726
69727     numDays: 42,
69728
69729     
69730     initComponent : function() {
69731         var me = this,
69732             clearTime = Ext.Date.clearTime;
69733
69734         me.selectedCls = me.baseCls + '-selected';
69735         me.disabledCellCls = me.baseCls + '-disabled';
69736         me.prevCls = me.baseCls + '-prevday';
69737         me.activeCls = me.baseCls + '-active';
69738         me.nextCls = me.baseCls + '-prevday';
69739         me.todayCls = me.baseCls + '-today';
69740         me.dayNames = me.dayNames.slice(me.startDay).concat(me.dayNames.slice(0, me.startDay));
69741         this.callParent();
69742
69743         me.value = me.value ?
69744                  clearTime(me.value, true) : clearTime(new Date());
69745
69746         me.addEvents(
69747             
69748             'select'
69749         );
69750
69751         me.initDisabledDays();
69752     },
69753
69754     
69755     onRender : function(container, position){
69756         
69757
69758         var me = this,
69759             days = new Array(me.numDays),
69760             today = Ext.Date.format(new Date(), me.format);
69761
69762         Ext.applyIf(me, {
69763             renderData: {},
69764             renderSelectors: {}
69765         });
69766
69767         Ext.apply(me.renderData, {
69768             dayNames: me.dayNames,
69769             ariaTitle: me.ariaTitle,
69770             value: me.value,
69771             showToday: me.showToday,
69772             prevText: me.prevText,
69773             nextText: me.nextText,
69774             days: days
69775         });
69776         me.getTpl('renderTpl').longDayFormat = me.longDayFormat;
69777
69778         Ext.apply(me.renderSelectors, {
69779             eventEl: 'table.' + me.baseCls + '-inner',
69780             prevEl: '.' + me.baseCls + '-prev a',
69781             nextEl: '.' + me.baseCls + '-next a',
69782             middleBtnEl: '.' + me.baseCls + '-month',
69783             footerEl: '.' + me.baseCls + '-footer'
69784         });
69785
69786         this.callParent(arguments);
69787         me.el.unselectable();
69788
69789         me.cells = me.eventEl.select('tbody td');
69790         me.textNodes = me.eventEl.query('tbody td span');
69791
69792         me.monthBtn = Ext.create('Ext.button.Split', {
69793             text: '',
69794             tooltip: me.monthYearText,
69795             renderTo: me.middleBtnEl
69796         });
69797         
69798
69799
69800         me.todayBtn = Ext.create('Ext.button.Button', {
69801             renderTo: me.footerEl,
69802             text: Ext.String.format(me.todayText, today),
69803             tooltip: Ext.String.format(me.todayTip, today),
69804             handler: me.selectToday,
69805             scope: me
69806         });
69807     },
69808
69809     
69810     initEvents: function(){
69811         var me = this,
69812             eDate = Ext.Date,
69813             day = eDate.DAY;
69814
69815         this.callParent();
69816
69817         me.prevRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
69818             handler: me.showPrevMonth,
69819             scope: me,
69820             preventDefault: true,
69821             stopDefault: true
69822         });
69823
69824         me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
69825             handler: me.showNextMonth,
69826             scope: me,
69827             preventDefault:true,
69828             stopDefault:true
69829         });
69830
69831         me.keyNav = Ext.create('Ext.util.KeyNav', me.eventEl, Ext.apply({
69832             scope: me,
69833             'left' : function(e){
69834                 if(e.ctrlKey){
69835                     me.showPrevMonth();
69836                 }else{
69837                     me.update(eDate.add(me.activeDate, day, -1));
69838                 }
69839             },
69840
69841             'right' : function(e){
69842                 if(e.ctrlKey){
69843                     me.showNextMonth();
69844                 }else{
69845                     me.update(eDate.add(me.activeDate, day, 1));
69846                 }
69847             },
69848
69849             'up' : function(e){
69850                 if(e.ctrlKey){
69851                     me.showNextYear();
69852                 }else{
69853                     me.update(eDate.add(me.activeDate, day, -7));
69854                 }
69855             },
69856
69857             'down' : function(e){
69858                 if(e.ctrlKey){
69859                     me.showPrevYear();
69860                 }else{
69861                     me.update(eDate.add(me.activeDate, day, 7));
69862                 }
69863             },
69864             'pageUp' : me.showNextMonth,
69865             'pageDown' : me.showPrevMonth,
69866             'enter' : function(e){
69867                 e.stopPropagation();
69868                 return true;
69869             }
69870         }, me.keyNavConfig));
69871
69872         if(me.showToday){
69873             me.todayKeyListener = me.eventEl.addKeyListener(Ext.EventObject.SPACE, me.selectToday,  me);
69874         }
69875         me.mon(me.eventEl, 'mousewheel', me.handleMouseWheel, me);
69876         me.mon(me.eventEl, 'click', me.handleDateClick,  me, {delegate: 'a.' + me.baseCls + '-date'});
69877         me.mon(me.monthBtn, 'click', me.showMonthPicker, me);
69878         me.mon(me.monthBtn, 'arrowclick', me.showMonthPicker, me);
69879         me.update(me.value);
69880     },
69881
69882     
69883     initDisabledDays : function(){
69884         var me = this,
69885             dd = me.disabledDates,
69886             re = '(?:',
69887             len;
69888
69889         if(!me.disabledDatesRE && dd){
69890                 len = dd.length - 1;
69891
69892             Ext.each(dd, function(d, i){
69893                 re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(Ext.Date.dateFormat(d, me.format)) + '$' : dd[i];
69894                 if(i != len){
69895                     re += '|';
69896                 }
69897             }, me);
69898             me.disabledDatesRE = new RegExp(re + ')');
69899         }
69900     },
69901
69902     
69903     setDisabledDates : function(dd){
69904         var me = this;
69905
69906         if(Ext.isArray(dd)){
69907             me.disabledDates = dd;
69908             me.disabledDatesRE = null;
69909         }else{
69910             me.disabledDatesRE = dd;
69911         }
69912         me.initDisabledDays();
69913         me.update(me.value, true);
69914         return me;
69915     },
69916
69917     
69918     setDisabledDays : function(dd){
69919         this.disabledDays = dd;
69920         return this.update(this.value, true);
69921     },
69922
69923     
69924     setMinDate : function(dt){
69925         this.minDate = dt;
69926         return this.update(this.value, true);
69927     },
69928
69929     
69930     setMaxDate : function(dt){
69931         this.maxDate = dt;
69932         return this.update(this.value, true);
69933     },
69934
69935     
69936     setValue : function(value){
69937         this.value = Ext.Date.clearTime(value, true);
69938         return this.update(this.value);
69939     },
69940
69941     
69942     getValue : function(){
69943         return this.value;
69944     },
69945
69946     
69947     focus : function(){
69948         this.update(this.activeDate);
69949     },
69950
69951     
69952     onEnable: function(){
69953         this.callParent();
69954         this.setDisabledStatus(false);
69955         this.update(this.activeDate);
69956
69957     },
69958
69959     
69960     onDisable : function(){
69961         this.callParent();
69962         this.setDisabledStatus(true);
69963     },
69964
69965     
69966     setDisabledStatus : function(disabled){
69967         var me = this;
69968
69969         me.keyNav.setDisabled(disabled);
69970         me.prevRepeater.setDisabled(disabled);
69971         me.nextRepeater.setDisabled(disabled);
69972         if (me.showToday) {
69973             me.todayKeyListener.setDisabled(disabled);
69974             me.todayBtn.setDisabled(disabled);
69975         }
69976     },
69977
69978     
69979     getActive: function(){
69980         return this.activeDate || me.value;
69981     },
69982
69983     
69984     runAnimation: function(isHide){
69985         var options = {
69986                 target: this.monthPicker,
69987                 duration: 200
69988             };
69989
69990         Ext.fx.Manager.run();
69991         if (isHide) {
69992             
69993         } else {
69994             
69995         }
69996         Ext.create('Ext.fx.Anim', options);
69997     },
69998
69999     
70000     hideMonthPicker : function(){
70001         var me = this,
70002             picker = me.monthPicker;
70003
70004         if (picker) {
70005             if (me.disableAnim) {
70006                 picker.hide();
70007             } else {
70008                 this.runAnimation(true);
70009             }
70010         }
70011         return me;
70012     },
70013
70014     
70015     showMonthPicker : function(){
70016
70017         var me = this,
70018             picker,
70019             size,
70020             top,
70021             left;
70022
70023
70024         if (me.rendered && !me.disabled) {
70025             size = me.getSize();
70026             picker = me.createMonthPicker();
70027             picker.show();
70028             picker.setSize(size);
70029             picker.setValue(me.getActive());
70030
70031             if (me.disableAnim) {
70032                 picker.setPosition(-1, -1);
70033             } else {
70034                 me.runAnimation(false);
70035             }
70036         }
70037         return me;
70038     },
70039
70040     
70041     createMonthPicker: function(){
70042         var me = this,
70043             picker = me.monthPicker;
70044
70045         if (!picker) {
70046             me.monthPicker = picker = Ext.create('Ext.picker.Month', {
70047                 renderTo: me.el,
70048                 floating: true,
70049                 shadow: false,
70050                 listeners: {
70051                     scope: me,
70052                     cancelclick: me.onCancelClick,
70053                     okclick: me.onOkClick,
70054                     yeardblclick: me.onOkClick,
70055                     monthdblclick: me.onOkClick
70056                 }
70057             });
70058
70059             me.on('beforehide', me.hideMonthPicker, me);
70060         }
70061         return picker;
70062     },
70063
70064     
70065     onOkClick: function(picker, value){
70066         var me = this,
70067             month = value[0],
70068             year = value[1],
70069             date = new Date(year, month, me.getActive().getDate());
70070
70071         if (date.getMonth() !== month) {
70072             
70073             date = new Date(year, month, 1).getLastDateOfMonth();
70074         }
70075         me.update(date);
70076         me.hideMonthPicker();
70077     },
70078
70079     
70080     onCancelClick: function(){
70081         this.hideMonthPicker();
70082     },
70083
70084     
70085     showPrevMonth : function(e){
70086         return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, -1));
70087     },
70088
70089     
70090     showNextMonth : function(e){
70091         return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, 1));
70092     },
70093
70094     
70095     showPrevYear : function(){
70096         this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, -1));
70097     },
70098
70099     
70100     showNextYear : function(){
70101         this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, 1));
70102     },
70103
70104     
70105     handleMouseWheel : function(e){
70106         e.stopEvent();
70107         if(!this.disabled){
70108             var delta = e.getWheelDelta();
70109             if(delta > 0){
70110                 this.showPrevMonth();
70111             } else if(delta < 0){
70112                 this.showNextMonth();
70113             }
70114         }
70115     },
70116
70117     
70118     handleDateClick : function(e, t){
70119         var me = this,
70120             handler = me.handler;
70121
70122         e.stopEvent();
70123         if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)){
70124             me.cancelFocus = me.focusOnSelect === false;
70125             me.setValue(new Date(t.dateValue));
70126             delete me.cancelFocus;
70127             me.fireEvent('select', me, me.value);
70128             if (handler) {
70129                 handler.call(me.scope || me, me, me.value);
70130             }
70131             
70132             
70133             
70134             
70135             me.onSelect();
70136         }
70137     },
70138
70139     
70140     onSelect: function() {
70141         if (this.hideOnSelect) {
70142              this.hide();
70143          }
70144     },
70145
70146     
70147     selectToday : function(){
70148         var me = this,
70149             btn = me.todayBtn,
70150             handler = me.handler;
70151
70152         if(btn && !btn.disabled){
70153             me.setValue(Ext.Date.clearTime(new Date()));
70154             me.fireEvent('select', me, me.value);
70155             if (handler) {
70156                 handler.call(me.scope || me, me, me.value);
70157             }
70158             me.onSelect();
70159         }
70160         return me;
70161     },
70162
70163     
70164     selectedUpdate: function(date, active){
70165         var me = this,
70166             t = date.getTime(),
70167             cells = me.cells,
70168             cls = me.selectedCls;
70169
70170         cells.removeCls(cls);
70171         cells.each(function(c){
70172             if (c.dom.firstChild.dateValue == t) {
70173                 me.el.dom.setAttribute('aria-activedescendent', c.dom.id);
70174                 c.addCls(cls);
70175                 if(me.isVisible() && !me.cancelFocus){
70176                     Ext.fly(c.dom.firstChild).focus(50);
70177                 }
70178                 return false;
70179             }
70180         }, this);
70181     },
70182
70183     
70184     fullUpdate: function(date, active){
70185         var me = this,
70186             cells = me.cells.elements,
70187             textNodes = me.textNodes,
70188             disabledCls = me.disabledCellCls,
70189             eDate = Ext.Date,
70190             i = 0,
70191             extraDays = 0,
70192             visible = me.isVisible(),
70193             sel = +eDate.clearTime(date, true),
70194             today = +eDate.clearTime(new Date()),
70195             min = me.minDate ? eDate.clearTime(me.minDate, true) : Number.NEGATIVE_INFINITY,
70196             max = me.maxDate ? eDate.clearTime(me.maxDate, true) : Number.POSITIVE_INFINITY,
70197             ddMatch = me.disabledDatesRE,
70198             ddText = me.disabledDatesText,
70199             ddays = me.disabledDays ? me.disabledDays.join('') : false,
70200             ddaysText = me.disabledDaysText,
70201             format = me.format,
70202             days = eDate.getDaysInMonth(date),
70203             firstOfMonth = eDate.getFirstDateOfMonth(date),
70204             startingPos = firstOfMonth.getDay() - me.startDay,
70205             previousMonth = eDate.add(date, eDate.MONTH, -1),
70206             longDayFormat = me.longDayFormat,
70207             prevStart,
70208             current,
70209             disableToday,
70210             tempDate,
70211             setCellClass,
70212             html,
70213             cls,
70214             formatValue,
70215             value;
70216
70217         if (startingPos < 0) {
70218             startingPos += 7;
70219         }
70220
70221         days += startingPos;
70222         prevStart = eDate.getDaysInMonth(previousMonth) - startingPos;
70223         current = new Date(previousMonth.getFullYear(), previousMonth.getMonth(), prevStart, me.initHour);
70224
70225         if (me.showToday) {
70226             tempDate = eDate.clearTime(new Date());
70227             disableToday = (tempDate < min || tempDate > max ||
70228                 (ddMatch && format && ddMatch.test(eDate.dateFormat(tempDate, format))) ||
70229                 (ddays && ddays.indexOf(tempDate.getDay()) != -1));
70230
70231             if (!me.disabled) {
70232                 me.todayBtn.setDisabled(disableToday);
70233                 me.todayKeyListener.setDisabled(disableToday);
70234             }
70235         }
70236
70237         setCellClass = function(cell){
70238             value = +eDate.clearTime(current, true);
70239             cell.title = eDate.format(current, longDayFormat);
70240             
70241             cell.firstChild.dateValue = value;
70242             if(value == today){
70243                 cell.className += ' ' + me.todayCls;
70244                 cell.title = me.todayText;
70245             }
70246             if(value == sel){
70247                 cell.className += ' ' + me.selectedCls;
70248                 me.el.dom.setAttribute('aria-activedescendant', cell.id);
70249                 if (visible && me.floating) {
70250                     Ext.fly(cell.firstChild).focus(50);
70251                 }
70252             }
70253             
70254             if(value < min) {
70255                 cell.className = disabledCls;
70256                 cell.title = me.minText;
70257                 return;
70258             }
70259             if(value > max) {
70260                 cell.className = disabledCls;
70261                 cell.title = me.maxText;
70262                 return;
70263             }
70264             if(ddays){
70265                 if(ddays.indexOf(current.getDay()) != -1){
70266                     cell.title = ddaysText;
70267                     cell.className = disabledCls;
70268                 }
70269             }
70270             if(ddMatch && format){
70271                 formatValue = eDate.dateFormat(current, format);
70272                 if(ddMatch.test(formatValue)){
70273                     cell.title = ddText.replace('%0', formatValue);
70274                     cell.className = disabledCls;
70275                 }
70276             }
70277         };
70278
70279         for(; i < me.numDays; ++i) {
70280             if (i < startingPos) {
70281                 html = (++prevStart);
70282                 cls = me.prevCls;
70283             } else if (i >= days) {
70284                 html = (++extraDays);
70285                 cls = me.nextCls;
70286             } else {
70287                 html = i - startingPos + 1;
70288                 cls = me.activeCls;
70289             }
70290             textNodes[i].innerHTML = html;
70291             cells[i].className = cls;
70292             current.setDate(current.getDate() + 1);
70293             setCellClass(cells[i]);
70294         }
70295
70296         me.monthBtn.setText(me.monthNames[date.getMonth()] + ' ' + date.getFullYear());
70297     },
70298
70299     
70300     update : function(date, forceRefresh){
70301         var me = this,
70302             active = me.activeDate;
70303
70304         if (me.rendered) {
70305             me.activeDate = date;
70306             if(!forceRefresh && active && me.el && active.getMonth() == date.getMonth() && active.getFullYear() == date.getFullYear()){
70307                 me.selectedUpdate(date, active);
70308             } else {
70309                 me.fullUpdate(date, active);
70310             }
70311         }
70312         return me;
70313     },
70314
70315     
70316     beforeDestroy : function() {
70317         var me = this;
70318
70319         if (me.rendered) {
70320             Ext.destroy(
70321                 me.todayKeyListener,
70322                 me.keyNav,
70323                 me.monthPicker,
70324                 me.monthBtn,
70325                 me.nextRepeater,
70326                 me.prevRepeater,
70327                 me.todayBtn
70328             );
70329             delete me.textNodes;
70330             delete me.cells.elements;
70331         }
70332     },
70333
70334     
70335     onShow: function() {
70336         this.callParent(arguments);
70337         if (this.focusOnShow) {
70338             this.focus();
70339         }
70340     }
70341 },
70342
70343
70344 function() {
70345     var proto = this.prototype;
70346
70347     proto.monthNames = Ext.Date.monthNames;
70348
70349     proto.dayNames = Ext.Date.dayNames;
70350
70351     proto.format = Ext.Date.defaultFormat;
70352 });
70353
70354
70355 Ext.define('Ext.form.field.Date', {
70356     extend:'Ext.form.field.Picker',
70357     alias: 'widget.datefield',
70358     requires: ['Ext.picker.Date'],
70359     alternateClassName: ['Ext.form.DateField', 'Ext.form.Date'],
70360
70361     
70362     format : "m/d/Y",
70363     
70364     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",
70365     
70366     disabledDaysText : "Disabled",
70367     
70368     disabledDatesText : "Disabled",
70369     
70370     minText : "The date in this field must be equal to or after {0}",
70371     
70372     maxText : "The date in this field must be equal to or before {0}",
70373     
70374     invalidText : "{0} is not a valid date - it must be in the format {1}",
70375     
70376     triggerCls : Ext.baseCSSPrefix + 'form-date-trigger',
70377     
70378     showToday : true,
70379     
70380     
70381     
70382     
70383     
70384     
70385
70386     
70387     
70388     initTime: '12', 
70389
70390     initTimeFormat: 'H',
70391
70392     matchFieldWidth: false,
70393     
70394     startDay: 0,
70395     
70396     initComponent : function(){
70397         var me = this,
70398             isString = Ext.isString,
70399             min, max;
70400
70401         min = me.minValue;
70402         max = me.maxValue;
70403         if(isString(min)){
70404             me.minValue = me.parseDate(min);
70405         }
70406         if(isString(max)){
70407             me.maxValue = me.parseDate(max);
70408         }
70409         me.disabledDatesRE = null;
70410         me.initDisabledDays();
70411
70412         me.callParent();
70413     },
70414
70415     initValue: function() {
70416         var me = this,
70417             value = me.value;
70418
70419         
70420         if (Ext.isString(value)) {
70421             me.value = me.rawToValue(value);
70422         }
70423
70424         me.callParent();
70425     },
70426
70427     
70428     initDisabledDays : function(){
70429         if(this.disabledDates){
70430             var dd = this.disabledDates,
70431                 len = dd.length - 1,
70432                 re = "(?:";
70433
70434             Ext.each(dd, function(d, i){
70435                 re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(d.dateFormat(this.format)) + '$' : dd[i];
70436                 if (i !== len) {
70437                     re += '|';
70438                 }
70439             }, this);
70440             this.disabledDatesRE = new RegExp(re + ')');
70441         }
70442     },
70443
70444     
70445     setDisabledDates : function(dd){
70446         var me = this,
70447             picker = me.picker;
70448             
70449         me.disabledDates = dd;
70450         me.initDisabledDays();
70451         if (picker) {
70452             picker.setDisabledDates(me.disabledDatesRE);
70453         }
70454     },
70455
70456     
70457     setDisabledDays : function(dd){
70458         var picker = this.picker;
70459             
70460         this.disabledDays = dd;
70461         if (picker) {
70462             picker.setDisabledDays(dd);
70463         }
70464     },
70465
70466     
70467     setMinValue : function(dt){
70468         var me = this,
70469             picker = me.picker,
70470             minValue = (Ext.isString(dt) ? me.parseDate(dt) : dt);
70471             
70472         me.minValue = minValue;
70473         if (picker) {
70474             picker.minText = Ext.String.format(me.minText, me.formatDate(me.minValue));
70475             picker.setMinDate(minValue);
70476         }
70477     },
70478
70479     
70480     setMaxValue : function(dt){
70481         var me = this,
70482             picker = me.picker,
70483             maxValue = (Ext.isString(dt) ? me.parseDate(dt) : dt);
70484             
70485         me.maxValue = maxValue;
70486         if (picker) {
70487             picker.maxText = Ext.String.format(me.maxText, me.formatDate(me.maxValue));
70488             picker.setMaxDate(maxValue);
70489         }
70490     },
70491
70492     
70493     getErrors: function(value) {
70494         var me = this,
70495             format = Ext.String.format,
70496             clearTime = Ext.Date.clearTime,
70497             errors = me.callParent(arguments),
70498             disabledDays = me.disabledDays,
70499             disabledDatesRE = me.disabledDatesRE,
70500             minValue = me.minValue,
70501             maxValue = me.maxValue,
70502             len = disabledDays ? disabledDays.length : 0,
70503             i = 0,
70504             svalue,
70505             fvalue,
70506             day,
70507             time;
70508
70509         value = me.formatDate(value || me.processRawValue(me.getRawValue()));
70510
70511         if (value === null || value.length < 1) { 
70512              return errors;
70513         }
70514
70515         svalue = value;
70516         value = me.parseDate(value);
70517         if (!value) {
70518             errors.push(format(me.invalidText, svalue, me.format));
70519             return errors;
70520         }
70521
70522         time = value.getTime();
70523         if (minValue && time < clearTime(minValue).getTime()) {
70524             errors.push(format(me.minText, me.formatDate(minValue)));
70525         }
70526
70527         if (maxValue && time > clearTime(maxValue).getTime()) {
70528             errors.push(format(me.maxText, me.formatDate(maxValue)));
70529         }
70530
70531         if (disabledDays) {
70532             day = value.getDay();
70533
70534             for(; i < len; i++) {
70535                 if (day === disabledDays[i]) {
70536                     errors.push(me.disabledDaysText);
70537                     break;
70538                 }
70539             }
70540         }
70541
70542         fvalue = me.formatDate(value);
70543         if (disabledDatesRE && disabledDatesRE.test(fvalue)) {
70544             errors.push(format(me.disabledDatesText, fvalue));
70545         }
70546
70547         return errors;
70548     },
70549
70550     rawToValue: function(rawValue) {
70551         return this.parseDate(rawValue) || rawValue || null;
70552     },
70553
70554     valueToRaw: function(value) {
70555         return this.formatDate(this.parseDate(value));
70556     },
70557
70558     
70559
70560     
70561     safeParse : function(value, format) {
70562         var me = this,
70563             utilDate = Ext.Date,
70564             parsedDate,
70565             result = null;
70566             
70567         if (utilDate.formatContainsHourInfo(format)) {
70568             
70569             result = utilDate.parse(value, format);
70570         } else {
70571             
70572             parsedDate = utilDate.parse(value + ' ' + me.initTime, format + ' ' + me.initTimeFormat);
70573             if (parsedDate) {
70574                 result = utilDate.clearTime(parsedDate);
70575             }
70576         }
70577         return result;
70578     },
70579     
70580     
70581     getSubmitValue: function() {
70582         var me = this,
70583             format = me.submitFormat || me.format,
70584             value = me.getValue();
70585             
70586         return value ? Ext.Date.format(value, format) : null;
70587     },
70588
70589     
70590     parseDate : function(value) {
70591         if(!value || Ext.isDate(value)){
70592             return value;
70593         }
70594
70595         var me = this,
70596             val = me.safeParse(value, me.format),
70597             altFormats = me.altFormats,
70598             altFormatsArray = me.altFormatsArray,
70599             i = 0,
70600             len;
70601
70602         if (!val && altFormats) {
70603             altFormatsArray = altFormatsArray || altFormats.split('|');
70604             len = altFormatsArray.length;
70605             for (; i < len && !val; ++i) {
70606                 val = me.safeParse(value, altFormatsArray[i]);
70607             }
70608         }
70609         return val;
70610     },
70611
70612     
70613     formatDate : function(date){
70614         return Ext.isDate(date) ? Ext.Date.dateFormat(date, this.format) : date;
70615     },
70616
70617     createPicker: function() {
70618         var me = this,
70619             format = Ext.String.format;
70620
70621         return Ext.create('Ext.picker.Date', {
70622             ownerCt: me.ownerCt,
70623             renderTo: document.body,
70624             floating: true,
70625             hidden: true,
70626             focusOnShow: true,
70627             minDate: me.minValue,
70628             maxDate: me.maxValue,
70629             disabledDatesRE: me.disabledDatesRE,
70630             disabledDatesText: me.disabledDatesText,
70631             disabledDays: me.disabledDays,
70632             disabledDaysText: me.disabledDaysText,
70633             format: me.format,
70634             showToday: me.showToday,
70635             startDay: me.startDay,
70636             minText: format(me.minText, me.formatDate(me.minValue)),
70637             maxText: format(me.maxText, me.formatDate(me.maxValue)),
70638             listeners: {
70639                 scope: me,
70640                 select: me.onSelect
70641             },
70642             keyNavConfig: {
70643                 esc: function() {
70644                     me.collapse();
70645                 }
70646             }
70647         });
70648     },
70649
70650     onSelect: function(m, d) {
70651         var me = this;
70652         
70653         me.setValue(d);
70654         me.fireEvent('select', me, d);
70655         me.collapse();
70656     },
70657
70658     
70659     onExpand: function() {
70660         var me = this,
70661             value = me.getValue();
70662         me.picker.setValue(Ext.isDate(value) ? value : new Date());
70663     },
70664
70665     
70666     onCollapse: function() {
70667         this.focus(false, 60);
70668     },
70669
70670     
70671     beforeBlur : function(){
70672         var me = this,
70673             v = me.parseDate(me.getRawValue()),
70674             focusTask = me.focusTask;
70675         
70676         if (focusTask) {
70677             focusTask.cancel();
70678         }
70679         
70680         if (v) {
70681             me.setValue(v);
70682         }
70683     }
70684
70685     
70686     
70687     
70688     
70689 });
70690
70691
70692 Ext.define('Ext.form.field.Display', {
70693     extend:'Ext.form.field.Base',
70694     alias: 'widget.displayfield',
70695     requires: ['Ext.util.Format', 'Ext.XTemplate'],
70696     alternateClassName: ['Ext.form.DisplayField', 'Ext.form.Display'],
70697     fieldSubTpl: [
70698         '<div id="{id}" class="{fieldCls}"></div>',
70699         {
70700             compiled: true,
70701             disableFormats: true
70702         }
70703     ],
70704
70705     
70706     fieldCls: Ext.baseCSSPrefix + 'form-display-field',
70707
70708     
70709     htmlEncode: false,
70710
70711     validateOnChange: false,
70712
70713     initEvents: Ext.emptyFn,
70714
70715     submitValue: false,
70716
70717     isValid: function() {
70718         return true;
70719     },
70720
70721     validate: function() {
70722         return true;
70723     },
70724
70725     getRawValue: function() {
70726         return this.rawValue;
70727     },
70728
70729     setRawValue: function(value) {
70730         var me = this;
70731         value = Ext.value(value, '');
70732         me.rawValue = value;
70733         if (me.rendered) {
70734             me.inputEl.dom.innerHTML = me.htmlEncode ? Ext.util.Format.htmlEncode(value) : value;
70735         }
70736         return value;
70737     },
70738
70739     
70740     getContentTarget: function() {
70741         return this.inputEl;
70742     }
70743
70744     
70745     
70746     
70747     
70748     
70749     
70750 });
70751
70752
70753 Ext.define("Ext.form.field.File", {
70754     extend: 'Ext.form.field.Text',
70755     alias: ['widget.filefield', 'widget.fileuploadfield'],
70756     alternateClassName: ['Ext.form.FileUploadField', 'Ext.ux.form.FileUploadField', 'Ext.form.File'],
70757     uses: ['Ext.button.Button', 'Ext.layout.component.field.File'],
70758
70759     
70760     buttonText: 'Browse...',
70761
70762     
70763     buttonOnly: false,
70764
70765     
70766     buttonMargin: 3,
70767
70768     
70769
70770     
70771
70772     
70773
70774     
70775
70776     
70777     fieldBodyCls: Ext.baseCSSPrefix + 'form-file-wrap',
70778
70779
70780     
70781     readOnly: true,
70782     componentLayout: 'filefield',
70783
70784     
70785     onRender: function() {
70786         var me = this,
70787             inputEl;
70788
70789         me.callParent(arguments);
70790
70791         me.createButton();
70792         me.createFileInput();
70793         
70794         
70795         
70796         if (me.disabled) {
70797             me.disableItems();
70798         }
70799
70800         inputEl = me.inputEl;
70801         inputEl.dom.removeAttribute('name'); 
70802         if (me.buttonOnly) {
70803             inputEl.setDisplayed(false);
70804         }
70805     },
70806
70807     
70808     createButton: function() {
70809         var me = this;
70810         me.button = Ext.widget('button', Ext.apply({
70811             renderTo: me.bodyEl,
70812             text: me.buttonText,
70813             cls: Ext.baseCSSPrefix + 'form-file-btn',
70814             preventDefault: false,
70815             style: me.buttonOnly ? '' : 'margin-left:' + me.buttonMargin + 'px'
70816         }, me.buttonConfig));
70817     },
70818
70819     
70820     createFileInput : function() {
70821         var me = this;
70822         me.fileInputEl = me.button.el.createChild({
70823             name: me.getName(),
70824             cls: Ext.baseCSSPrefix + 'form-file-input',
70825             tag: 'input',
70826             type: 'file',
70827             size: 1
70828         }).on('change', me.onFileChange, me);
70829     },
70830
70831     
70832     onFileChange: function() {
70833         this.lastValue = null; 
70834         Ext.form.field.File.superclass.setValue.call(this, this.fileInputEl.dom.value);
70835     },
70836
70837     
70838     setValue: Ext.emptyFn,
70839
70840     reset : function(){
70841         this.fileInputEl.remove();
70842         this.createFileInput();
70843         this.callParent();
70844     },
70845
70846     onDisable: function(){
70847         this.callParent();
70848         this.disableItems();
70849     },
70850     
70851     disableItems: function(){
70852         var file = this.fileInputEl,
70853             button = this.button;
70854              
70855         if (file) {
70856             file.dom.disabled = true;
70857         }
70858         if (button) {
70859             button.disable();
70860         }    
70861     },
70862
70863     onEnable: function(){
70864         var me = this;
70865         me.callParent();
70866         me.fileInputEl.dom.disabled = false;
70867         me.button.enable();
70868     },
70869
70870     isFileUpload: function() {
70871         return true;
70872     },
70873
70874     extractFileInput: function() {
70875         var fileInput = this.fileInputEl.dom;
70876         this.reset();
70877         return fileInput;
70878     },
70879
70880     onDestroy: function(){
70881         Ext.destroyMembers(this, 'fileInputEl', 'button');
70882         this.callParent();
70883     }
70884
70885
70886 });
70887
70888
70889 Ext.define('Ext.form.field.Hidden', {
70890     extend:'Ext.form.field.Base',
70891     alias: ['widget.hiddenfield', 'widget.hidden'],
70892     alternateClassName: 'Ext.form.Hidden',
70893
70894     
70895     inputType : 'hidden',
70896     hideLabel: true,
70897     
70898     initComponent: function(){
70899         this.formItemCls += '-hidden';
70900         this.callParent();    
70901     },
70902
70903     
70904     initEvents: Ext.emptyFn,
70905     setSize : Ext.emptyFn,
70906     setWidth : Ext.emptyFn,
70907     setHeight : Ext.emptyFn,
70908     setPosition : Ext.emptyFn,
70909     setPagePosition : Ext.emptyFn,
70910     markInvalid : Ext.emptyFn,
70911     clearInvalid : Ext.emptyFn
70912 });
70913
70914
70915 Ext.define('Ext.picker.Color', {
70916     extend: 'Ext.Component',
70917     requires: 'Ext.XTemplate',
70918     alias: 'widget.colorpicker',
70919     alternateClassName: 'Ext.ColorPalette',
70920     
70921     
70922     componentCls : Ext.baseCSSPrefix + 'color-picker',
70923     
70924     
70925     selectedCls: Ext.baseCSSPrefix + 'color-picker-selected',
70926     
70927     
70928     value : null,
70929     
70930     
70931     clickEvent :'click',
70932
70933     
70934     allowReselect : false,
70935
70936     
70937     colors : [
70938         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
70939         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
70940         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
70941         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
70942         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
70943     ],
70944
70945     
70946     
70947     
70948     colorRe: /(?:^|\s)color-(.{6})(?:\s|$)/,
70949     
70950     constructor: function() {
70951         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>');
70952         this.callParent(arguments);
70953     },
70954     
70955     
70956     initComponent : function(){
70957         var me = this;
70958         
70959         this.callParent(arguments);
70960         me.addEvents(
70961             
70962             'select'
70963         );
70964
70965         if (me.handler) {
70966             me.on('select', me.handler, me.scope, true);
70967         }
70968     },
70969
70970
70971     
70972     onRender : function(container, position){
70973         var me = this,
70974             clickEvent = me.clickEvent;
70975             
70976         Ext.apply(me.renderData, {
70977             itemCls: me.itemCls,
70978             colors: me.colors    
70979         });
70980         this.callParent(arguments);
70981
70982         me.mon(me.el, clickEvent, me.handleClick, me, {delegate: 'a'});
70983         
70984         if(clickEvent != 'click'){
70985             me.mon(me.el, 'click', Ext.emptyFn, me, {delegate: 'a', stopEvent: true});
70986         }
70987     },
70988
70989     
70990     afterRender : function(){
70991         var me = this,
70992             value;
70993             
70994         this.callParent(arguments);
70995         if (me.value) {
70996             value = me.value;
70997             me.value = null;
70998             me.select(value, true);
70999         }
71000     },
71001
71002     
71003     handleClick : function(event, target){
71004         var me = this,
71005             color;
71006             
71007         event.stopEvent();
71008         if (!me.disabled) {
71009             color = target.className.match(me.colorRe)[1];
71010             me.select(color.toUpperCase());
71011         }
71012     },
71013
71014     
71015     select : function(color, suppressEvent){
71016         
71017         var me = this,
71018             selectedCls = me.selectedCls,
71019             value = me.value,
71020             el;
71021             
71022         color = color.replace('#', '');
71023         if (!me.rendered) {
71024             me.value = color;
71025             return;
71026         }
71027         
71028         
71029         if (color != value || me.allowReselect) {
71030             el = me.el;
71031
71032             if (me.value) {
71033                 el.down('a.color-' + value).removeCls(selectedCls);
71034             }
71035             el.down('a.color-' + color).addCls(selectedCls);
71036             me.value = color;
71037             if (suppressEvent !== true) {
71038                 me.fireEvent('select', me, color);
71039             }
71040         }
71041     },
71042     
71043     
71044     getValue: function(){
71045         return this.value || null;
71046     }
71047 });
71048
71049
71050
71051 Ext.define('Ext.layout.component.field.HtmlEditor', {
71052     extend: 'Ext.layout.component.field.Field',
71053     alias: ['layout.htmleditor'],
71054
71055     type: 'htmleditor',
71056
71057     sizeBodyContents: function(width, height) {
71058         var me = this,
71059             owner = me.owner,
71060             bodyEl = owner.bodyEl,
71061             toolbar = owner.getToolbar(),
71062             textarea = owner.textareaEl,
71063             iframe = owner.iframeEl,
71064             editorHeight;
71065
71066         if (Ext.isNumber(width)) {
71067             width -= bodyEl.getFrameWidth('lr');
71068         }
71069         toolbar.setWidth(width);
71070         textarea.setWidth(width);
71071         iframe.setWidth(width);
71072
71073         
71074         if (Ext.isNumber(height)) {
71075             editorHeight = height - toolbar.getHeight() - bodyEl.getFrameWidth('tb');
71076             textarea.setHeight(editorHeight);
71077             iframe.setHeight(editorHeight);
71078         }
71079     }
71080 });
71081
71082 Ext.define('Ext.form.field.HtmlEditor', {
71083     extend:'Ext.Component',
71084     mixins: {
71085         labelable: 'Ext.form.Labelable',
71086         field: 'Ext.form.field.Field'
71087     },
71088     alias: 'widget.htmleditor',
71089     alternateClassName: 'Ext.form.HtmlEditor',
71090     requires: [
71091         'Ext.tip.QuickTipManager',
71092         'Ext.picker.Color',
71093         'Ext.toolbar.Item',
71094         'Ext.toolbar.Toolbar',
71095         'Ext.util.Format',
71096         'Ext.layout.component.field.HtmlEditor'
71097     ],
71098
71099     fieldSubTpl: [
71100         '<div class="{toolbarWrapCls}"></div>',
71101         '<textarea id="{id}" name="{name}" tabIndex="-1" class="{textareaCls}" ',
71102             'style="{size}" autocomplete="off"></textarea>',
71103         '<iframe name="{iframeName}" frameBorder="0" style="overflow:auto;{size}" src="{iframeSrc}"></iframe>',
71104         {
71105             compiled: true,
71106             disableFormats: true
71107         }
71108     ],
71109
71110     
71111     enableFormat : true,
71112     
71113     enableFontSize : true,
71114     
71115     enableColors : true,
71116     
71117     enableAlignments : true,
71118     
71119     enableLists : true,
71120     
71121     enableSourceEdit : true,
71122     
71123     enableLinks : true,
71124     
71125     enableFont : true,
71126     
71127     createLinkText : 'Please enter the URL for the link:',
71128     
71129     defaultLinkValue : 'http:/'+'/',
71130     
71131     fontFamilies : [
71132         'Arial',
71133         'Courier New',
71134         'Tahoma',
71135         'Times New Roman',
71136         'Verdana'
71137     ],
71138     defaultFont: 'tahoma',
71139     
71140     defaultValue: (Ext.isOpera || Ext.isIE6) ? '&#160;' : '&#8203;',
71141
71142     fieldBodyCls: Ext.baseCSSPrefix + 'html-editor-wrap',
71143
71144     componentLayout: 'htmleditor',
71145
71146     
71147     initialized : false,
71148     activated : false,
71149     sourceEditMode : false,
71150     iframePad:3,
71151     hideMode:'offsets',
71152
71153     maskOnDisable: true,
71154     
71155     
71156     initComponent : function(){
71157         var me = this;
71158
71159         me.addEvents(
71160             
71161             'initialize',
71162             
71163             'activate',
71164              
71165             'beforesync',
71166              
71167             'beforepush',
71168              
71169             'sync',
71170              
71171             'push',
71172              
71173             'editmodechange'
71174         );
71175
71176         me.callParent(arguments);
71177
71178         
71179         me.initLabelable();
71180         me.initField();
71181     },
71182
71183     
71184     createToolbar : function(editor){
71185         var me = this,
71186             items = [],
71187             tipsEnabled = Ext.tip.QuickTipManager && Ext.tip.QuickTipManager.isEnabled(),
71188             baseCSSPrefix = Ext.baseCSSPrefix,
71189             fontSelectItem, toolbar, undef;
71190
71191         function btn(id, toggle, handler){
71192             return {
71193                 itemId : id,
71194                 cls : baseCSSPrefix + 'btn-icon',
71195                 iconCls: baseCSSPrefix + 'edit-'+id,
71196                 enableToggle:toggle !== false,
71197                 scope: editor,
71198                 handler:handler||editor.relayBtnCmd,
71199                 clickEvent:'mousedown',
71200                 tooltip: tipsEnabled ? editor.buttonTips[id] || undef : undef,
71201                 overflowText: editor.buttonTips[id].title || undef,
71202                 tabIndex:-1
71203             };
71204         }
71205
71206
71207         if (me.enableFont && !Ext.isSafari2) {
71208             fontSelectItem = Ext.widget('component', {
71209                 renderTpl: [
71210                     '<select class="{cls}">',
71211                         '<tpl for="fonts">',
71212                             '<option value="{[values.toLowerCase()]}" style="font-family:{.}"<tpl if="values.toLowerCase()==parent.defaultFont"> selected</tpl>>{.}</option>',
71213                         '</tpl>',
71214                     '</select>'
71215                 ],
71216                 renderData: {
71217                     cls: baseCSSPrefix + 'font-select',
71218                     fonts: me.fontFamilies,
71219                     defaultFont: me.defaultFont
71220                 },
71221                 renderSelectors: {
71222                     selectEl: 'select'
71223                 },
71224                 onDisable: function() {
71225                     var selectEl = this.selectEl;
71226                     if (selectEl) {
71227                         selectEl.dom.disabled = true;
71228                     }
71229                     Ext.Component.superclass.onDisable.apply(this, arguments);
71230                 },
71231                 onEnable: function() {
71232                     var selectEl = this.selectEl;
71233                     if (selectEl) {
71234                         selectEl.dom.disabled = false;
71235                     }
71236                     Ext.Component.superclass.onEnable.apply(this, arguments);
71237                 }
71238             });
71239
71240             items.push(
71241                 fontSelectItem,
71242                 '-'
71243             );
71244         }
71245
71246         if (me.enableFormat) {
71247             items.push(
71248                 btn('bold'),
71249                 btn('italic'),
71250                 btn('underline')
71251             );
71252         }
71253
71254         if (me.enableFontSize) {
71255             items.push(
71256                 '-',
71257                 btn('increasefontsize', false, me.adjustFont),
71258                 btn('decreasefontsize', false, me.adjustFont)
71259             );
71260         }
71261
71262         if (me.enableColors) {
71263             items.push(
71264                 '-', {
71265                     itemId: 'forecolor',
71266                     cls: baseCSSPrefix + 'btn-icon',
71267                     iconCls: baseCSSPrefix + 'edit-forecolor',
71268                     overflowText: editor.buttonTips.forecolor.title,
71269                     tooltip: tipsEnabled ? editor.buttonTips.forecolor || undef : undef,
71270                     tabIndex:-1,
71271                     menu : Ext.widget('menu', {
71272                         plain: true,
71273                         items: [{
71274                             xtype: 'colorpicker',
71275                             allowReselect: true,
71276                             focus: Ext.emptyFn,
71277                             value: '000000',
71278                             plain: true,
71279                             clickEvent: 'mousedown',
71280                             handler: function(cp, color) {
71281                                 me.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
71282                                 me.deferFocus();
71283                                 this.up('menu').hide();
71284                             }
71285                         }]
71286                     })
71287                 }, {
71288                     itemId: 'backcolor',
71289                     cls: baseCSSPrefix + 'btn-icon',
71290                     iconCls: baseCSSPrefix + 'edit-backcolor',
71291                     overflowText: editor.buttonTips.backcolor.title,
71292                     tooltip: tipsEnabled ? editor.buttonTips.backcolor || undef : undef,
71293                     tabIndex:-1,
71294                     menu : Ext.widget('menu', {
71295                         plain: true,
71296                         items: [{
71297                             xtype: 'colorpicker',
71298                             focus: Ext.emptyFn,
71299                             value: 'FFFFFF',
71300                             plain: true,
71301                             allowReselect: true,
71302                             clickEvent: 'mousedown',
71303                             handler: function(cp, color) {
71304                                 if (Ext.isGecko) {
71305                                     me.execCmd('useCSS', false);
71306                                     me.execCmd('hilitecolor', color);
71307                                     me.execCmd('useCSS', true);
71308                                     me.deferFocus();
71309                                 } else {
71310                                     me.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
71311                                     me.deferFocus();
71312                                 }
71313                                 this.up('menu').hide();
71314                             }
71315                         }]
71316                     })
71317                 }
71318             );
71319         }
71320
71321         if (me.enableAlignments) {
71322             items.push(
71323                 '-',
71324                 btn('justifyleft'),
71325                 btn('justifycenter'),
71326                 btn('justifyright')
71327             );
71328         }
71329
71330         if (!Ext.isSafari2) {
71331             if (me.enableLinks) {
71332                 items.push(
71333                     '-',
71334                     btn('createlink', false, me.createLink)
71335                 );
71336             }
71337
71338             if (me.enableLists) {
71339                 items.push(
71340                     '-',
71341                     btn('insertorderedlist'),
71342                     btn('insertunorderedlist')
71343                 );
71344             }
71345             if (me.enableSourceEdit) {
71346                 items.push(
71347                     '-',
71348                     btn('sourceedit', true, function(btn){
71349                         me.toggleSourceEdit(!me.sourceEditMode);
71350                     })
71351                 );
71352             }
71353         }
71354
71355         
71356         toolbar = Ext.widget('toolbar', {
71357             renderTo: me.toolbarWrap,
71358             enableOverflow: true,
71359             items: items
71360         });
71361
71362         if (fontSelectItem) {
71363             me.fontSelect = fontSelectItem.selectEl;
71364
71365             me.mon(me.fontSelect, 'change', function(){
71366                 me.relayCmd('fontname', me.fontSelect.dom.value);
71367                 me.deferFocus();
71368             });
71369         }
71370
71371         
71372         me.mon(toolbar.el, 'click', function(e){
71373             e.preventDefault();
71374         });
71375
71376         me.toolbar = toolbar;
71377     },
71378
71379     onDisable: function() {
71380         this.bodyEl.mask();
71381         this.callParent(arguments);
71382     },
71383
71384     onEnable: function() {
71385         this.bodyEl.unmask();
71386         this.callParent(arguments);
71387     },
71388
71389     
71390     setReadOnly: function(readOnly) {
71391         var me = this,
71392             textareaEl = me.textareaEl,
71393             iframeEl = me.iframeEl,
71394             body;
71395
71396         me.readOnly = readOnly;
71397
71398         if (textareaEl) {
71399             textareaEl.dom.readOnly = readOnly;
71400         }
71401
71402         if (me.initialized) {
71403             body = me.getEditorBody();
71404             if (Ext.isIE) {
71405                 
71406                 iframeEl.setDisplayed(false);
71407                 body.contentEditable = !readOnly;
71408                 iframeEl.setDisplayed(true);
71409             } else {
71410                 me.setDesignMode(!readOnly);
71411             }
71412             if (body) {
71413                 body.style.cursor = readOnly ? 'default' : 'text';
71414             }
71415             me.disableItems(readOnly);
71416         }
71417     },
71418
71419     
71420     getDocMarkup: function() {
71421         var me = this,
71422             h = me.iframeEl.getHeight() - me.iframePad * 2;
71423         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);
71424     },
71425
71426     
71427     getEditorBody: function() {
71428         var doc = this.getDoc();
71429         return doc.body || doc.documentElement;
71430     },
71431
71432     
71433     getDoc: function() {
71434         return (!Ext.isIE && this.iframeEl.dom.contentDocument) || this.getWin().document;
71435     },
71436
71437     
71438     getWin: function() {
71439         return Ext.isIE ? this.iframeEl.dom.contentWindow : window.frames[this.iframeEl.dom.name];
71440     },
71441
71442     
71443     onRender: function() {
71444         var me = this,
71445             renderSelectors = me.renderSelectors;
71446
71447         Ext.applyIf(renderSelectors, me.getLabelableSelectors());
71448
71449         Ext.applyIf(renderSelectors, {
71450             toolbarWrap: 'div.' + Ext.baseCSSPrefix + 'html-editor-tb',
71451             iframeEl: 'iframe',
71452             textareaEl: 'textarea'
71453         });
71454
71455         me.callParent(arguments);
71456
71457         me.textareaEl.dom.value = me.value || '';
71458
71459         
71460         me.monitorTask = Ext.TaskManager.start({
71461             run: me.checkDesignMode,
71462             scope: me,
71463             interval:100
71464         });
71465
71466         me.createToolbar(me);
71467         me.disableItems(true);
71468     },
71469
71470     initRenderTpl: function() {
71471         var me = this;
71472         if (!me.hasOwnProperty('renderTpl')) {
71473             me.renderTpl = me.getTpl('labelableRenderTpl');
71474         }
71475         return me.callParent();
71476     },
71477
71478     initRenderData: function() {
71479         return Ext.applyIf(this.callParent(), this.getLabelableRenderData());
71480     },
71481
71482     getSubTplData: function() {
71483         var cssPrefix = Ext.baseCSSPrefix;
71484         return {
71485             toolbarWrapCls: cssPrefix + 'html-editor-tb',
71486             textareaCls: cssPrefix + 'hidden',
71487             iframeName: Ext.id(),
71488             iframeSrc: Ext.SSL_SECURE_URL,
71489             size: 'height:100px;'
71490         };
71491     },
71492
71493     getSubTplMarkup: function() {
71494         return this.getTpl('fieldSubTpl').apply(this.getSubTplData());
71495     },
71496
71497     getBodyNaturalWidth: function() {
71498         return 565;
71499     },
71500
71501     initFrameDoc: function() {
71502         var me = this,
71503             doc, task;
71504
71505         Ext.TaskManager.stop(me.monitorTask);
71506
71507         doc = me.getDoc();
71508         me.win = me.getWin();
71509
71510         doc.open();
71511         doc.write(me.getDocMarkup());
71512         doc.close();
71513
71514         task = { 
71515             run: function() {
71516                 var doc = me.getDoc();
71517                 if (doc.body || doc.readyState === 'complete') {
71518                     Ext.TaskManager.stop(task);
71519                     me.setDesignMode(true);
71520                     Ext.defer(me.initEditor, 10, me);
71521                 }
71522             },
71523             interval : 10,
71524             duration:10000,
71525             scope: me
71526         };
71527         Ext.TaskManager.start(task);
71528     },
71529
71530     checkDesignMode: function() {
71531         var me = this,
71532             doc = me.getDoc();
71533         if (doc && (!doc.editorInitialized || me.getDesignMode() !== 'on')) {
71534             me.initFrameDoc();
71535         }
71536     },
71537
71538     
71539     setDesignMode: function(mode) {
71540         var me = this,
71541             doc = me.getDoc();
71542         if (doc) {
71543             if (me.readOnly) {
71544                 mode = false;
71545             }
71546             doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off';
71547         }
71548     },
71549
71550     
71551     getDesignMode: function() {
71552         var doc = this.getDoc();
71553         return !doc ? '' : String(doc.designMode).toLowerCase();
71554     },
71555
71556     disableItems: function(disabled) {
71557         this.getToolbar().items.each(function(item){
71558             if(item.getItemId() !== 'sourceedit'){
71559                 item.setDisabled(disabled);
71560             }
71561         });
71562     },
71563
71564     
71565     toggleSourceEdit: function(sourceEditMode) {
71566         var me = this,
71567             iframe = me.iframeEl,
71568             textarea = me.textareaEl,
71569             hiddenCls = Ext.baseCSSPrefix + 'hidden',
71570             btn = me.getToolbar().getComponent('sourceedit');
71571
71572         if (!Ext.isBoolean(sourceEditMode)) {
71573             sourceEditMode = !me.sourceEditMode;
71574         }
71575         me.sourceEditMode = sourceEditMode;
71576
71577         if (btn.pressed !== sourceEditMode) {
71578             btn.toggle(sourceEditMode);
71579         }
71580         if (sourceEditMode) {
71581             me.disableItems(true);
71582             me.syncValue();
71583             iframe.addCls(hiddenCls);
71584             textarea.removeCls(hiddenCls);
71585             textarea.dom.removeAttribute('tabIndex');
71586             textarea.focus();
71587         }
71588         else {
71589             if (me.initialized) {
71590                 me.disableItems(me.readOnly);
71591             }
71592             me.pushValue();
71593             iframe.removeCls(hiddenCls);
71594             textarea.addCls(hiddenCls);
71595             textarea.dom.setAttribute('tabIndex', -1);
71596             me.deferFocus();
71597         }
71598         me.fireEvent('editmodechange', me, sourceEditMode);
71599         me.doComponentLayout();
71600     },
71601
71602     
71603     createLink : function() {
71604         var url = prompt(this.createLinkText, this.defaultLinkValue);
71605         if (url && url !== 'http:/'+'/') {
71606             this.relayCmd('createlink', url);
71607         }
71608     },
71609
71610     clearInvalid: Ext.emptyFn,
71611
71612     
71613     setValue: function(value) {
71614         var me = this,
71615             textarea = me.textareaEl;
71616         me.mixins.field.setValue.call(me, value);
71617         if (value === null || value === undefined) {
71618             value = '';
71619         }
71620         if (textarea) {
71621             textarea.dom.value = value;
71622         }
71623         me.pushValue();
71624         return this;
71625     },
71626
71627     
71628     cleanHtml: function(html) {
71629         html = String(html);
71630         if (Ext.isWebKit) { 
71631             html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
71632         }
71633
71634         
71635         if (html.charCodeAt(0) === this.defaultValue.replace(/\D/g, '')) {
71636             html = html.substring(1);
71637         }
71638         return html;
71639     },
71640
71641     
71642     syncValue : function(){
71643         var me = this,
71644             body, html, bodyStyle, match;
71645         if (me.initialized) {
71646             body = me.getEditorBody();
71647             html = body.innerHTML;
71648             if (Ext.isWebKit) {
71649                 bodyStyle = body.getAttribute('style'); 
71650                 match = bodyStyle.match(/text-align:(.*?);/i);
71651                 if (match && match[1]) {
71652                     html = '<div style="' + match[0] + '">' + html + '</div>';
71653                 }
71654             }
71655             html = me.cleanHtml(html);
71656             if (me.fireEvent('beforesync', me, html) !== false) {
71657                 me.textareaEl.dom.value = html;
71658                 me.fireEvent('sync', me, html);
71659             }
71660         }
71661     },
71662
71663     
71664     getValue : function() {
71665         var me = this,
71666             value;
71667         if (!me.sourceEditMode) {
71668             me.syncValue();
71669         }
71670         value = me.rendered ? me.textareaEl.dom.value : me.value;
71671         me.value = value;
71672         return value;
71673     },
71674
71675     
71676     pushValue: function() {
71677         var me = this,
71678             v;
71679         if(me.initialized){
71680             v = me.textareaEl.dom.value || '';
71681             if (!me.activated && v.length < 1) {
71682                 v = me.defaultValue;
71683             }
71684             if (me.fireEvent('beforepush', me, v) !== false) {
71685                 me.getEditorBody().innerHTML = v;
71686                 if (Ext.isGecko) {
71687                     
71688                     me.setDesignMode(false);  
71689                     me.setDesignMode(true);
71690                 }
71691                 me.fireEvent('push', me, v);
71692             }
71693         }
71694     },
71695
71696     
71697     deferFocus : function(){
71698          this.focus(false, true);
71699     },
71700
71701     getFocusEl: function() {
71702         var me = this,
71703             win = me.win;
71704         return win && !me.sourceEditMode ? win : me.textareaEl;
71705     },
71706
71707     
71708     initEditor : function(){
71709         
71710         try {
71711             var me = this,
71712                 dbody = me.getEditorBody(),
71713                 ss = me.textareaEl.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'),
71714                 doc,
71715                 fn;
71716
71717             ss['background-attachment'] = 'fixed'; 
71718             dbody.bgProperties = 'fixed'; 
71719
71720             Ext.core.DomHelper.applyStyles(dbody, ss);
71721
71722             doc = me.getDoc();
71723
71724             if (doc) {
71725                 try {
71726                     Ext.EventManager.removeAll(doc);
71727                 } catch(e) {}
71728             }
71729
71730             
71731             fn = Ext.Function.bind(me.onEditorEvent, me);
71732             Ext.EventManager.on(doc, {
71733                 mousedown: fn,
71734                 dblclick: fn,
71735                 click: fn,
71736                 keyup: fn,
71737                 buffer:100
71738             });
71739
71740             
71741             
71742             
71743             
71744             
71745             fn = me.onRelayedEvent;
71746             Ext.EventManager.on(doc, {
71747                 mousedown: fn, 
71748                 mousemove: fn, 
71749                 mouseup: fn,   
71750                 click: fn,     
71751                 dblclick: fn,  
71752                 scope: me
71753             });
71754
71755             if (Ext.isGecko) {
71756                 Ext.EventManager.on(doc, 'keypress', me.applyCommand, me);
71757             }
71758             if (me.fixKeys) {
71759                 Ext.EventManager.on(doc, 'keydown', me.fixKeys, me);
71760             }
71761
71762             
71763             Ext.EventManager.on(window, 'unload', me.beforeDestroy, me);
71764             doc.editorInitialized = true;
71765
71766             me.initialized = true;
71767             me.pushValue();
71768             me.setReadOnly(me.readOnly);
71769             me.fireEvent('initialize', me);
71770         } catch(ex) {
71771             
71772         }
71773     },
71774
71775     
71776     beforeDestroy : function(){
71777         var me = this,
71778             monitorTask = me.monitorTask,
71779             doc, prop;
71780
71781         if (monitorTask) {
71782             Ext.TaskManager.stop(monitorTask);
71783         }
71784         if (me.rendered) {
71785             try {
71786                 doc = me.getDoc();
71787                 if (doc) {
71788                     Ext.EventManager.removeAll(doc);
71789                     for (prop in doc) {
71790                         if (doc.hasOwnProperty(prop)) {
71791                             delete doc[prop];
71792                         }
71793                     }
71794                 }
71795             } catch(e) {
71796                 
71797             }
71798             Ext.destroyMembers('tb', 'toolbarWrap', 'iframeEl', 'textareaEl');
71799         }
71800         me.callParent();
71801     },
71802
71803     
71804     onRelayedEvent: function (event) {
71805         
71806
71807         var iframeEl = this.iframeEl,
71808             iframeXY = iframeEl.getXY(),
71809             eventXY = event.getXY();
71810
71811         
71812         
71813         event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]];
71814
71815         event.injectEvent(iframeEl); 
71816
71817         event.xy = eventXY; 
71818     },
71819
71820     
71821     onFirstFocus : function(){
71822         var me = this,
71823             selection, range;
71824         me.activated = true;
71825         me.disableItems(me.readOnly);
71826         if (Ext.isGecko) { 
71827             me.win.focus();
71828             selection = me.win.getSelection();
71829             if (!selection.focusNode || selection.focusNode.nodeType !== 3) {
71830                 range = selection.getRangeAt(0);
71831                 range.selectNodeContents(me.getEditorBody());
71832                 range.collapse(true);
71833                 me.deferFocus();
71834             }
71835             try {
71836                 me.execCmd('useCSS', true);
71837                 me.execCmd('styleWithCSS', false);
71838             } catch(e) {
71839                 
71840             }
71841         }
71842         me.fireEvent('activate', me);
71843     },
71844
71845     
71846     adjustFont: function(btn) {
71847         var adjust = btn.getItemId() === 'increasefontsize' ? 1 : -1,
71848             size = this.getDoc().queryCommandValue('FontSize') || '2',
71849             isPxSize = Ext.isString(size) && size.indexOf('px') !== -1,
71850             isSafari;
71851         size = parseInt(size, 10);
71852         if (isPxSize) {
71853             
71854             
71855             if (size <= 10) {
71856                 size = 1 + adjust;
71857             }
71858             else if (size <= 13) {
71859                 size = 2 + adjust;
71860             }
71861             else if (size <= 16) {
71862                 size = 3 + adjust;
71863             }
71864             else if (size <= 18) {
71865                 size = 4 + adjust;
71866             }
71867             else if (size <= 24) {
71868                 size = 5 + adjust;
71869             }
71870             else {
71871                 size = 6 + adjust;
71872             }
71873             size = Ext.Number.constrain(size, 1, 6);
71874         } else {
71875             isSafari = Ext.isSafari;
71876             if (isSafari) { 
71877                 adjust *= 2;
71878             }
71879             size = Math.max(1, size + adjust) + (isSafari ? 'px' : 0);
71880         }
71881         this.execCmd('FontSize', size);
71882     },
71883
71884     
71885     onEditorEvent: function(e) {
71886         this.updateToolbar();
71887     },
71888
71889     
71890     updateToolbar: function() {
71891         var me = this,
71892             btns, doc, name, fontSelect;
71893
71894         if (me.readOnly) {
71895             return;
71896         }
71897
71898         if (!me.activated) {
71899             me.onFirstFocus();
71900             return;
71901         }
71902
71903         btns = me.getToolbar().items.map;
71904         doc = me.getDoc();
71905
71906         if (me.enableFont && !Ext.isSafari2) {
71907             name = (doc.queryCommandValue('FontName') || me.defaultFont).toLowerCase();
71908             fontSelect = me.fontSelect.dom;
71909             if (name !== fontSelect.value) {
71910                 fontSelect.value = name;
71911             }
71912         }
71913
71914         function updateButtons() {
71915             Ext.Array.forEach(Ext.Array.toArray(arguments), function(name) {
71916                 btns[name].toggle(doc.queryCommandState(name));
71917             });
71918         }
71919         if(me.enableFormat){
71920             updateButtons('bold', 'italic', 'underline');
71921         }
71922         if(me.enableAlignments){
71923             updateButtons('justifyleft', 'justifycenter', 'justifyright');
71924         }
71925         if(!Ext.isSafari2 && me.enableLists){
71926             updateButtons('insertorderedlist', 'insertunorderedlist');
71927         }
71928
71929         Ext.menu.Manager.hideAll();
71930
71931         me.syncValue();
71932     },
71933
71934     
71935     relayBtnCmd: function(btn) {
71936         this.relayCmd(btn.getItemId());
71937     },
71938
71939     
71940     relayCmd: function(cmd, value) {
71941         Ext.defer(function() {
71942             var me = this;
71943             me.focus();
71944             me.execCmd(cmd, value);
71945             me.updateToolbar();
71946         }, 10, this);
71947     },
71948
71949     
71950     execCmd : function(cmd, value){
71951         var me = this,
71952             doc = me.getDoc(),
71953             undef;
71954         doc.execCommand(cmd, false, value === undef ? null : value);
71955         me.syncValue();
71956     },
71957
71958     
71959     applyCommand : function(e){
71960         if (e.ctrlKey) {
71961             var me = this,
71962                 c = e.getCharCode(), cmd;
71963             if (c > 0) {
71964                 c = String.fromCharCode(c);
71965                 switch (c) {
71966                     case 'b':
71967                         cmd = 'bold';
71968                     break;
71969                     case 'i':
71970                         cmd = 'italic';
71971                     break;
71972                     case 'u':
71973                         cmd = 'underline';
71974                     break;
71975                 }
71976                 if (cmd) {
71977                     me.win.focus();
71978                     me.execCmd(cmd);
71979                     me.deferFocus();
71980                     e.preventDefault();
71981                 }
71982             }
71983         }
71984     },
71985
71986     
71987     insertAtCursor : function(text){
71988         var me = this,
71989             range;
71990
71991         if (me.activated) {
71992             me.win.focus();
71993             if (Ext.isIE) {
71994                 range = me.getDoc().selection.createRange();
71995                 if (range) {
71996                     range.pasteHTML(text);
71997                     me.syncValue();
71998                     me.deferFocus();
71999                 }
72000             }else{
72001                 me.execCmd('InsertHTML', text);
72002                 me.deferFocus();
72003             }
72004         }
72005     },
72006
72007     
72008     fixKeys: function() { 
72009         if (Ext.isIE) {
72010             return function(e){
72011                 var me = this,
72012                     k = e.getKey(),
72013                     doc = me.getDoc(),
72014                     range, target;
72015                 if (k === e.TAB) {
72016                     e.stopEvent();
72017                     range = doc.selection.createRange();
72018                     if(range){
72019                         range.collapse(true);
72020                         range.pasteHTML('&nbsp;&nbsp;&nbsp;&nbsp;');
72021                         me.deferFocus();
72022                     }
72023                 }
72024                 else if (k === e.ENTER) {
72025                     range = doc.selection.createRange();
72026                     if (range) {
72027                         target = range.parentElement();
72028                         if(!target || target.tagName.toLowerCase() !== 'li'){
72029                             e.stopEvent();
72030                             range.pasteHTML('<br />');
72031                             range.collapse(false);
72032                             range.select();
72033                         }
72034                     }
72035                 }
72036             };
72037         }
72038
72039         if (Ext.isOpera) {
72040             return function(e){
72041                 var me = this;
72042                 if (e.getKey() === e.TAB) {
72043                     e.stopEvent();
72044                     me.win.focus();
72045                     me.execCmd('InsertHTML','&nbsp;&nbsp;&nbsp;&nbsp;');
72046                     me.deferFocus();
72047                 }
72048             };
72049         }
72050
72051         if (Ext.isWebKit) {
72052             return function(e){
72053                 var me = this,
72054                     k = e.getKey();
72055                 if (k === e.TAB) {
72056                     e.stopEvent();
72057                     me.execCmd('InsertText','\t');
72058                     me.deferFocus();
72059                 }
72060                 else if (k === e.ENTER) {
72061                     e.stopEvent();
72062                     me.execCmd('InsertHtml','<br /><br />');
72063                     me.deferFocus();
72064                 }
72065             };
72066         }
72067
72068         return null; 
72069     }(),
72070
72071     
72072     getToolbar : function(){
72073         return this.toolbar;
72074     },
72075
72076     
72077     buttonTips : {
72078         bold : {
72079             title: 'Bold (Ctrl+B)',
72080             text: 'Make the selected text bold.',
72081             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72082         },
72083         italic : {
72084             title: 'Italic (Ctrl+I)',
72085             text: 'Make the selected text italic.',
72086             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72087         },
72088         underline : {
72089             title: 'Underline (Ctrl+U)',
72090             text: 'Underline the selected text.',
72091             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72092         },
72093         increasefontsize : {
72094             title: 'Grow Text',
72095             text: 'Increase the font size.',
72096             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72097         },
72098         decreasefontsize : {
72099             title: 'Shrink Text',
72100             text: 'Decrease the font size.',
72101             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72102         },
72103         backcolor : {
72104             title: 'Text Highlight Color',
72105             text: 'Change the background color of the selected text.',
72106             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72107         },
72108         forecolor : {
72109             title: 'Font Color',
72110             text: 'Change the color of the selected text.',
72111             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72112         },
72113         justifyleft : {
72114             title: 'Align Text Left',
72115             text: 'Align text to the left.',
72116             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72117         },
72118         justifycenter : {
72119             title: 'Center Text',
72120             text: 'Center text in the editor.',
72121             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72122         },
72123         justifyright : {
72124             title: 'Align Text Right',
72125             text: 'Align text to the right.',
72126             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72127         },
72128         insertunorderedlist : {
72129             title: 'Bullet List',
72130             text: 'Start a bulleted list.',
72131             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72132         },
72133         insertorderedlist : {
72134             title: 'Numbered List',
72135             text: 'Start a numbered list.',
72136             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72137         },
72138         createlink : {
72139             title: 'Hyperlink',
72140             text: 'Make the selected text a hyperlink.',
72141             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72142         },
72143         sourceedit : {
72144             title: 'Source Edit',
72145             text: 'Switch to source editing mode.',
72146             cls: Ext.baseCSSPrefix + 'html-editor-tip'
72147         }
72148     }
72149
72150     
72151     
72152     
72153     
72154     
72155     
72156     
72157     
72158     
72159     
72160     
72161     
72162     
72163     
72164     
72165     
72166     
72167 });
72168
72169
72170 Ext.define('Ext.form.field.Radio', {
72171     extend:'Ext.form.field.Checkbox',
72172     alias: ['widget.radiofield', 'widget.radio'],
72173     alternateClassName: 'Ext.form.Radio',
72174     requires: ['Ext.form.RadioManager'],
72175
72176     isRadio: true,
72177
72178     
72179
72180     
72181     inputType: 'radio',
72182     ariaRole: 'radio',
72183
72184     
72185     getGroupValue: function() {
72186         var selected = this.getManager().getChecked(this.name);
72187         return selected ? selected.inputValue : null;
72188     },
72189
72190     
72191     onBoxClick: function(e) {
72192         var me = this;
72193         if (!me.disabled && !me.readOnly) {
72194             this.setValue(true);
72195         }
72196     },
72197
72198     
72199     setValue: function(v) {
72200         var me = this,
72201             active;
72202
72203         if (Ext.isBoolean(v)) {
72204             me.callParent(arguments);
72205         } else {
72206             active = me.getManager().getWithValue(me.name, v).getAt(0);
72207             if (active) {
72208                 active.setValue(true);
72209             }
72210         }
72211         return me;
72212     },
72213
72214     
72215     getSubmitValue: function() {
72216         return this.checked ? this.inputValue : null;
72217     },
72218
72219     getModelData: function() {
72220         return this.getSubmitData();
72221     },
72222
72223     
72224     onChange: function(newVal, oldVal) {
72225         var me = this;
72226         me.callParent(arguments);
72227
72228         if (newVal) {
72229             this.getManager().getByName(me.name).each(function(item){
72230                 if (item !== me) {
72231                     item.setValue(false);
72232                 }
72233             }, me);
72234         }
72235     },
72236
72237     
72238     beforeDestroy: function(){
72239         this.callParent();
72240         this.getManager().removeAtKey(this.id);
72241     },
72242
72243     
72244     getManager: function() {
72245         return Ext.form.RadioManager;
72246     }
72247 });
72248
72249
72250 Ext.define('Ext.picker.Time', {
72251     extend: 'Ext.view.BoundList',
72252     alias: 'widget.timepicker',
72253     requires: ['Ext.data.Store', 'Ext.Date'],
72254
72255     
72256
72257     
72258
72259     
72260     increment: 15,
72261
72262     
72263     format : "g:i A",
72264
72265     
72266     displayField: 'disp',
72267
72268     
72269     initDate: [2008,1,1],
72270
72271     componentCls: Ext.baseCSSPrefix + 'timepicker',
72272
72273     
72274     loadingText: '',
72275
72276     initComponent: function() {
72277         var me = this,
72278             dateUtil = Ext.Date,
72279             clearTime = dateUtil.clearTime,
72280             initDate = me.initDate.join('/');
72281
72282         
72283         me.absMin = clearTime(new Date(initDate));
72284         me.absMax = dateUtil.add(clearTime(new Date(initDate)), 'mi', (24 * 60) - 1);
72285
72286         me.store = me.createStore();
72287         me.updateList();
72288
72289         this.callParent();
72290     },
72291
72292     
72293     setMinValue: function(value) {
72294         this.minValue = value;
72295         this.updateList();
72296     },
72297
72298     
72299     setMaxValue: function(value) {
72300         this.maxValue = value;
72301         this.updateList();
72302     },
72303
72304     
72305     normalizeDate: function(date) {
72306         var initDate = this.initDate;
72307         date.setFullYear(initDate[0], initDate[1] - 1, initDate[2]);
72308         return date;
72309     },
72310
72311     
72312     updateList: function() {
72313         var me = this,
72314             min = me.normalizeDate(me.minValue || me.absMin),
72315             max = me.normalizeDate(me.maxValue || me.absMax);
72316
72317         me.store.filterBy(function(record) {
72318             var date = record.get('date');
72319             return date >= min && date <= max;
72320         });
72321     },
72322
72323     
72324     createStore: function() {
72325         var me = this,
72326             utilDate = Ext.Date,
72327             times = [],
72328             min = me.absMin,
72329             max = me.absMax;
72330
72331         while(min <= max){
72332             times.push({
72333                 disp: utilDate.dateFormat(min, me.format),
72334                 date: min
72335             });
72336             min = utilDate.add(min, 'mi', me.increment);
72337         }
72338
72339         return Ext.create('Ext.data.Store', {
72340             fields: ['disp', 'date'],
72341             data: times
72342         });
72343     }
72344
72345 });
72346
72347
72348 Ext.define('Ext.form.field.Time', {
72349     extend:'Ext.form.field.Picker',
72350     alias: 'widget.timefield',
72351     requires: ['Ext.form.field.Date', 'Ext.picker.Time', 'Ext.view.BoundListKeyNav', 'Ext.Date'],
72352     alternateClassName: ['Ext.form.TimeField', 'Ext.form.Time'],
72353
72354     
72355     triggerCls: Ext.baseCSSPrefix + 'form-time-trigger',
72356
72357     
72358
72359     
72360
72361     
72362     minText : "The time in this field must be equal to or after {0}",
72363
72364     
72365     maxText : "The time in this field must be equal to or before {0}",
72366
72367     
72368     invalidText : "{0} is not a valid time",
72369
72370     
72371     format : "g:i A",
72372
72373     
72374
72375     
72376     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",
72377
72378     
72379     increment: 15,
72380
72381     
72382     pickerMaxHeight: 300,
72383
72384     
72385     selectOnTab: true,
72386
72387     
72388     initDate: '1/1/2008',
72389     initDateFormat: 'j/n/Y',
72390
72391
72392     initComponent: function() {
72393         var me = this,
72394             min = me.minValue,
72395             max = me.maxValue;
72396         if (min) {
72397             me.setMinValue(min);
72398         }
72399         if (max) {
72400             me.setMaxValue(max);
72401         }
72402         this.callParent();
72403     },
72404
72405     initValue: function() {
72406         var me = this,
72407             value = me.value;
72408
72409         
72410         if (Ext.isString(value)) {
72411             me.value = me.rawToValue(value);
72412         }
72413
72414         me.callParent();
72415     },
72416
72417     
72418     setMinValue: function(value) {
72419         var me = this,
72420             picker = me.picker;
72421         me.setLimit(value, true);
72422         if (picker) {
72423             picker.setMinValue(me.minValue);
72424         }
72425     },
72426
72427     
72428     setMaxValue: function(value) {
72429         var me = this,
72430             picker = me.picker;
72431         me.setLimit(value, false);
72432         if (picker) {
72433             picker.setMaxValue(me.maxValue);
72434         }
72435     },
72436
72437     
72438     setLimit: function(value, isMin) {
72439         var me = this,
72440             d, val;
72441         if (Ext.isString(value)) {
72442             d = me.parseDate(value);
72443         }
72444         else if (Ext.isDate(value)) {
72445             d = value;
72446         }
72447         if (d) {
72448             val = Ext.Date.clearTime(new Date(me.initDate));
72449             val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
72450             me[isMin ? 'minValue' : 'maxValue'] = val;
72451         }
72452     },
72453
72454     rawToValue: function(rawValue) {
72455         return this.parseDate(rawValue) || rawValue || null;
72456     },
72457
72458     valueToRaw: function(value) {
72459         return this.formatDate(this.parseDate(value));
72460     },
72461
72462     
72463     getErrors: function(value) {
72464         var me = this,
72465             format = Ext.String.format,
72466             errors = me.callParent(arguments),
72467             minValue = me.minValue,
72468             maxValue = me.maxValue,
72469             date;
72470
72471         value = me.formatDate(value || me.processRawValue(me.getRawValue()));
72472
72473         if (value === null || value.length < 1) { 
72474              return errors;
72475         }
72476
72477         date = me.parseDate(value);
72478         if (!date) {
72479             errors.push(format(me.invalidText, value, me.format));
72480             return errors;
72481         }
72482
72483         if (minValue && date < minValue) {
72484             errors.push(format(me.minText, me.formatDate(minValue)));
72485         }
72486
72487         if (maxValue && date > maxValue) {
72488             errors.push(format(me.maxText, me.formatDate(maxValue)));
72489         }
72490
72491         return errors;
72492     },
72493
72494     formatDate: function() {
72495         return Ext.form.field.Date.prototype.formatDate.apply(this, arguments);
72496     },
72497
72498     
72499     parseDate: function(value) {
72500         if (!value || Ext.isDate(value)) {
72501             return value;
72502         }
72503
72504         var me = this,
72505             val = me.safeParse(value, me.format),
72506             altFormats = me.altFormats,
72507             altFormatsArray = me.altFormatsArray,
72508             i = 0,
72509             len;
72510
72511         if (!val && altFormats) {
72512             altFormatsArray = altFormatsArray || altFormats.split('|');
72513             len = altFormatsArray.length;
72514             for (; i < len && !val; ++i) {
72515                 val = me.safeParse(value, altFormatsArray[i]);
72516             }
72517         }
72518         return val;
72519     },
72520
72521     safeParse: function(value, format){
72522         var me = this,
72523             utilDate = Ext.Date,
72524             parsedDate,
72525             result = null;
72526
72527         if (utilDate.formatContainsDateInfo(format)) {
72528             
72529             result = utilDate.parse(value, format);
72530         } else {
72531             
72532             parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
72533             if (parsedDate) {
72534                 result = parsedDate;
72535             }
72536         }
72537         return result;
72538     },
72539
72540     
72541     getSubmitValue: function() {
72542         var me = this,
72543             format = me.submitFormat || me.format,
72544             value = me.getValue();
72545
72546         return value ? Ext.Date.format(value, format) : null;
72547     },
72548
72549     
72550     createPicker: function() {
72551         var me = this,
72552             picker = Ext.create('Ext.picker.Time', {
72553                 selModel: {
72554                     mode: 'SINGLE'
72555                 },
72556                 floating: true,
72557                 hidden: true,
72558                 minValue: me.minValue,
72559                 maxValue: me.maxValue,
72560                 increment: me.increment,
72561                 format: me.format,
72562                 ownerCt: this.ownerCt,
72563                 renderTo: document.body,
72564                 maxHeight: me.pickerMaxHeight,
72565                 focusOnToFront: false
72566             });
72567
72568         me.mon(picker.getSelectionModel(), {
72569             selectionchange: me.onListSelect,
72570             scope: me
72571         });
72572
72573         return picker;
72574     },
72575
72576     
72577     onExpand: function() {
72578         var me = this,
72579             keyNav = me.pickerKeyNav,
72580             selectOnTab = me.selectOnTab,
72581             picker = me.getPicker(),
72582             lastSelected = picker.getSelectionModel().lastSelected,
72583             itemNode;
72584
72585         if (!keyNav) {
72586             keyNav = me.pickerKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
72587                 boundList: picker,
72588                 forceKeyDown: true,
72589                 tab: function(e) {
72590                     if (selectOnTab) {
72591                         this.selectHighlighted(e);
72592                         me.triggerBlur();
72593                     }
72594                     
72595                     return true;
72596                 }
72597             });
72598             
72599             if (selectOnTab) {
72600                 me.ignoreMonitorTab = true;
72601             }
72602         }
72603         Ext.defer(keyNav.enable, 1, keyNav); 
72604
72605         
72606         if (lastSelected) {
72607             itemNode = picker.getNode(lastSelected);
72608             if (itemNode) {
72609                 picker.highlightItem(itemNode);
72610                 picker.el.scrollChildIntoView(itemNode, false);
72611             }
72612         }
72613     },
72614
72615     
72616     onCollapse: function() {
72617         var me = this,
72618             keyNav = me.pickerKeyNav;
72619         if (keyNav) {
72620             keyNav.disable();
72621             me.ignoreMonitorTab = false;
72622         }
72623     },
72624
72625     
72626     onListSelect: function(list, recordArray) {
72627         var me = this,
72628             record = recordArray[0],
72629             val = record ? record.get('date') : null;
72630         me.setValue(val);
72631         me.fireEvent('select', me, val);
72632         me.picker.clearHighlight();
72633         me.collapse();
72634         me.inputEl.focus();
72635     }
72636 });
72637
72638
72639
72640 Ext.define('Ext.grid.CellEditor', {
72641     extend: 'Ext.Editor',
72642     constructor: function(config) {
72643         if (config.field) {
72644             config.field.monitorTab = false;
72645         }
72646         config.autoSize = {
72647             width: 'boundEl'
72648         };
72649         this.callParent(arguments);
72650     },
72651     
72652     
72653     onShow: function() {
72654         var first = this.boundEl.first();
72655         if (first) {
72656             first.hide();
72657         }
72658         this.callParent(arguments);
72659     },
72660     
72661     
72662     onHide: function() {
72663         var first = this.boundEl.first();
72664         if (first) {
72665             first.show();
72666         }
72667         this.callParent(arguments);
72668     },
72669     
72670     
72671     afterRender: function() {
72672         this.callParent(arguments);
72673         var field = this.field;
72674         if (field.isXType('checkboxfield')) {
72675             field.mon(field.inputEl, 'mousedown', this.onCheckBoxMouseDown, this);
72676             field.mon(field.inputEl, 'click', this.onCheckBoxClick, this);
72677         }
72678     },
72679     
72680     
72681     onCheckBoxMouseDown: function() {
72682         this.completeEdit = Ext.emptyFn;
72683     },
72684     
72685     
72686     onCheckBoxClick: function() {
72687         delete this.completeEdit;
72688         this.field.focus(false, 10);
72689     },
72690     
72691     alignment: "tl-tl",
72692     hideEl : false,
72693     cls: Ext.baseCSSPrefix + "small-editor " + Ext.baseCSSPrefix + "grid-editor",
72694     shim: false,
72695     shadow: false
72696 });
72697
72698 Ext.define('Ext.grid.ColumnLayout', {
72699     extend: 'Ext.layout.container.HBox',
72700     alias: 'layout.gridcolumn',
72701     type : 'column',
72702
72703     
72704     clearInnerCtOnLayout: false,
72705
72706     constructor: function() {
72707         var me = this;
72708         me.callParent(arguments);
72709         if (!Ext.isDefined(me.availableSpaceOffset)) {
72710             me.availableSpaceOffset = (Ext.getScrollBarWidth() - 2);
72711         }
72712     },
72713
72714     beforeLayout: function() {
72715         var me = this,
72716             i = 0,
72717             items = me.getLayoutItems(),
72718             len = items.length,
72719             item, returnValue;
72720
72721         returnValue = me.callParent(arguments);
72722
72723         
72724         me.innerCt.setHeight(23);
72725
72726         
72727         if (me.align == 'stretchmax') {
72728             for (; i < len; i++) {
72729                 item = items[i];
72730                 item.el.setStyle({
72731                     height: 'auto'
72732                 });
72733                 item.titleContainer.setStyle({
72734                     height: 'auto',
72735                     paddingTop: '0'
72736                 });
72737                 if (item.componentLayout && item.componentLayout.lastComponentSize) {
72738                     item.componentLayout.lastComponentSize.height = item.el.dom.offsetHeight;
72739                 }
72740             }
72741         }
72742         return returnValue;
72743     },
72744
72745     
72746     calculateChildBoxes: function(visibleItems, targetSize) {
72747         var me = this,
72748             calculations = me.callParent(arguments),
72749             boxes = calculations.boxes,
72750             metaData = calculations.meta,
72751             len = boxes.length, i = 0, box, item;
72752
72753         if (targetSize.width && !me.isColumn) {
72754             
72755             if (me.owner.forceFit) {
72756
72757                 for (; i < len; i++) {
72758                     box = boxes[i];
72759                     item = box.component;
72760
72761                     
72762                     item.minWidth = Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
72763
72764                     
72765                     
72766                     item.flex = box.width;
72767                 }
72768
72769                 
72770                 calculations = me.callParent(arguments);
72771             }
72772             else if (metaData.tooNarrow) {
72773                 targetSize.width = metaData.desiredSize;
72774             }
72775         }
72776
72777         return calculations;
72778     },
72779
72780     afterLayout: function() {
72781         var me = this,
72782             i = 0,
72783             items = me.getLayoutItems(),
72784             len = items.length;
72785
72786         me.callParent(arguments);
72787
72788         
72789         if (me.align == 'stretchmax') {
72790             for (; i < len; i++) {
72791                 items[i].setPadding();
72792             }
72793         }
72794     },
72795
72796     
72797     
72798     updateInnerCtSize: function(tSize, calcs) {
72799         var me    = this,
72800             extra = 0;
72801
72802         
72803         if (!me.isColumn && calcs.meta.tooNarrow) {
72804             if (
72805                 Ext.isWebKit ||
72806                 Ext.isGecko ||
72807                 (Ext.isIEQuirks && (Ext.isIE6 || Ext.isIE7 || Ext.isIE8))
72808             ) {
72809                 extra = 1;
72810             
72811             } else if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
72812                 extra = 2;
72813             }
72814             
72815             
72816             extra++;
72817             tSize.width = calcs.meta.desiredSize + (me.reserveOffset ? me.availableSpaceOffset : 0) + extra;
72818         }
72819         return me.callParent(arguments);
72820     },
72821
72822     doOwnerCtLayouts: function() {
72823         var ownerCt = this.owner.ownerCt;
72824         if (!ownerCt.componentLayout.layoutBusy) {
72825             ownerCt.doComponentLayout();
72826         }
72827     }
72828 });
72829
72830 Ext.define('Ext.grid.LockingView', {
72831     
72832     mixins: {
72833         observable: 'Ext.util.Observable'
72834     },
72835     
72836     eventRelayRe: /^(beforeitem|beforecontainer|item|container|cell)/,
72837     
72838     constructor: function(config){
72839         var me = this,
72840             eventNames = [],
72841             eventRe = me.eventRelayRe,
72842             locked = config.locked.getView(),
72843             normal = config.normal.getView(),
72844             events,
72845             event;
72846         
72847         Ext.apply(me, {
72848             lockedView: locked,
72849             normalView: normal,
72850             lockedGrid: config.locked,
72851             normalGrid: config.normal,
72852             panel: config.panel
72853         });
72854         me.mixins.observable.constructor.call(me, config);
72855         
72856         
72857         events = locked.events;
72858         for (event in events) {
72859             if (events.hasOwnProperty(event) && eventRe.test(event)) {
72860                 eventNames.push(event);
72861             }
72862         }
72863         me.relayEvents(locked, eventNames);
72864         me.relayEvents(normal, eventNames);
72865         
72866         normal.on({
72867             scope: me,
72868             itemmouseleave: me.onItemMouseLeave,
72869             itemmouseenter: me.onItemMouseEnter
72870         });
72871         
72872         locked.on({
72873             scope: me,
72874             itemmouseleave: me.onItemMouseLeave,
72875             itemmouseenter: me.onItemMouseEnter
72876         });
72877     },
72878     
72879     getGridColumns: function() {
72880         var cols = this.lockedGrid.headerCt.getGridColumns();
72881         return cols.concat(this.normalGrid.headerCt.getGridColumns());
72882     },
72883     
72884     onItemMouseEnter: function(view, record){
72885         var me = this,
72886             locked = me.lockedView,
72887             other = me.normalView,
72888             item;
72889             
72890         if (view.trackOver) {
72891             if (view !== locked) {
72892                 other = locked;
72893             }
72894             item = other.getNode(record);
72895             other.highlightItem(item);
72896         }
72897     },
72898     
72899     onItemMouseLeave: function(view, record){
72900         var me = this,
72901             locked = me.lockedView,
72902             other = me.normalView;
72903             
72904         if (view.trackOver) {
72905             if (view !== locked) {
72906                 other = locked;
72907             }
72908             other.clearHighlight();
72909         }
72910     },
72911     
72912     relayFn: function(name, args){
72913         args = args || [];
72914         
72915         var view = this.lockedView;
72916         view[name].apply(view, args || []);    
72917         view = this.normalView;
72918         view[name].apply(view, args || []);   
72919     },
72920     
72921     getSelectionModel: function(){
72922         return this.panel.getSelectionModel();    
72923     },
72924     
72925     getStore: function(){
72926         return this.panel.store;
72927     },
72928     
72929     getNode: function(nodeInfo){
72930         
72931         return this.normalView.getNode(nodeInfo);
72932     },
72933     
72934     getCell: function(record, column){
72935         var view = this.lockedView,
72936             row;
72937         
72938         
72939         if (view.getHeaderAtIndex(column) === -1) {
72940             view = this.normalView;
72941         }
72942         
72943         row = view.getNode(record);
72944         return Ext.fly(row).down(column.getCellSelector());
72945     },
72946     
72947     getRecord: function(node){
72948         var result = this.lockedView.getRecord(node);
72949         if (!node) {
72950             result = this.normalView.getRecord(node);
72951         }
72952         return result;
72953     },
72954     
72955     addElListener: function(eventName, fn, scope){
72956         this.relayFn('addElListener', arguments);
72957     },
72958     
72959     refreshNode: function(){
72960         this.relayFn('refreshNode', arguments);
72961     },
72962     
72963     refresh: function(){
72964         this.relayFn('refresh', arguments);
72965     },
72966     
72967     bindStore: function(){
72968         this.relayFn('bindStore', arguments);
72969     },
72970     
72971     addRowCls: function(){
72972         this.relayFn('addRowCls', arguments);
72973     },
72974     
72975     removeRowCls: function(){
72976         this.relayFn('removeRowCls', arguments);
72977     }
72978        
72979 });
72980
72981 Ext.define('Ext.grid.Lockable', {
72982     
72983     requires: ['Ext.grid.LockingView'],
72984     
72985     
72986     syncRowHeight: true,
72987     
72988     
72989     
72990     
72991
72992     
72993     
72994     
72995     spacerHidden: true,
72996     
72997     
72998     unlockText: 'Unlock',
72999     lockText: 'Lock',
73000     
73001     determineXTypeToCreate: function() {
73002         var me = this,
73003             typeToCreate;
73004
73005         if (me.subGridXType) {
73006             typeToCreate = me.subGridXType;
73007         } else {
73008             var xtypes     = this.getXTypes().split('/'),
73009                 xtypesLn   = xtypes.length,
73010                 xtype      = xtypes[xtypesLn - 1],
73011                 superxtype = xtypes[xtypesLn - 2];
73012                 
73013             if (superxtype !== 'tablepanel') {
73014                 typeToCreate = superxtype;
73015             } else {
73016                 typeToCreate = xtype;
73017             }
73018         }
73019         
73020         return typeToCreate;
73021     },
73022     
73023     
73024     
73025     injectLockable: function() {
73026         
73027         this.lockable = true;
73028         
73029         
73030         this.hasView = true;
73031
73032         var me = this,
73033             
73034             
73035             
73036             xtype = me.determineXTypeToCreate(),
73037             
73038             selModel = me.getSelectionModel(),
73039             lockedGrid = {
73040                 xtype: xtype,
73041                 
73042                 enableAnimations: false,
73043                 scroll: false,
73044                 scrollerOwner: false,
73045                 selModel: selModel,
73046                 border: false,
73047                 cls: Ext.baseCSSPrefix + 'grid-inner-locked'
73048             },
73049             normalGrid = {
73050                 xtype: xtype,
73051                 enableAnimations: false,
73052                 scrollerOwner: false,
73053                 selModel: selModel,
73054                 border: false
73055             },
73056             i = 0,
73057             columns,
73058             lockedHeaderCt,
73059             normalHeaderCt;
73060         
73061         me.addCls(Ext.baseCSSPrefix + 'grid-locked');
73062         
73063         
73064         
73065         
73066         Ext.copyTo(normalGrid, me, me.normalCfgCopy);
73067         Ext.copyTo(lockedGrid, me, me.lockedCfgCopy);
73068         for (; i < me.normalCfgCopy.length; i++) {
73069             delete me[me.normalCfgCopy[i]];
73070         }
73071         for (i = 0; i < me.lockedCfgCopy.length; i++) {
73072             delete me[me.lockedCfgCopy[i]];
73073         }
73074         
73075         me.lockedHeights = [];
73076         me.normalHeights = [];
73077         
73078         columns = me.processColumns(me.columns);
73079
73080         lockedGrid.width = columns.lockedWidth;
73081         lockedGrid.columns = columns.locked;
73082         normalGrid.columns = columns.normal;
73083         
73084         me.store = Ext.StoreManager.lookup(me.store);
73085         lockedGrid.store = me.store;
73086         normalGrid.store = me.store;
73087         
73088         
73089         normalGrid.flex = 1;
73090         lockedGrid.viewConfig = me.lockedViewConfig || {};
73091         lockedGrid.viewConfig.loadingUseMsg = false;
73092         normalGrid.viewConfig = me.normalViewConfig || {};
73093         
73094         Ext.applyIf(lockedGrid.viewConfig, me.viewConfig);
73095         Ext.applyIf(normalGrid.viewConfig, me.viewConfig);
73096         
73097         me.normalGrid = Ext.ComponentManager.create(normalGrid);
73098         me.lockedGrid = Ext.ComponentManager.create(lockedGrid);
73099         
73100         me.view = Ext.create('Ext.grid.LockingView', {
73101             locked: me.lockedGrid,
73102             normal: me.normalGrid,
73103             panel: me    
73104         });
73105         
73106         if (me.syncRowHeight) {
73107             me.lockedGrid.getView().on({
73108                 refresh: me.onLockedGridAfterRefresh,
73109                 itemupdate: me.onLockedGridAfterUpdate,
73110                 scope: me
73111             });
73112             
73113             me.normalGrid.getView().on({
73114                 refresh: me.onNormalGridAfterRefresh,
73115                 itemupdate: me.onNormalGridAfterUpdate,
73116                 scope: me
73117             });
73118         }
73119         
73120         lockedHeaderCt = me.lockedGrid.headerCt;
73121         normalHeaderCt = me.normalGrid.headerCt;
73122         
73123         lockedHeaderCt.lockedCt = true;
73124         lockedHeaderCt.lockableInjected = true;
73125         normalHeaderCt.lockableInjected = true;
73126         
73127         lockedHeaderCt.on({
73128             columnshow: me.onLockedHeaderShow,
73129             columnhide: me.onLockedHeaderHide,
73130             columnmove: me.onLockedHeaderMove,
73131             sortchange: me.onLockedHeaderSortChange,
73132             columnresize: me.onLockedHeaderResize,
73133             scope: me
73134         });
73135         
73136         normalHeaderCt.on({
73137             columnmove: me.onNormalHeaderMove,
73138             sortchange: me.onNormalHeaderSortChange,
73139             scope: me
73140         });
73141         
73142         me.normalGrid.on({
73143             scrollershow: me.onScrollerShow,
73144             scrollerhide: me.onScrollerHide,
73145             scope: me
73146         });
73147         
73148         me.lockedGrid.on('afterlayout', me.onLockedGridAfterLayout, me, {single: true});
73149         
73150         me.modifyHeaderCt();
73151         me.items = [me.lockedGrid, me.normalGrid];
73152
73153         me.layout = {
73154             type: 'hbox',
73155             align: 'stretch'
73156         };
73157     },
73158     
73159     processColumns: function(columns){
73160         
73161         var i = 0,
73162             len = columns.length,
73163             lockedWidth = 0,
73164             lockedHeaders = [],
73165             normalHeaders = [],
73166             column;
73167             
73168         for (; i < len; ++i) {
73169             column = columns[i];
73170             
73171             
73172             column.processed = true;
73173             if (column.locked) {
73174                 if (column.flex) {
73175                     Ext.Error.raise("Columns which are locked do NOT support a flex width. You must set a width on the " + columns[i].text + "column.");
73176                 }
73177                 lockedWidth += column.width;
73178                 lockedHeaders.push(column);
73179             } else {
73180                 normalHeaders.push(column);
73181             }
73182         }
73183         return {
73184             lockedWidth: lockedWidth,
73185             locked: lockedHeaders,
73186             normal: normalHeaders    
73187         };
73188     },
73189     
73190     
73191     onLockedGridAfterLayout: function() {
73192         var me         = this,
73193             lockedView = me.lockedGrid.getView();
73194         lockedView.on({
73195             refresh: me.createSpacer,
73196             beforerefresh: me.destroySpacer,
73197             scope: me
73198         });
73199     },
73200     
73201     
73202     onLockedHeaderMove: function() {
73203         if (this.syncRowHeight) {
73204             this.onNormalGridAfterRefresh();
73205         }
73206     },
73207     
73208     
73209     onNormalHeaderMove: function() {
73210         if (this.syncRowHeight) {
73211             this.onLockedGridAfterRefresh();
73212         }
73213     },
73214     
73215     
73216     
73217     createSpacer: function() {
73218         var me   = this,
73219             
73220             
73221             w    = Ext.getScrollBarWidth() + (Ext.isIE ? 2 : 0),
73222             view = me.lockedGrid.getView(),
73223             el   = view.el;
73224
73225         me.spacerEl = Ext.core.DomHelper.append(el, {
73226             cls: me.spacerHidden ? (Ext.baseCSSPrefix + 'hidden') : '',
73227             style: 'height: ' + w + 'px;'
73228         }, true);
73229     },
73230     
73231     destroySpacer: function() {
73232         var me = this;
73233         if (me.spacerEl) {
73234             me.spacerEl.destroy();
73235             delete me.spacerEl;
73236         }
73237     },
73238     
73239     
73240     onLockedGridAfterRefresh: function() {
73241         var me     = this,
73242             view   = me.lockedGrid.getView(),
73243             el     = view.el,
73244             rowEls = el.query(view.getItemSelector()),
73245             ln     = rowEls.length,
73246             i = 0;
73247             
73248         
73249         me.lockedHeights = [];
73250         
73251         for (; i < ln; i++) {
73252             me.lockedHeights[i] = rowEls[i].clientHeight;
73253         }
73254         me.syncRowHeights();
73255     },
73256     
73257     
73258     onNormalGridAfterRefresh: function() {
73259         var me     = this,
73260             view   = me.normalGrid.getView(),
73261             el     = view.el,
73262             rowEls = el.query(view.getItemSelector()),
73263             ln     = rowEls.length,
73264             i = 0;
73265             
73266         
73267         me.normalHeights = [];
73268         
73269         for (; i < ln; i++) {
73270             me.normalHeights[i] = rowEls[i].clientHeight;
73271         }
73272         me.syncRowHeights();
73273     },
73274     
73275     
73276     onLockedGridAfterUpdate: function(record, index, node) {
73277         this.lockedHeights[index] = node.clientHeight;
73278         this.syncRowHeights();
73279     },
73280     
73281     
73282     onNormalGridAfterUpdate: function(record, index, node) {
73283         this.normalHeights[index] = node.clientHeight;
73284         this.syncRowHeights();
73285     },
73286     
73287     
73288     
73289     syncRowHeights: function() {
73290         var me = this,
73291             lockedHeights = me.lockedHeights,
73292             normalHeights = me.normalHeights,
73293             calcHeights   = [],
73294             ln = lockedHeights.length,
73295             i  = 0,
73296             lockedView, normalView,
73297             lockedRowEls, normalRowEls,
73298             vertScroller = me.getVerticalScroller(),
73299             scrollTop;
73300
73301         
73302         
73303         if (lockedHeights.length && normalHeights.length) {
73304             lockedView = me.lockedGrid.getView();
73305             normalView = me.normalGrid.getView();
73306             lockedRowEls = lockedView.el.query(lockedView.getItemSelector());
73307             normalRowEls = normalView.el.query(normalView.getItemSelector());
73308
73309             
73310             for (; i < ln; i++) {
73311                 
73312                 if (!isNaN(lockedHeights[i]) && !isNaN(normalHeights[i])) {
73313                     if (lockedHeights[i] > normalHeights[i]) {
73314                         Ext.fly(normalRowEls[i]).setHeight(lockedHeights[i]);
73315                     } else if (lockedHeights[i] < normalHeights[i]) {
73316                         Ext.fly(lockedRowEls[i]).setHeight(normalHeights[i]);
73317                     }
73318                 }
73319             }
73320
73321             
73322             me.normalGrid.invalidateScroller();
73323             
73324             
73325             
73326             if (vertScroller && vertScroller.setViewScrollTop) {
73327                 vertScroller.setViewScrollTop(me.virtualScrollTop);
73328             } else {
73329                 
73330                 
73331                 
73332                 scrollTop = normalView.el.dom.scrollTop;
73333                 normalView.el.dom.scrollTop = scrollTop;
73334                 lockedView.el.dom.scrollTop = scrollTop;
73335             }
73336             
73337             
73338             me.lockedHeights = [];
73339             me.normalHeights = [];
73340         }
73341     },
73342     
73343     
73344     onScrollerShow: function(scroller, direction) {
73345         if (direction === 'horizontal') {
73346             this.spacerHidden = false;
73347             this.spacerEl.removeCls(Ext.baseCSSPrefix + 'hidden');
73348         }
73349     },
73350     
73351     
73352     onScrollerHide: function(scroller, direction) {
73353         if (direction === 'horizontal') {
73354             this.spacerHidden = true;
73355             this.spacerEl.addCls(Ext.baseCSSPrefix + 'hidden');
73356         }
73357     },
73358
73359     
73360     
73361     modifyHeaderCt: function() {
73362         var me = this;
73363         me.lockedGrid.headerCt.getMenuItems = me.getMenuItems(true);
73364         me.normalGrid.headerCt.getMenuItems = me.getMenuItems(false);
73365     },
73366     
73367     onUnlockMenuClick: function() {
73368         this.unlock();
73369     },
73370     
73371     onLockMenuClick: function() {
73372         this.lock();
73373     },
73374     
73375     getMenuItems: function(locked) {
73376         var me            = this,
73377             unlockText    = me.unlockText,
73378             lockText      = me.lockText,
73379             
73380             unlockCls     = 'xg-hmenu-unlock',
73381             lockCls       = 'xg-hmenu-lock',
73382             unlockHandler = Ext.Function.bind(me.onUnlockMenuClick, me),
73383             lockHandler   = Ext.Function.bind(me.onLockMenuClick, me);
73384         
73385         
73386         return function() {
73387             var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
73388             o.push('-',{
73389                 cls: unlockCls,
73390                 text: unlockText,
73391                 handler: unlockHandler,
73392                 disabled: !locked
73393             });
73394             o.push({
73395                 cls: lockCls,
73396                 text: lockText,
73397                 handler: lockHandler,
73398                 disabled: locked
73399             });
73400             return o;
73401         };
73402     },
73403     
73404     
73405     
73406     lock: function(activeHd, toIdx) {
73407         var me         = this,
73408             normalGrid = me.normalGrid,
73409             lockedGrid = me.lockedGrid,
73410             normalHCt  = normalGrid.headerCt,
73411             lockedHCt  = lockedGrid.headerCt;
73412             
73413         activeHd = activeHd || normalHCt.getMenu().activeHeader;
73414         
73415         
73416         
73417         if (activeHd.flex) {
73418             activeHd.width = activeHd.getWidth();
73419             delete activeHd.flex;
73420         }
73421         
73422         normalHCt.remove(activeHd, false);
73423         lockedHCt.suspendLayout = true;
73424         if (Ext.isDefined(toIdx)) {
73425             lockedHCt.insert(toIdx, activeHd);
73426         } else {
73427             lockedHCt.add(activeHd);
73428         }
73429         lockedHCt.suspendLayout = false;
73430         me.syncLockedSection();
73431     },
73432     
73433     syncLockedSection: function() {
73434         var me = this;
73435         me.syncLockedWidth();
73436         me.lockedGrid.getView().refresh();
73437         me.normalGrid.getView().refresh();
73438     },
73439     
73440     
73441     
73442     syncLockedWidth: function() {
73443         var me = this,
73444             width = me.lockedGrid.headerCt.getFullWidth(true);
73445         me.lockedGrid.setWidth(width);
73446     },
73447     
73448     onLockedHeaderResize: function() {
73449         this.syncLockedWidth();
73450     },
73451     
73452     onLockedHeaderHide: function() {
73453         this.syncLockedWidth();
73454     },
73455     
73456     onLockedHeaderShow: function() {
73457         this.syncLockedWidth();
73458     },
73459     
73460     onLockedHeaderSortChange: function(headerCt, header, sortState) {
73461         if (sortState) {
73462             
73463             
73464             this.normalGrid.headerCt.clearOtherSortStates(null, true);
73465         }
73466     },
73467     
73468     onNormalHeaderSortChange: function(headerCt, header, sortState) {
73469         if (sortState) {
73470             
73471             
73472             this.lockedGrid.headerCt.clearOtherSortStates(null, true);
73473         }
73474     },
73475     
73476     
73477     
73478     unlock: function(activeHd, toIdx) {
73479         var me         = this,
73480             normalGrid = me.normalGrid,
73481             lockedGrid = me.lockedGrid,
73482             normalHCt  = normalGrid.headerCt,
73483             lockedHCt  = lockedGrid.headerCt;
73484
73485         if (!Ext.isDefined(toIdx)) {
73486             toIdx = 0;
73487         }
73488         activeHd = activeHd || lockedHCt.getMenu().activeHeader;
73489         
73490         lockedHCt.remove(activeHd, false);
73491         me.syncLockedWidth();
73492         me.lockedGrid.getView().refresh();
73493         normalHCt.insert(toIdx, activeHd);
73494         me.normalGrid.getView().refresh();
73495     },
73496     
73497     
73498     reconfigureLockable: function(store, columns) {
73499         var me = this,
73500             lockedGrid = me.lockedGrid,
73501             normalGrid = me.normalGrid;
73502         
73503         if (columns) {
73504             lockedGrid.headerCt.removeAll();
73505             normalGrid.headerCt.removeAll();
73506             
73507             columns = me.processColumns(columns);
73508             lockedGrid.setWidth(columns.lockedWidth);
73509             lockedGrid.headerCt.add(columns.locked);
73510             normalGrid.headerCt.add(columns.normal);
73511         }
73512         
73513         if (store) {
73514             store = Ext.data.StoreManager.lookup(store);
73515             me.store = store;
73516             lockedGrid.bindStore(store);
73517             normalGrid.bindStore(store);
73518         } else {
73519             lockedGrid.getView().refresh();
73520             normalGrid.getView().refresh();
73521         }
73522     }
73523 });
73524
73525
73526 Ext.define('Ext.grid.Scroller', {
73527     extend: 'Ext.Component',
73528     alias: 'widget.gridscroller',
73529     weight: 110,
73530     cls: Ext.baseCSSPrefix + 'scroller',
73531     focusable: false,
73532     
73533     renderTpl: ['<div class="' + Ext.baseCSSPrefix + 'stretcher"></div>'],
73534     
73535     initComponent: function() {
73536         var me       = this,
73537             dock     = me.dock,
73538             cls      = Ext.baseCSSPrefix + 'scroller-vertical',
73539             sizeProp = 'width',
73540             
73541             
73542             
73543             
73544             
73545             scrollbarWidth = Ext.getScrollBarWidth() + (Ext.isIE ? 1 : -1);
73546
73547         me.offsets = {bottom: 0};
73548
73549         if (dock === 'top' || dock === 'bottom') {
73550             cls = Ext.baseCSSPrefix + 'scroller-horizontal';
73551             sizeProp = 'height';
73552         }
73553         me[sizeProp] = scrollbarWidth;
73554         
73555         me.cls += (' ' + cls);
73556         
73557         Ext.applyIf(me.renderSelectors, {
73558             stretchEl: '.' + Ext.baseCSSPrefix + 'stretcher'
73559         });
73560         me.callParent();
73561     },
73562     
73563     
73564     afterRender: function() {
73565         var me = this;
73566         me.callParent();
73567         me.ownerCt.on('afterlayout', me.onOwnerAfterLayout, me);
73568         me.mon(me.el, 'scroll', me.onElScroll, me);
73569         Ext.cache[me.el.id].skipGarbageCollection = true;
73570     },
73571     
73572     getSizeCalculation: function() {
73573         var owner  = this.getPanel(),
73574             dock   = this.dock,
73575             elDom  = this.el.dom,
73576             width  = 1,
73577             height = 1,
73578             view, tbl;
73579             
73580         if (dock === 'top' || dock === 'bottom') {
73581             
73582             
73583             var items  = owner.query('tableview'),
73584                 center = items[1] || items[0];
73585             
73586             if (!center) {
73587                 return false;
73588             }
73589             
73590             
73591             
73592             width = center.headerCt.getFullWidth();
73593             
73594             if (Ext.isIEQuirks) {
73595                 width--;
73596             }
73597             
73598             width--;
73599         } else {            
73600             view = owner.down('tableview:not([lockableInjected])');
73601             if (!view) {
73602                 return false;
73603             }
73604             tbl = view.el;
73605             if (!tbl) {
73606                 return false;
73607             }
73608             
73609             
73610             
73611             height = tbl.dom.scrollHeight;
73612         }
73613         if (isNaN(width)) {
73614             width = 1;
73615         }
73616         if (isNaN(height)) {
73617             height = 1;
73618         }
73619         return {
73620             width: width,
73621             height: height
73622         };
73623     },
73624     
73625     invalidate: function(firstPass) {
73626         if (!this.stretchEl || !this.ownerCt) {
73627             return;
73628         }
73629         var size  = this.getSizeCalculation(),
73630             elDom = this.el.dom;
73631         if (size) {
73632             this.stretchEl.setSize(size);
73633         
73634             
73635             
73636             elDom.scrollTop = elDom.scrollTop;
73637         }
73638     },
73639
73640     onOwnerAfterLayout: function(owner, layout) {
73641         this.invalidate();
73642     },
73643
73644     
73645     setScrollTop: function(scrollTop) {
73646         if (this.el) {
73647             var elDom = this.el.dom;
73648             return elDom.scrollTop = Ext.Number.constrain(scrollTop, 0, elDom.scrollHeight - elDom.clientHeight);
73649         }
73650     },
73651
73652     
73653     setScrollLeft: function(scrollLeft) {
73654         if (this.el) {
73655             var elDom = this.el.dom;
73656             return elDom.scrollLeft = Ext.Number.constrain(scrollLeft, 0, elDom.scrollWidth - elDom.clientWidth);
73657         }
73658     },
73659
73660     
73661     scrollByDeltaY: function(delta) {
73662         if (this.el) {
73663             var elDom = this.el.dom;
73664             return this.setScrollTop(elDom.scrollTop + delta);
73665         }
73666     },
73667
73668     
73669     scrollByDeltaX: function(delta) {
73670         if (this.el) {
73671             var elDom = this.el.dom;
73672             return this.setScrollLeft(elDom.scrollLeft + delta);
73673         }
73674     },
73675     
73676     
73677     
73678     scrollToTop : function(){
73679         this.setScrollTop(0);
73680     },
73681     
73682     
73683     onElScroll: function(event, target) {
73684         this.fireEvent('bodyscroll', event, target);
73685     },
73686
73687     getPanel: function() {
73688         var me = this;
73689         if (!me.panel) {
73690             me.panel = this.up('[scrollerOwner]');
73691         }
73692         return me.panel;
73693     }
73694 });
73695
73696
73697
73698 Ext.define('Ext.grid.PagingScroller', {
73699     extend: 'Ext.grid.Scroller',
73700     alias: 'widget.paginggridscroller',
73701     
73702     
73703     
73704     
73705     
73706     
73707     
73708     percentageFromEdge: 0.35,
73709     
73710     
73711     scrollToLoadBuffer: 200,
73712     
73713     activePrefetch: true,
73714     
73715     chunkSize: 50,
73716     snapIncrement: 25,
73717     
73718     syncScroll: true,
73719     
73720     initComponent: function() {
73721         var me = this,
73722             ds = me.store;
73723
73724         ds.on('guaranteedrange', this.onGuaranteedRange, this);
73725         this.callParent(arguments);
73726     },
73727     
73728     
73729     onGuaranteedRange: function(range, start, end) {
73730         var me = this,
73731             ds = me.store,
73732             rs;
73733         
73734         if (range.length && me.visibleStart < range[0].index) {
73735             return;
73736         }
73737         
73738         ds.loadRecords(range);
73739
73740         if (!me.firstLoad) {
73741             if (me.rendered) {
73742                 me.invalidate();
73743             } else {
73744                 me.on('afterrender', this.invalidate, this, {single: true});
73745             }
73746             me.firstLoad = true;
73747         } else {
73748             
73749             me.syncTo();
73750         }
73751     },
73752     
73753     syncTo: function() {
73754         var me            = this,
73755             pnl           = me.getPanel(),
73756             store         = pnl.store,
73757             scrollerElDom = this.el.dom,
73758             rowOffset     = me.visibleStart - store.guaranteedStart,
73759             scrollBy      = rowOffset * me.rowHeight,
73760             scrollHeight  = scrollerElDom.scrollHeight,
73761             clientHeight  = scrollerElDom.clientHeight,
73762             scrollTop     = scrollerElDom.scrollTop,
73763             useMaximum;
73764         
73765         
73766         
73767         if (Ext.isIE9 && Ext.isStrict) {
73768             clientHeight = scrollerElDom.offsetHeight + 2;
73769         }
73770
73771         
73772         
73773         useMaximum = (scrollHeight - clientHeight - scrollTop <= 0);
73774         this.setViewScrollTop(scrollBy, useMaximum);
73775     },
73776     
73777     getPageData : function(){
73778         var panel = this.getPanel(),
73779             store = panel.store,
73780             totalCount = store.getTotalCount();
73781             
73782         return {
73783             total : totalCount,
73784             currentPage : store.currentPage,
73785             pageCount: Math.ceil(totalCount / store.pageSize),
73786             fromRecord: ((store.currentPage - 1) * store.pageSize) + 1,
73787             toRecord: Math.min(store.currentPage * store.pageSize, totalCount)
73788         };
73789     },
73790     
73791     onElScroll: function(e, t) {
73792         var me = this,
73793             panel = me.getPanel(),
73794             store = panel.store,
73795             pageSize = store.pageSize,
73796             guaranteedStart = store.guaranteedStart,
73797             guaranteedEnd = store.guaranteedEnd,
73798             totalCount = store.getTotalCount(),
73799             numFromEdge = Math.ceil(me.percentageFromEdge * store.pageSize),
73800             position = t.scrollTop,
73801             visibleStart = Math.floor(position / me.rowHeight),
73802             view = panel.down('tableview'),
73803             viewEl = view.el,
73804             visibleHeight = viewEl.getHeight(),
73805             visibleAhead = Math.ceil(visibleHeight / me.rowHeight),
73806             visibleEnd = visibleStart + visibleAhead,
73807             prevPage = Math.floor(visibleStart / store.pageSize),
73808             nextPage = Math.floor(visibleEnd / store.pageSize) + 2,
73809             lastPage = Math.ceil(totalCount / store.pageSize),
73810             
73811             requestStart = Math.floor(visibleStart / me.snapIncrement) * me.snapIncrement,
73812             requestEnd = requestStart + pageSize - 1,
73813             activePrefetch = me.activePrefetch;
73814
73815         me.visibleStart = visibleStart;
73816         me.visibleEnd = visibleEnd;
73817         
73818         
73819         me.syncScroll = true;
73820         if (totalCount >= pageSize) {
73821             
73822             if (requestEnd > totalCount - 1) {
73823                 this.cancelLoad();
73824                 if (store.rangeSatisfied(totalCount - pageSize, totalCount - 1)) {
73825                     me.syncScroll = true;
73826                 }
73827                 store.guaranteeRange(totalCount - pageSize, totalCount - 1);
73828             
73829             } else if (visibleStart < guaranteedStart || visibleEnd > guaranteedEnd) {
73830                 if (store.rangeSatisfied(requestStart, requestEnd)) {
73831                     this.cancelLoad();
73832                     store.guaranteeRange(requestStart, requestEnd);
73833                 } else {
73834                     store.mask();
73835                     me.attemptLoad(requestStart, requestEnd);
73836                 }
73837                 
73838                 me.syncScroll = false;
73839             } else if (activePrefetch && visibleStart < (guaranteedStart + numFromEdge) && prevPage > 0) {
73840                 me.syncScroll = true;
73841                 store.prefetchPage(prevPage);
73842             } else if (activePrefetch && visibleEnd > (guaranteedEnd - numFromEdge) && nextPage < lastPage) {
73843                 me.syncScroll = true;
73844                 store.prefetchPage(nextPage);
73845             }
73846         }
73847     
73848     
73849         if (me.syncScroll) {
73850             me.syncTo();
73851         }
73852     },
73853     
73854     getSizeCalculation: function() {
73855         
73856         
73857         var owner = this.ownerCt,
73858             view   = owner.getView(),
73859             store  = this.store,
73860             dock   = this.dock,
73861             elDom  = this.el.dom,
73862             width  = 1,
73863             height = 1;
73864         
73865         if (!this.rowHeight) {
73866             this.rowHeight = view.el.down(view.getItemSelector()).getHeight(false, true);
73867         }
73868
73869         height = store.getTotalCount() * this.rowHeight;
73870
73871         if (isNaN(width)) {
73872             width = 1;
73873         }
73874         if (isNaN(height)) {
73875             height = 1;
73876         }
73877         return {
73878             width: width,
73879             height: height
73880         };
73881     },
73882     
73883     attemptLoad: function(start, end) {
73884         var me = this;
73885         if (!me.loadTask) {
73886             me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
73887         }
73888         me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]);
73889     },
73890     
73891     cancelLoad: function() {
73892         if (this.loadTask) {
73893             this.loadTask.cancel();
73894         }
73895     },
73896     
73897     doAttemptLoad:  function(start, end) {
73898         var store = this.getPanel().store;
73899         store.guaranteeRange(start, end);
73900     },
73901     
73902     setViewScrollTop: function(scrollTop, useMax) {
73903         var owner = this.getPanel(),
73904             items = owner.query('tableview'),
73905             i = 0,
73906             len = items.length,
73907             center,
73908             centerEl,
73909             calcScrollTop,
73910             maxScrollTop,
73911             scrollerElDom = this.el.dom;
73912             
73913         owner.virtualScrollTop = scrollTop;
73914             
73915         center = items[1] || items[0];
73916         centerEl = center.el.dom;
73917         
73918         maxScrollTop = ((owner.store.pageSize * this.rowHeight) - centerEl.clientHeight);
73919         calcScrollTop = (scrollTop % ((owner.store.pageSize * this.rowHeight) + 1));
73920         if (useMax) {
73921             calcScrollTop = maxScrollTop;
73922         }
73923         if (calcScrollTop > maxScrollTop) {
73924             
73925             return;
73926             
73927         }
73928         for (; i < len; i++) {
73929             items[i].el.dom.scrollTop = calcScrollTop;
73930         }
73931     }
73932 });
73933
73934
73935
73936 Ext.define('Ext.panel.Table', {
73937     extend: 'Ext.panel.Panel',
73938
73939     alias: 'widget.tablepanel',
73940
73941     uses: [
73942         'Ext.selection.RowModel',
73943         'Ext.grid.Scroller',
73944         'Ext.grid.header.Container',
73945         'Ext.grid.Lockable'
73946     ],
73947
73948     cls: Ext.baseCSSPrefix + 'grid',
73949     extraBodyCls: Ext.baseCSSPrefix + 'grid-body',
73950
73951     layout: 'fit',
73952     
73953     hasView: false,
73954
73955     
73956     viewType: null,
73957     selType: 'rowmodel',
73958
73959     
73960     scrollDelta: 40,
73961
73962     
73963     scroll: true,
73964
73965     
73966
73967     
73968
73969     
73970
73971     
73972     sortableColumns: true,
73973
73974     verticalScrollDock: 'right',
73975     verticalScrollerType: 'gridscroller',
73976
73977     horizontalScrollerPresentCls: Ext.baseCSSPrefix + 'horizontal-scroller-present',
73978     verticalScrollerPresentCls: Ext.baseCSSPrefix + 'vertical-scroller-present',
73979
73980     
73981     
73982     scrollerOwner: true,
73983
73984     invalidateScrollerOnRefresh: true,
73985     
73986     enableColumnMove: true,
73987     enableColumnResize: true,
73988
73989
73990     initComponent: function() {
73991         if (!this.viewType) {
73992             Ext.Error.raise("You must specify a viewType config.");
73993         }
73994         if (!this.store) {
73995             Ext.Error.raise("You must specify a store config");
73996         }
73997         if (this.headers) {
73998             Ext.Error.raise("The headers config is not supported. Please specify columns instead.");
73999         }
74000
74001         var me          = this,
74002             scroll      = me.scroll,
74003             vertical    = false,
74004             horizontal  = false,
74005             headerCtCfg = me.columns || me.colModel,
74006             i           = 0,
74007             view,
74008             border = me.border;
74009
74010         
74011         me.determineScrollbars = Ext.Function.createBuffered(me.determineScrollbars, 30);
74012         me.invalidateScroller = Ext.Function.createBuffered(me.invalidateScroller, 30);
74013         me.injectView = Ext.Function.createBuffered(me.injectView, 30);
74014
74015         if (me.hideHeaders) {
74016             border = false;
74017         }
74018
74019         
74020         
74021         if (headerCtCfg instanceof Ext.grid.header.Container) {
74022             me.headerCt = headerCtCfg;
74023             me.headerCt.border = border;
74024             me.columns = me.headerCt.items.items;
74025         } else {
74026             if (Ext.isArray(headerCtCfg)) {
74027                 headerCtCfg = {
74028                     items: headerCtCfg,
74029                     border: border
74030                 };
74031             }
74032             Ext.apply(headerCtCfg, {
74033                 forceFit: me.forceFit,
74034                 sortable: me.sortableColumns,
74035                 enableColumnMove: me.enableColumnMove,
74036                 enableColumnResize: me.enableColumnResize,
74037                 border:  border
74038             });
74039             me.columns = headerCtCfg.items;
74040
74041              
74042              
74043              if (Ext.ComponentQuery.query('{locked !== undefined}{processed != true}', me.columns).length) {
74044                  me.self.mixin('lockable', Ext.grid.Lockable);
74045                  me.injectLockable();
74046              }
74047         }
74048
74049         me.store = Ext.data.StoreManager.lookup(me.store);
74050         me.addEvents(
74051             
74052             'scrollerhide',
74053             
74054             'scrollershow'
74055         );
74056
74057         me.bodyCls = me.bodyCls || '';
74058         me.bodyCls += (' ' + me.extraBodyCls);
74059
74060         
74061         delete me.autoScroll;
74062
74063         
74064         
74065         if (!me.hasView) {
74066
74067             
74068             
74069             if (!me.headerCt) {
74070                 me.headerCt = Ext.create('Ext.grid.header.Container', headerCtCfg);
74071             }
74072
74073             
74074             me.columns = me.headerCt.items.items;
74075
74076             if (me.hideHeaders) {
74077                 me.headerCt.height = 0;
74078                 me.headerCt.border = false;
74079                 me.headerCt.addCls(Ext.baseCSSPrefix + 'grid-header-ct-hidden');
74080                 me.addCls(Ext.baseCSSPrefix + 'grid-header-hidden');
74081                 
74082                 
74083                 if (Ext.isIEQuirks) {
74084                     me.headerCt.style = {
74085                         display: 'none'
74086                     };
74087                 }
74088             }
74089
74090             
74091             if (scroll === true || scroll === 'both') {
74092                 vertical = horizontal = true;
74093             } else if (scroll === 'horizontal') {
74094                 horizontal = true;
74095             } else if (scroll === 'vertical') {
74096                 vertical = true;
74097             
74098             } else {
74099                 me.headerCt.availableSpaceOffset = 0;
74100             }
74101
74102             if (vertical) {
74103                 me.verticalScroller = me.verticalScroller || {};
74104                 Ext.applyIf(me.verticalScroller, {
74105                     dock: me.verticalScrollDock,
74106                     xtype: me.verticalScrollerType,
74107                     store: me.store
74108                 });
74109                 me.verticalScroller = Ext.ComponentManager.create(me.verticalScroller);
74110                 me.mon(me.verticalScroller, {
74111                     bodyscroll: me.onVerticalScroll,
74112                     scope: me
74113                 });
74114             }
74115
74116             if (horizontal) {
74117                 me.horizontalScroller = Ext.ComponentManager.create({
74118                     xtype: 'gridscroller',
74119                     section: me,
74120                     dock: 'bottom',
74121                     store: me.store
74122                 });
74123                 me.mon(me.horizontalScroller, {
74124                     bodyscroll: me.onHorizontalScroll,
74125                     scope: me
74126                 });
74127             }
74128
74129             me.headerCt.on('columnresize', me.onHeaderResize, me);
74130             me.relayEvents(me.headerCt, ['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange']);
74131             me.features = me.features || [];
74132             me.dockedItems = me.dockedItems || [];
74133             me.dockedItems.unshift(me.headerCt);
74134             me.viewConfig = me.viewConfig || {};
74135             me.viewConfig.invalidateScrollerOnRefresh = me.invalidateScrollerOnRefresh;
74136
74137             
74138             
74139             view = me.getView();
74140
74141             if (view) {
74142                 me.mon(view.store, {
74143                     load: me.onStoreLoad,
74144                     scope: me
74145                 });
74146                 me.mon(view, {
74147                     refresh: {
74148                         fn: this.onViewRefresh,
74149                         scope: me,
74150                         buffer: 50
74151                     },
74152                     itemupdate: me.onViewItemUpdate,
74153                     scope: me
74154                 });
74155                 this.relayEvents(view, [
74156                     
74157                     'beforeitemmousedown',
74158                     
74159                     'beforeitemmouseup',
74160                     
74161                     'beforeitemmouseenter',
74162                     
74163                     'beforeitemmouseleave',
74164                     
74165                     'beforeitemclick',
74166                     
74167                     'beforeitemdblclick',
74168                     
74169                     'beforeitemcontextmenu',
74170                     
74171                     'itemmousedown',
74172                     
74173                     'itemmouseup',
74174                     
74175                     'itemmouseenter',
74176                     
74177                     'itemmouseleave',
74178                     
74179                     'itemclick',
74180                     
74181                     'itemdblclick',
74182                     
74183                     'itemcontextmenu',
74184                     
74185                     'beforecontainermousedown',
74186                     
74187                     'beforecontainermouseup',
74188                     
74189                     'beforecontainermouseover',
74190                     
74191                     'beforecontainermouseout',
74192                     
74193                     'beforecontainerclick',
74194                     
74195                     'beforecontainerdblclick',
74196                     
74197                     'beforecontainercontextmenu',
74198                     
74199                     'containermouseup',
74200                     
74201                     'containermouseover',
74202                     
74203                     'containermouseout',
74204                     
74205                     'containerclick',
74206                     
74207                     'containerdblclick',
74208                     
74209                     'containercontextmenu',
74210
74211                     
74212                     'selectionchange',
74213                     
74214                     'beforeselect'
74215                 ]);
74216             }
74217         }
74218         me.callParent(arguments);
74219     },
74220
74221     
74222     initStateEvents: function(){
74223         var events = this.stateEvents;
74224         
74225         Ext.each(['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange'], function(event){
74226             if (Ext.Array.indexOf(events, event)) {
74227                 events.push(event);
74228             }
74229         });
74230         this.callParent();
74231     },
74232
74233     getState: function(){
74234         var state = {
74235             columns: []
74236         },
74237         sorter = this.store.sorters.first();
74238
74239         this.headerCt.items.each(function(header){
74240             state.columns.push({
74241                 id: header.headerId,
74242                 width: header.flex ? undefined : header.width,
74243                 hidden: header.hidden,
74244                 sortable: header.sortable
74245             });
74246         });
74247
74248         if (sorter) {
74249             state.sort = {
74250                 property: sorter.property,
74251                 direction: sorter.direction
74252             };
74253         }
74254         return state;
74255     },
74256
74257     applyState: function(state) {
74258         var headers = state.columns,
74259             length = headers ? headers.length : 0,
74260             headerCt = this.headerCt,
74261             items = headerCt.items,
74262             sorter = state.sort,
74263             store = this.store,
74264             i = 0,
74265             index,
74266             headerState,
74267             header;
74268
74269         for (; i < length; ++i) {
74270             headerState = headers[i];
74271             header = headerCt.down('gridcolumn[headerId=' + headerState.id + ']');
74272             index = items.indexOf(header);
74273             if (i !== index) {
74274                 headerCt.moveHeader(index, i);
74275             }
74276             header.sortable = headerState.sortable;
74277             if (Ext.isDefined(headerState.width)) {
74278                 delete header.flex;
74279                 if (header.rendered) {
74280                     header.setWidth(headerState.width);
74281                 } else {
74282                     header.minWidth = header.width = headerState.width;
74283                 }
74284             }
74285             header.hidden = headerState.hidden;
74286         }
74287
74288         if (sorter) {
74289             if (store.remoteSort) {
74290                 store.sorters.add(Ext.create('Ext.util.Sorter', {
74291                     property: sorter.property,
74292                     direction: sorter.direction
74293                 }));
74294             }
74295             else {
74296                 store.sort(sorter.property, sorter.direction);
74297             }
74298         }
74299     },
74300
74301     
74302     getStore: function(){
74303         return this.store;
74304     },
74305
74306     
74307     getView: function() {
74308         var me = this,
74309             sm;
74310
74311         if (!me.view) {
74312             sm = me.getSelectionModel();
74313             me.view = me.createComponent(Ext.apply({}, me.viewConfig, {
74314                 xtype: me.viewType,
74315                 store: me.store,
74316                 headerCt: me.headerCt,
74317                 selModel: sm,
74318                 features: me.features,
74319                 panel: me
74320             }));
74321             me.mon(me.view, {
74322                 uievent: me.processEvent,
74323                 scope: me
74324             });
74325             sm.view = me.view;
74326             me.headerCt.view = me.view;
74327             me.relayEvents(me.view, ['cellclick', 'celldblclick']);
74328         }
74329         return me.view;
74330     },
74331
74332     
74333     setAutoScroll: Ext.emptyFn,
74334
74335     
74336     
74337     
74338     elScroll: function(direction, distance, animate) {
74339         var me = this,
74340             scroller;
74341
74342         if (direction === "up" || direction === "left") {
74343             distance = -distance;
74344         }
74345
74346         if (direction === "down" || direction === "up") {
74347             scroller = me.getVerticalScroller();
74348             scroller.scrollByDeltaY(distance);
74349         } else {
74350             scroller = me.getHorizontalScroller();
74351             scroller.scrollByDeltaX(distance);
74352         }
74353     },
74354     
74355     afterLayout: function() {
74356         this.callParent(arguments);
74357         this.injectView();
74358     },
74359     
74360
74361     
74362     injectView: function() {
74363         if (!this.hasView && !this.collapsed) {
74364             var me   = this,
74365                 view = me.getView();
74366
74367             me.hasView = true;
74368             me.add(view);
74369
74370             
74371             view.el.scroll = Ext.Function.bind(me.elScroll, me);
74372             
74373             
74374             me.mon(view.el, {
74375                 mousewheel: me.onMouseWheel,
74376                 scope: me
74377             });
74378         }
74379     },
74380
74381     afterExpand: function() {
74382         this.callParent(arguments);
74383         if (!this.hasView) {
74384             this.injectView();
74385         }
74386     },
74387
74388     
74389     processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
74390         var me = this,
74391             header;
74392
74393         if (cellIndex !== -1) {
74394             header = me.headerCt.getGridColumns()[cellIndex];
74395             return header.processEvent.apply(header, arguments);
74396         }
74397     },
74398
74399     
74400     determineScrollbars: function() {
74401         var me = this,
74402             viewElDom,
74403             centerScrollWidth,
74404             centerClientWidth,
74405             scrollHeight,
74406             clientHeight;
74407
74408         if (!me.collapsed && me.view && me.view.el) {
74409             viewElDom = me.view.el.dom;
74410             
74411             centerScrollWidth = me.headerCt.getFullWidth();
74412             
74413             centerClientWidth = viewElDom.offsetWidth;
74414             if (me.verticalScroller && me.verticalScroller.el) {
74415                 scrollHeight = me.verticalScroller.getSizeCalculation().height;
74416             } else {
74417                 scrollHeight = viewElDom.scrollHeight;
74418             }
74419
74420             clientHeight = viewElDom.clientHeight;
74421
74422             me.suspendLayout = true;
74423             me.scrollbarChanged = false;
74424             if (!me.collapsed && scrollHeight > clientHeight) {
74425                 me.showVerticalScroller();
74426             } else {
74427                 me.hideVerticalScroller();
74428             }
74429
74430             if (!me.collapsed && centerScrollWidth > (centerClientWidth + Ext.getScrollBarWidth() - 2)) {
74431                 me.showHorizontalScroller();
74432             } else {
74433                 me.hideHorizontalScroller();
74434             }
74435             me.suspendLayout = false;
74436             if (me.scrollbarChanged) {
74437                 me.doComponentLayout();
74438             }
74439         }
74440     },
74441
74442     onHeaderResize: function() {
74443         if (this.view && this.view.rendered) {
74444             this.determineScrollbars();
74445             this.invalidateScroller();
74446         }
74447     },
74448
74449     
74450     hideHorizontalScroller: function() {
74451         var me = this;
74452
74453         if (me.horizontalScroller && me.horizontalScroller.ownerCt === me) {
74454             me.scrollbarChanged = true;
74455             me.verticalScroller.offsets.bottom = 0;
74456             me.removeDocked(me.horizontalScroller, false);
74457             me.removeCls(me.horizontalScrollerPresentCls);
74458             me.fireEvent('scrollerhide', me.horizontalScroller, 'horizontal');
74459         }
74460
74461     },
74462
74463     
74464     showHorizontalScroller: function() {
74465         var me = this;
74466
74467         if (me.verticalScroller) {
74468             me.verticalScroller.offsets.bottom = Ext.getScrollBarWidth() - 2;
74469         }
74470         if (me.horizontalScroller && me.horizontalScroller.ownerCt !== me) {
74471             me.scrollbarChanged = true;
74472             me.addDocked(me.horizontalScroller);
74473             me.addCls(me.horizontalScrollerPresentCls);
74474             me.fireEvent('scrollershow', me.horizontalScroller, 'horizontal');
74475         }
74476     },
74477
74478     
74479     hideVerticalScroller: function() {
74480         var me = this,
74481             headerCt = me.headerCt;
74482
74483         
74484         if (headerCt && headerCt.layout.reserveOffset) {
74485             headerCt.layout.reserveOffset = false;
74486             headerCt.doLayout();
74487         }
74488         if (me.verticalScroller && me.verticalScroller.ownerCt === me) {
74489             me.scrollbarChanged = true;
74490             me.removeDocked(me.verticalScroller, false);
74491             me.removeCls(me.verticalScrollerPresentCls);
74492             me.fireEvent('scrollerhide', me.verticalScroller, 'vertical');
74493         }
74494     },
74495
74496     
74497     showVerticalScroller: function() {
74498         var me = this,
74499             headerCt = me.headerCt;
74500
74501         
74502         if (headerCt && !headerCt.layout.reserveOffset) {
74503             headerCt.layout.reserveOffset = true;
74504             headerCt.doLayout();
74505         }
74506         if (me.verticalScroller && me.verticalScroller.ownerCt !== me) {
74507             me.scrollbarChanged = true;
74508             me.addDocked(me.verticalScroller);
74509             me.addCls(me.verticalScrollerPresentCls);
74510             me.fireEvent('scrollershow', me.verticalScroller, 'vertical');
74511         }
74512     },
74513
74514     
74515     invalidateScroller: function() {
74516         var me = this,
74517             vScroll = me.verticalScroller,
74518             hScroll = me.horizontalScroller;
74519
74520         if (vScroll) {
74521             vScroll.invalidate();
74522         }
74523         if (hScroll) {
74524             hScroll.invalidate();
74525         }
74526     },
74527
74528     
74529     onHeaderMove: function(headerCt, header, fromIdx, toIdx) {
74530         this.view.refresh();
74531     },
74532
74533     
74534     onHeaderHide: function(headerCt, header) {
74535         this.invalidateScroller();
74536     },
74537
74538     onHeaderShow: function(headerCt, header) {
74539         this.invalidateScroller();
74540     },
74541
74542     getVerticalScroller: function() {
74543         return this.getScrollerOwner().down('gridscroller[dock=' + this.verticalScrollDock + ']');
74544     },
74545
74546     getHorizontalScroller: function() {
74547         return this.getScrollerOwner().down('gridscroller[dock=bottom]');
74548     },
74549
74550     onMouseWheel: function(e) {
74551         var me = this,
74552             browserEvent = e.browserEvent,
74553             vertScroller = me.getVerticalScroller(),
74554             horizScroller = me.getHorizontalScroller(),
74555             scrollDelta = me.scrollDelta,
74556             deltaY, deltaX,
74557             vertScrollerEl, horizScrollerEl,
74558             vertScrollerElDom, horizScrollerElDom,
74559             horizontalCanScrollLeft, horizontalCanScrollRight,
74560             verticalCanScrollDown, verticalCanScrollUp;
74561
74562         
74563         if (horizScroller) {
74564             horizScrollerEl = horizScroller.el;
74565             if (horizScrollerEl) {
74566                 horizScrollerElDom = horizScrollerEl.dom;
74567                 horizontalCanScrollRight = horizScrollerElDom.scrollLeft !== horizScrollerElDom.scrollWidth - horizScrollerElDom.clientWidth;
74568                 horizontalCanScrollLeft  = horizScrollerElDom.scrollLeft !== 0;
74569             }
74570         }
74571         if (vertScroller) {
74572             vertScrollerEl = vertScroller.el;
74573             if (vertScrollerEl) {
74574                 vertScrollerElDom = vertScrollerEl.dom;
74575                 verticalCanScrollDown = vertScrollerElDom.scrollTop !== vertScrollerElDom.scrollHeight - vertScrollerElDom.clientHeight;
74576                 verticalCanScrollUp   = vertScrollerElDom.scrollTop !== 0;
74577             }
74578         }
74579
74580         
74581         if (browserEvent.wheelDeltaX || browserEvent.wheelDeltaY) {        
74582             deltaX = -browserEvent.wheelDeltaX / 120 * scrollDelta / 3;
74583             deltaY = -browserEvent.wheelDeltaY / 120 * scrollDelta / 3;
74584         } else {
74585             
74586             if (browserEvent.axis && browserEvent.axis === 1) {
74587                 deltaX = -(scrollDelta * e.getWheelDelta()) / 3;
74588             } else {
74589                 deltaY = -(scrollDelta * e.getWheelDelta() / 3);
74590             }
74591         }
74592         
74593         if (horizScroller) {
74594             if ((deltaX < 0 && horizontalCanScrollLeft) || (deltaX > 0 && horizontalCanScrollRight)) {
74595                 e.stopEvent();
74596                 horizScroller.scrollByDeltaX(deltaX);
74597             }
74598         }
74599         if (vertScroller) {
74600             if ((deltaY < 0 && verticalCanScrollUp) || (deltaY > 0 && verticalCanScrollDown)) {
74601                 e.stopEvent();
74602                 vertScroller.scrollByDeltaY(deltaY);    
74603             }
74604         }
74605     },
74606
74607     
74608     onViewRefresh: function() {
74609         if (Ext.isIE) {
74610             this.syncCellHeight();
74611         }
74612         this.determineScrollbars();
74613         if (this.invalidateScrollerOnRefresh) {
74614             this.invalidateScroller();
74615         }
74616     },
74617
74618     onViewItemUpdate: function(record, index, tr) {
74619         if (Ext.isIE) {
74620             this.syncCellHeight([tr]);
74621         }
74622     },
74623
74624     
74625     
74626     
74627     syncCellHeight: function(trs) {
74628         var me    = this,
74629             i     = 0,
74630             tds,
74631             j, tdsLn,
74632             tr, td,
74633             trsLn,
74634             rowHeights = [],
74635             cellHeights,
74636             cellClsSelector = ('.' + Ext.baseCSSPrefix + 'grid-cell');
74637
74638         trs   = trs || me.view.getNodes();
74639         
74640         trsLn = trs.length;
74641         
74642         for (; i < trsLn; i++) {
74643             tr = trs[i];
74644             tds = Ext.fly(tr).query(cellClsSelector);
74645             tdsLn = tds.length;
74646             cellHeights = [];
74647             for (j = 0; j < tdsLn; j++) {
74648                 td = tds[j];
74649                 cellHeights.push(td.clientHeight);
74650             }
74651             rowHeights.push(Ext.Array.max(cellHeights));
74652         }
74653
74654         
74655         for (i = 0; i < trsLn; i++) {
74656             tr = trs[i];
74657             tdsLn = tr.childNodes.length;
74658             for (j = 0; j < tdsLn; j++) {
74659                 td = Ext.fly(tr.childNodes[j]);
74660                 if (rowHeights[i]) {
74661                     if (td.is(cellClsSelector)) {
74662                         td.setHeight(rowHeights[i]);
74663                     } else {
74664                         td.down(cellClsSelector).setHeight(rowHeights[i]);
74665                     }
74666                 }
74667                 
74668             }
74669         }
74670     },
74671
74672     
74673     setScrollTop: function(top) {
74674         var me               = this,
74675             rootCmp          = me.getScrollerOwner(),
74676             verticalScroller = me.getVerticalScroller();
74677
74678         rootCmp.virtualScrollTop = top;
74679         if (verticalScroller) {
74680             verticalScroller.setScrollTop(top);
74681         }
74682
74683     },
74684
74685     getScrollerOwner: function() {
74686         var rootCmp = this;
74687         if (!this.scrollerOwner) {
74688             rootCmp = this.up('[scrollerOwner]');
74689         }
74690         return rootCmp;
74691     },
74692
74693     
74694     scrollByDeltaY: function(deltaY) {
74695         var rootCmp = this.getScrollerOwner(),
74696             scrollerRight;
74697         scrollerRight = rootCmp.down('gridscroller[dock=' + this.verticalScrollDock + ']');
74698         if (scrollerRight) {
74699             scrollerRight.scrollByDeltaY(deltaY);
74700         }
74701     },
74702
74703
74704     
74705     scrollByDeltaX: function(deltaX) {
74706         this.horizontalScroller.scrollByDeltaX(deltaX);
74707     },
74708
74709     
74710     getLhsMarker: function() {
74711         var me = this;
74712
74713         if (!me.lhsMarker) {
74714             me.lhsMarker = Ext.core.DomHelper.append(me.el, {
74715                 cls: Ext.baseCSSPrefix + 'grid-resize-marker'
74716             }, true);
74717         }
74718         return me.lhsMarker;
74719     },
74720
74721     
74722     getRhsMarker: function() {
74723         var me = this;
74724
74725         if (!me.rhsMarker) {
74726             me.rhsMarker = Ext.core.DomHelper.append(me.el, {
74727                 cls: Ext.baseCSSPrefix + 'grid-resize-marker'
74728             }, true);
74729         }
74730         return me.rhsMarker;
74731     },
74732
74733     
74734     getSelectionModel: function(){
74735         if (!this.selModel) {
74736             this.selModel = {};
74737         }
74738
74739         var mode = 'SINGLE',
74740             type;
74741         if (this.simpleSelect) {
74742             mode = 'SIMPLE';
74743         } else if (this.multiSelect) {
74744             mode = 'MULTI';
74745         }
74746
74747         Ext.applyIf(this.selModel, {
74748             allowDeselect: this.allowDeselect,
74749             mode: mode
74750         });
74751
74752         if (!this.selModel.events) {
74753             type = this.selModel.selType || this.selType;
74754             this.selModel = Ext.create('selection.' + type, this.selModel);
74755         }
74756
74757         if (!this.selModel.hasRelaySetup) {
74758             this.relayEvents(this.selModel, ['selectionchange', 'select', 'deselect']);
74759             this.selModel.hasRelaySetup = true;
74760         }
74761
74762         
74763         
74764         if (this.disableSelection) {
74765             this.selModel.locked = true;
74766         }
74767         return this.selModel;
74768     },
74769
74770     onVerticalScroll: function(event, target) {
74771         var owner = this.getScrollerOwner(),
74772             items = owner.query('tableview'),
74773             i = 0,
74774             len = items.length;
74775
74776         for (; i < len; i++) {
74777             items[i].el.dom.scrollTop = target.scrollTop;
74778         }
74779     },
74780
74781     onHorizontalScroll: function(event, target) {
74782         var owner = this.getScrollerOwner(),
74783             items = owner.query('tableview'),
74784             i = 0,
74785             len = items.length,
74786             center,
74787             centerEl,
74788             centerScrollWidth,
74789             centerClientWidth,
74790             width;
74791
74792         center = items[1] || items[0];
74793         centerEl = center.el.dom;
74794         centerScrollWidth = centerEl.scrollWidth;
74795         centerClientWidth = centerEl.offsetWidth;
74796         width = this.horizontalScroller.getWidth();
74797
74798         centerEl.scrollLeft = target.scrollLeft;
74799         this.headerCt.el.dom.scrollLeft = target.scrollLeft;
74800     },
74801
74802     
74803     onStoreLoad: Ext.emptyFn,
74804
74805     getEditorParent: function() {
74806         return this.body;
74807     },
74808
74809     bindStore: function(store) {
74810         var me = this;
74811         me.store = store;
74812         me.getView().bindStore(store);
74813     },
74814
74815     reconfigure: function(store, columns) {
74816         var me = this;
74817
74818         if (me.lockable) {
74819             me.reconfigureLockable(store, columns);
74820             return;
74821         }
74822
74823         if (columns) {
74824             me.headerCt.removeAll();
74825             me.headerCt.add(columns);
74826         }
74827         if (store) {
74828             store = Ext.StoreManager.lookup(store);
74829             me.bindStore(store);
74830         } else {
74831             me.getView().refresh();
74832         }
74833     },
74834     
74835     afterComponentLayout: function() {
74836         var me = this;
74837         me.callParent(arguments);
74838         me.determineScrollbars();
74839         me.invalidateScroller();
74840     }
74841 });
74842
74843 Ext.define('Ext.view.Table', {
74844     extend: 'Ext.view.View',
74845     alias: 'widget.tableview',
74846     uses: [
74847         'Ext.view.TableChunker',
74848         'Ext.util.DelayedTask',
74849         'Ext.util.MixedCollection'
74850     ],
74851
74852     cls: Ext.baseCSSPrefix + 'grid-view',
74853
74854     
74855     itemSelector: '.' + Ext.baseCSSPrefix + 'grid-row',
74856     
74857     cellSelector: '.' + Ext.baseCSSPrefix + 'grid-cell',
74858
74859     selectedItemCls: Ext.baseCSSPrefix + 'grid-row-selected',
74860     selectedCellCls: Ext.baseCSSPrefix + 'grid-cell-selected',
74861     focusedItemCls: Ext.baseCSSPrefix + 'grid-row-focused',
74862     overItemCls: Ext.baseCSSPrefix + 'grid-row-over',
74863     altRowCls:   Ext.baseCSSPrefix + 'grid-row-alt',
74864     rowClsRe: /(?:^|\s*)grid-row-(first|last|alt)(?:\s+|$)/g,
74865     cellRe: new RegExp('x-grid-cell-([^\\s]+) ', ''),
74866
74867     
74868     trackOver: true,
74869
74870     
74871     getRowClass: null,
74872
74873     initComponent: function() {
74874         var me = this;
74875         
74876         me.scrollState = {};
74877         me.selModel.view = me;
74878         me.headerCt.view = me;
74879         me.initFeatures();
74880         me.tpl = '<div></div>';
74881         me.callParent();
74882         me.mon(me.store, {
74883             load: me.onStoreLoad,
74884             scope: me
74885         });
74886
74887         
74888         
74889         
74890         
74891         
74892         
74893         
74894         
74895         
74896     },
74897
74898     
74899     onStoreLoad: function(){
74900         var me = this;
74901         
74902         if (me.invalidateScrollerOnRefresh) {
74903             if (Ext.isGecko) {
74904                 if (!me.scrollToTopTask) {
74905                     me.scrollToTopTask = Ext.create('Ext.util.DelayedTask', me.scrollToTop, me);
74906                 }
74907                 me.scrollToTopTask.delay(1);
74908             } else {
74909                 me    .scrollToTop();
74910             }
74911         }
74912     },
74913
74914     
74915     scrollToTop: Ext.emptyFn,
74916     
74917     
74918     addElListener: function(eventName, fn, scope){
74919         this.mon(this, eventName, fn, scope, {
74920             element: 'el'
74921         });
74922     },
74923     
74924     
74925     getGridColumns: function() {
74926         return this.headerCt.getGridColumns();    
74927     },
74928     
74929     
74930     getHeaderAtIndex: function(index) {
74931         return this.headerCt.getHeaderAtIndex(index);
74932     },
74933     
74934     
74935     getCell: function(record, column) {
74936         var row = this.getNode(record);
74937         return Ext.fly(row).down(column.getCellSelector());
74938     },
74939
74940     
74941     getFeature: function(id) {
74942         var features = this.featuresMC;
74943         if (features) {
74944             return features.get(id);
74945         }
74946     },
74947
74948     
74949     initFeatures: function() {
74950         var me = this,
74951             i = 0,
74952             features,
74953             len;
74954             
74955         me.features = me.features || [];
74956         features = me.features;
74957         len = features.length;
74958
74959         me.featuresMC = Ext.create('Ext.util.MixedCollection');
74960         for (; i < len; i++) {
74961             
74962             if (!features[i].isFeature) {
74963                 features[i] = Ext.create('feature.' + features[i].ftype, features[i]);
74964             }
74965             
74966             features[i].view = me;
74967             me.featuresMC.add(features[i]);
74968         }
74969     },
74970
74971     
74972     attachEventsForFeatures: function() {
74973         var features = this.features,
74974             ln       = features.length,
74975             i        = 0;
74976
74977         for (; i < ln; i++) {
74978             if (features[i].isFeature) {
74979                 features[i].attachEvents();
74980             }
74981         }
74982     },
74983
74984     afterRender: function() {
74985         var me = this;
74986         
74987         me.callParent();
74988         me.mon(me.el, {
74989             scroll: me.fireBodyScroll,
74990             scope: me
74991         });
74992         me.el.unselectable();
74993         me.attachEventsForFeatures();
74994     },
74995
74996     fireBodyScroll: function(e, t) {
74997         this.fireEvent('bodyscroll', e, t);
74998     },
74999
75000     
75001     
75002     prepareData: function(data, idx, record) {
75003         var me       = this,
75004             orig     = me.headerCt.prepareData(data, idx, record, me, me.ownerCt),
75005             features = me.features,
75006             ln       = features.length,
75007             i        = 0,
75008             node, feature;
75009
75010         for (; i < ln; i++) {
75011             feature = features[i];
75012             if (feature.isFeature) {
75013                 Ext.apply(orig, feature.getAdditionalData(data, idx, record, orig, me));
75014             }
75015         }
75016
75017         return orig;
75018     },
75019
75020     
75021     collectData: function(records, startIndex) {
75022         var preppedRecords = this.callParent(arguments),
75023             headerCt  = this.headerCt,
75024             fullWidth = headerCt.getFullWidth(),
75025             features  = this.features,
75026             ln = features.length,
75027             o = {
75028                 rows: preppedRecords,
75029                 fullWidth: fullWidth
75030             },
75031             i  = 0,
75032             feature,
75033             j = 0,
75034             jln,
75035             rowParams;
75036
75037         jln = preppedRecords.length;
75038         
75039         
75040         if (this.getRowClass) {
75041             for (; j < jln; j++) {
75042                 rowParams = {};
75043                 preppedRecords[j]['rowCls'] = this.getRowClass(records[j], j, rowParams, this.store);
75044                 if (rowParams.alt) {
75045                     Ext.Error.raise("The getRowClass alt property is no longer supported.");
75046                 }
75047                 if (rowParams.tstyle) {
75048                     Ext.Error.raise("The getRowClass tstyle property is no longer supported.");
75049                 }
75050                 if (rowParams.cells) {
75051                     Ext.Error.raise("The getRowClass cells property is no longer supported.");
75052                 }
75053                 if (rowParams.body) {
75054                     Ext.Error.raise("The getRowClass body property is no longer supported. Use the getAdditionalData method of the rowbody feature.");
75055                 }
75056                 if (rowParams.bodyStyle) {
75057                     Ext.Error.raise("The getRowClass bodyStyle property is no longer supported.");
75058                 }
75059                 if (rowParams.cols) {
75060                     Ext.Error.raise("The getRowClass cols property is no longer supported.");
75061                 }
75062             }
75063         }
75064         
75065         
75066         for (; i < ln; i++) {
75067             feature = features[i];
75068             if (feature.isFeature && feature.collectData && !feature.disabled) {
75069                 o = feature.collectData(records, preppedRecords, startIndex, fullWidth, o);
75070                 break;
75071             }
75072         }
75073         return o;
75074     },
75075
75076     
75077     
75078     onHeaderResize: function(header, w, suppressFocus) {
75079         var me = this,
75080             el = me.el;
75081         if (el) {
75082             me.saveScrollState();
75083             
75084             
75085             
75086             el.select('.' + Ext.baseCSSPrefix + 'grid-col-resizer-'+header.id).setWidth(w);
75087             el.select('.' + Ext.baseCSSPrefix + 'grid-table-resizer').setWidth(me.headerCt.getFullWidth());
75088             me.restoreScrollState();
75089             me.setNewTemplate();
75090             if (!suppressFocus) {
75091                 me.el.focus();
75092             }
75093         }
75094     },
75095
75096     
75097     onHeaderShow: function(headerCt, header, suppressFocus) {
75098         
75099         if (header.oldWidth) {
75100             this.onHeaderResize(header, header.oldWidth, suppressFocus);
75101             delete header.oldWidth;
75102         
75103         
75104         
75105         } else if (header.width && !header.flex) {
75106             this.onHeaderResize(header, header.width, suppressFocus);
75107         }
75108         this.setNewTemplate();
75109     },
75110
75111     
75112     onHeaderHide: function(headerCt, header, suppressFocus) {
75113         this.onHeaderResize(header, 0, suppressFocus);
75114     },
75115
75116     
75117     setNewTemplate: function() {
75118         var me = this,
75119             columns = me.headerCt.getColumnsForTpl(true);
75120             
75121         me.tpl = me.getTableChunker().getTableTpl({
75122             columns: columns,
75123             features: me.features
75124         });
75125     },
75126
75127     
75128     getTableChunker: function() {
75129         return this.chunker || Ext.view.TableChunker;
75130     },
75131
75132     
75133     addRowCls: function(rowInfo, cls) {
75134         var row = this.getNode(rowInfo);
75135         if (row) {
75136             Ext.fly(row).addCls(cls);
75137         }
75138     },
75139
75140     
75141     removeRowCls: function(rowInfo, cls) {
75142         var row = this.getNode(rowInfo);
75143         if (row) {
75144             Ext.fly(row).removeCls(cls);
75145         }
75146     },
75147
75148     
75149     onRowSelect : function(rowIdx) {
75150         this.addRowCls(rowIdx, this.selectedItemCls);
75151     },
75152
75153     
75154     onRowDeselect : function(rowIdx) {
75155         var me = this;
75156         
75157         me.removeRowCls(rowIdx, me.selectedItemCls);
75158         me.removeRowCls(rowIdx, me.focusedItemCls);
75159     },
75160     
75161     onCellSelect: function(position) {
75162         var cell = this.getCellByPosition(position);
75163         if (cell) {
75164             cell.addCls(this.selectedCellCls);
75165         }
75166     },
75167     
75168     onCellDeselect: function(position) {
75169         var cell = this.getCellByPosition(position);
75170         if (cell) {
75171             cell.removeCls(this.selectedCellCls);
75172         }
75173         
75174     },
75175     
75176     onCellFocus: function(position) {
75177         
75178         this.focusCell(position);
75179     },
75180     
75181     getCellByPosition: function(position) {
75182         var row    = position.row,
75183             column = position.column,
75184             store  = this.store,
75185             node   = this.getNode(row),
75186             header = this.headerCt.getHeaderAtIndex(column),
75187             cellSelector,
75188             cell = false;
75189             
75190         if (header && node) {
75191             cellSelector = header.getCellSelector();
75192             cell = Ext.fly(node).down(cellSelector);
75193         }
75194         return cell;
75195     },
75196
75197     
75198     
75199     onRowFocus: function(rowIdx, highlight, supressFocus) {
75200         var me = this,
75201             row = me.getNode(rowIdx);
75202
75203         if (highlight) {
75204             me.addRowCls(rowIdx, me.focusedItemCls);
75205             if (!supressFocus) {
75206                 me.focusRow(rowIdx);
75207             }
75208             
75209         } else {
75210             me.removeRowCls(rowIdx, me.focusedItemCls);
75211         }
75212     },
75213
75214     
75215     focusRow: function(rowIdx) {
75216         var me         = this,
75217             row        = me.getNode(rowIdx),
75218             el         = me.el,
75219             adjustment = 0,
75220             panel      = me.ownerCt,
75221             rowRegion,
75222             elRegion,
75223             record;
75224             
75225         if (row && el) {
75226             elRegion  = el.getRegion();
75227             rowRegion = Ext.fly(row).getRegion();
75228             
75229             if (rowRegion.top < elRegion.top) {
75230                 adjustment = rowRegion.top - elRegion.top;
75231             
75232             } else if (rowRegion.bottom > elRegion.bottom) {
75233                 adjustment = rowRegion.bottom - elRegion.bottom;
75234             }
75235             record = me.getRecord(row);
75236             rowIdx = me.store.indexOf(record);
75237
75238             if (adjustment) {
75239                 
75240                 panel.scrollByDeltaY(adjustment);
75241             }
75242             me.fireEvent('rowfocus', record, row, rowIdx);
75243         }
75244     },
75245
75246     focusCell: function(position) {
75247         var me          = this,
75248             cell        = me.getCellByPosition(position),
75249             el          = me.el,
75250             adjustmentY = 0,
75251             adjustmentX = 0,
75252             elRegion    = el.getRegion(),
75253             panel       = me.ownerCt,
75254             cellRegion,
75255             record;
75256
75257         if (cell) {
75258             cellRegion = cell.getRegion();
75259             
75260             if (cellRegion.top < elRegion.top) {
75261                 adjustmentY = cellRegion.top - elRegion.top;
75262             
75263             } else if (cellRegion.bottom > elRegion.bottom) {
75264                 adjustmentY = cellRegion.bottom - elRegion.bottom;
75265             }
75266
75267             
75268             if (cellRegion.left < elRegion.left) {
75269                 adjustmentX = cellRegion.left - elRegion.left;
75270             
75271             } else if (cellRegion.right > elRegion.right) {
75272                 adjustmentX = cellRegion.right - elRegion.right;
75273             }
75274
75275             if (adjustmentY) {
75276                 
75277                 panel.scrollByDeltaY(adjustmentY);
75278             }
75279             if (adjustmentX) {
75280                 panel.scrollByDeltaX(adjustmentX);
75281             }
75282             el.focus();
75283             me.fireEvent('cellfocus', record, cell, position);
75284         }
75285     },
75286
75287     
75288     scrollByDelta: function(delta, dir) {
75289         dir = dir || 'scrollTop';
75290         var elDom = this.el.dom;
75291         elDom[dir] = (elDom[dir] += delta);
75292     },
75293
75294     onUpdate: function(ds, index) {
75295         this.callParent(arguments);
75296     },
75297
75298     
75299     saveScrollState: function() {
75300         var dom = this.el.dom,
75301             state = this.scrollState;
75302
75303         state.left = dom.scrollLeft;
75304         state.top = dom.scrollTop;
75305     },
75306
75307     
75308     restoreScrollState: function() {
75309         var dom = this.el.dom,
75310             state = this.scrollState,
75311             headerEl = this.headerCt.el.dom;
75312
75313         headerEl.scrollLeft = dom.scrollLeft = state.left;
75314         dom.scrollTop = state.top;
75315     },
75316
75317     
75318     refresh: function(firstPass) {
75319         var me = this,
75320             table;
75321
75322         
75323         me.setNewTemplate();
75324         
75325         me.callParent(arguments);
75326
75327         
75328
75329         if (me.rendered && !firstPass) {
75330             
75331             
75332         }
75333     },
75334
75335     processItemEvent: function(record, row, rowIndex, e) {
75336         var me = this,
75337             cell = e.getTarget(me.cellSelector, row),
75338             cellIndex = cell ? cell.cellIndex : -1,
75339             map = me.statics().EventMap,
75340             selModel = me.getSelectionModel(),
75341             type = e.type,
75342             result;
75343
75344         if (type == 'keydown' && !cell && selModel.getCurrentPosition) {
75345             
75346             cell = me.getCellByPosition(selModel.getCurrentPosition());
75347             if (cell) {
75348                 cell = cell.dom;
75349                 cellIndex = cell.cellIndex;
75350             }
75351         }
75352
75353         result = me.fireEvent('uievent', type, me, cell, rowIndex, cellIndex, e);
75354
75355         if (result === false || me.callParent(arguments) === false) {
75356             return false;
75357         }
75358
75359         
75360         if (type == 'mouseover' || type == 'mouseout') {
75361             return true;
75362         }
75363
75364         return !(
75365             
75366             (me['onBeforeCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
75367             (me.fireEvent('beforecell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false) ||
75368             (me['onCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) ||
75369             (me.fireEvent('cell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false)
75370         );
75371     },
75372
75373     processSpecialEvent: function(e) {
75374         var me = this,
75375             map = me.statics().EventMap,
75376             features = me.features,
75377             ln = features.length,
75378             type = e.type,
75379             i, feature, prefix, featureTarget,
75380             beforeArgs, args,
75381             panel = me.ownerCt;
75382
75383         me.callParent(arguments);
75384
75385         if (type == 'mouseover' || type == 'mouseout') {
75386             return;
75387         }
75388
75389         for (i = 0; i < ln; i++) {
75390             feature = features[i];
75391             if (feature.hasFeatureEvent) {
75392                 featureTarget = e.getTarget(feature.eventSelector, me.getTargetEl());
75393                 if (featureTarget) {
75394                     prefix = feature.eventPrefix;
75395                     
75396                     
75397                     beforeArgs = feature.getFireEventArgs('before' + prefix + type, me, featureTarget, e);
75398                     args = feature.getFireEventArgs(prefix + type, me, featureTarget, e);
75399                     
75400                     if (
75401                         
75402                         (me.fireEvent.apply(me, beforeArgs) === false) ||
75403                         
75404                         (panel.fireEvent.apply(panel, beforeArgs) === false) ||
75405                         
75406                         (me.fireEvent.apply(me, args) === false) ||
75407                         
75408                         (panel.fireEvent.apply(panel, args) === false)
75409                     ) {
75410                         return false;
75411                     }
75412                 }
75413             }
75414         }
75415         return true;
75416     },
75417
75418     onCellMouseDown: Ext.emptyFn,
75419     onCellMouseUp: Ext.emptyFn,
75420     onCellClick: Ext.emptyFn,
75421     onCellDblClick: Ext.emptyFn,
75422     onCellContextMenu: Ext.emptyFn,
75423     onCellKeyDown: Ext.emptyFn,
75424     onBeforeCellMouseDown: Ext.emptyFn,
75425     onBeforeCellMouseUp: Ext.emptyFn,
75426     onBeforeCellClick: Ext.emptyFn,
75427     onBeforeCellDblClick: Ext.emptyFn,
75428     onBeforeCellContextMenu: Ext.emptyFn,
75429     onBeforeCellKeyDown: Ext.emptyFn,
75430
75431     
75432     expandToFit: function(header) {
75433         var maxWidth = this.getMaxContentWidth(header);
75434         delete header.flex;
75435         header.setWidth(maxWidth);
75436     },
75437
75438     
75439     getMaxContentWidth: function(header) {
75440         var cellSelector = header.getCellInnerSelector(),
75441             cells        = this.el.query(cellSelector),
75442             i = 0,
75443             ln = cells.length,
75444             maxWidth = header.el.dom.scrollWidth,
75445             scrollWidth;
75446
75447         for (; i < ln; i++) {
75448             scrollWidth = cells[i].scrollWidth;
75449             if (scrollWidth > maxWidth) {
75450                 maxWidth = scrollWidth;
75451             }
75452         }
75453         return maxWidth;
75454     },
75455
75456     getPositionByEvent: function(e) {
75457         var me       = this,
75458             cellNode = e.getTarget(me.cellSelector),
75459             rowNode  = e.getTarget(me.itemSelector),
75460             record   = me.getRecord(rowNode),
75461             header   = me.getHeaderByCell(cellNode);
75462
75463         return me.getPosition(record, header);
75464     },
75465
75466     getHeaderByCell: function(cell) {
75467         if (cell) {
75468             var m = cell.className.match(this.cellRe);
75469             if (m && m[1]) {
75470                 return Ext.getCmp(m[1]);
75471             }
75472         }
75473         return false;
75474     },
75475
75476     
75477     walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
75478         var me       = this,
75479             row      = pos.row,
75480             column   = pos.column,
75481             rowCount = me.store.getCount(),
75482             firstCol = me.getFirstVisibleColumnIndex(),
75483             lastCol  = me.getLastVisibleColumnIndex(),
75484             newPos   = {row: row, column: column},
75485             activeHeader = me.headerCt.getHeaderAtIndex(column);
75486
75487         
75488         if (!activeHeader || activeHeader.hidden) {
75489             return false;
75490         }
75491
75492         e = e || {};
75493         direction = direction.toLowerCase();
75494         switch (direction) {
75495             case 'right':
75496                 
75497                 if (column === lastCol) {
75498                     
75499                     if (preventWrap || row === rowCount - 1) {
75500                         return false;
75501                     }
75502                     if (!e.ctrlKey) {
75503                         
75504                         newPos.row = row + 1;
75505                         newPos.column = firstCol;
75506                     }
75507                 
75508                 } else {
75509                     if (!e.ctrlKey) {
75510                         newPos.column = column + me.getRightGap(activeHeader);
75511                     } else {
75512                         newPos.column = lastCol;
75513                     }
75514                 }
75515                 break;
75516
75517             case 'left':
75518                 
75519                 if (column === firstCol) {
75520                     
75521                     if (preventWrap || row === 0) {
75522                         return false;
75523                     }
75524                     if (!e.ctrlKey) {
75525                         
75526                         newPos.row = row - 1;
75527                         newPos.column = lastCol;
75528                     }
75529                 
75530                 } else {
75531                     if (!e.ctrlKey) {
75532                         newPos.column = column + me.getLeftGap(activeHeader);
75533                     } else {
75534                         newPos.column = firstCol;
75535                     }
75536                 }
75537                 break;
75538
75539             case 'up':
75540                 
75541                 if (row === 0) {
75542                     return false;
75543                 
75544                 } else {
75545                     if (!e.ctrlKey) {
75546                         newPos.row = row - 1;
75547                     } else {
75548                         newPos.row = 0;
75549                     }
75550                 }
75551                 break;
75552
75553             case 'down':
75554                 
75555                 if (row === rowCount - 1) {
75556                     return false;
75557                 
75558                 } else {
75559                     if (!e.ctrlKey) {
75560                         newPos.row = row + 1;
75561                     } else {
75562                         newPos.row = rowCount - 1;
75563                     }
75564                 }
75565                 break;
75566         }
75567
75568         if (verifierFn && verifierFn.call(scope || window, newPos) !== true) {
75569             return false;
75570         } else {
75571             return newPos;
75572         }
75573     },
75574     getFirstVisibleColumnIndex: function() {
75575         var headerCt   = this.getHeaderCt(),
75576             allColumns = headerCt.getGridColumns(),
75577             visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
75578             firstHeader = visHeaders[0];
75579
75580         return headerCt.getHeaderIndex(firstHeader);
75581     },
75582
75583     getLastVisibleColumnIndex: function() {
75584         var headerCt   = this.getHeaderCt(),
75585             allColumns = headerCt.getGridColumns(),
75586             visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
75587             lastHeader = visHeaders[visHeaders.length - 1];
75588
75589         return headerCt.getHeaderIndex(lastHeader);
75590     },
75591
75592     getHeaderCt: function() {
75593         return this.headerCt;
75594     },
75595
75596     getPosition: function(record, header) {
75597         var me = this,
75598             store = me.store,
75599             gridCols = me.headerCt.getGridColumns();
75600
75601         return {
75602             row: store.indexOf(record),
75603             column: Ext.Array.indexOf(gridCols, header)
75604         };
75605     },
75606
75607     
75608     getRightGap: function(activeHeader) {
75609         var headerCt        = this.getHeaderCt(),
75610             headers         = headerCt.getGridColumns(),
75611             activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
75612             i               = activeHeaderIdx + 1,
75613             nextIdx;
75614
75615         for (; i <= headers.length; i++) {
75616             if (!headers[i].hidden) {
75617                 nextIdx = i;
75618                 break;
75619             }
75620         }
75621
75622         return nextIdx - activeHeaderIdx;
75623     },
75624
75625     beforeDestroy: function() {
75626         if (this.rendered) {
75627             this.el.removeAllListeners();
75628         }
75629         this.callParent(arguments);
75630     },
75631
75632     
75633     getLeftGap: function(activeHeader) {
75634         var headerCt        = this.getHeaderCt(),
75635             headers         = headerCt.getGridColumns(),
75636             activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
75637             i               = activeHeaderIdx - 1,
75638             prevIdx;
75639
75640         for (; i >= 0; i--) {
75641             if (!headers[i].hidden) {
75642                 prevIdx = i;
75643                 break;
75644             }
75645         }
75646
75647         return prevIdx - activeHeaderIdx;
75648     }
75649 });
75650
75651 Ext.define('Ext.grid.View', {
75652     extend: 'Ext.view.Table',
75653     alias: 'widget.gridview',
75654
75655     
75656     stripeRows: true,
75657     
75658     invalidateScrollerOnRefresh: true,
75659     
75660     
75661     scrollToTop : function(){
75662         if (this.rendered) {
75663             var section = this.ownerCt,
75664                 verticalScroller = section.verticalScroller;
75665                 
75666             if (verticalScroller) {
75667                 verticalScroller.scrollToTop();
75668             }
75669         }
75670     },
75671
75672     
75673     onAdd: function(ds, records, index) {
75674         this.callParent(arguments);
75675         this.doStripeRows(index);
75676     },
75677     
75678     
75679     onRemove: function(ds, records, index) {
75680         this.callParent(arguments);
75681         this.doStripeRows(index);
75682     },
75683     
75684     onUpdate: function(ds, record, operation) {
75685         var index = ds.indexOf(record);
75686         this.callParent(arguments);
75687         this.doStripeRows(index, index);
75688     },
75689     
75690     
75691     doStripeRows: function(startRow, endRow) {
75692         
75693         if (this.stripeRows) {
75694             var rows   = this.getNodes(startRow, endRow),
75695                 rowsLn = rows.length,
75696                 i      = 0,
75697                 row;
75698                 
75699             for (; i < rowsLn; i++) {
75700                 row = rows[i];
75701                 
75702                 row.className = row.className.replace(this.rowClsRe, ' ');
75703                 startRow++;
75704                 
75705                 if (startRow % 2 === 0) {
75706                     row.className += (' ' + this.altRowCls);
75707                 }
75708             }
75709         }
75710     },
75711     
75712     refresh: function(firstPass) {
75713         this.callParent(arguments);
75714         this.doStripeRows(0);
75715         
75716         var g = this.up('gridpanel');
75717         if (g && this.invalidateScrollerOnRefresh) {
75718             g.invalidateScroller();
75719         }
75720     }
75721 });
75722
75723
75724 Ext.define('Ext.grid.Panel', {
75725     extend: 'Ext.panel.Table',
75726     requires: ['Ext.grid.View'],
75727     alias: ['widget.gridpanel', 'widget.grid'],
75728     alternateClassName: ['Ext.list.ListView', 'Ext.ListView', 'Ext.grid.GridPanel'],
75729     viewType: 'gridview',
75730     
75731     lockable: false,
75732     
75733     
75734     
75735     normalCfgCopy: ['invalidateScrollerOnRefresh', 'verticalScroller', 'verticalScrollDock', 'verticalScrollerType', 'scroll'],
75736     lockedCfgCopy: ['invalidateScrollerOnRefresh'],
75737     
75738     
75739     
75740     initComponent: function() {
75741         var me = this;
75742
75743         if (me.columnLines) {
75744             me.setColumnLines(me.columnLines);
75745         }
75746         
75747         me.callParent();
75748     },
75749     
75750     setColumnLines: function(show) {
75751         var me = this,
75752             method = (show) ? 'addClsWithUI' : 'removeClsWithUI';
75753         
75754         me[method]('with-col-lines')
75755     }
75756 });
75757
75758
75759
75760
75761
75762
75763
75764
75765
75766 Ext.define('Ext.grid.RowEditor', {
75767     extend: 'Ext.form.Panel',
75768     requires: [
75769         'Ext.tip.ToolTip',
75770         'Ext.util.HashMap',
75771         'Ext.util.KeyNav'
75772     ],
75773
75774     saveBtnText  : 'Update',
75775     cancelBtnText: 'Cancel',
75776     errorsText: 'Errors',
75777     dirtyText: 'You need to commit or cancel your changes',
75778
75779     lastScrollLeft: 0,
75780     lastScrollTop: 0,
75781
75782     border: false,
75783     
75784     
75785     
75786     hideMode: 'offsets',
75787
75788     initComponent: function() {
75789         var me = this,
75790             form;
75791
75792         me.cls = Ext.baseCSSPrefix + 'grid-row-editor';
75793
75794         me.layout = {
75795             type: 'hbox',
75796             align: 'middle'
75797         };
75798
75799         
75800         
75801         me.columns = Ext.create('Ext.util.HashMap');
75802         me.columns.getKey = function(columnHeader) {
75803             var f;
75804             if (columnHeader.getEditor) {
75805                 f = columnHeader.getEditor();
75806                 if (f) {
75807                     return f.id;
75808                 }
75809             }
75810             return columnHeader.id;
75811         };
75812         me.mon(me.columns, {
75813             add: me.onFieldAdd,
75814             remove: me.onFieldRemove,
75815             replace: me.onFieldReplace,
75816             scope: me
75817         });
75818
75819         me.callParent(arguments);
75820
75821         if (me.fields) {
75822             me.setField(me.fields);
75823             delete me.fields;
75824         }
75825
75826         form = me.getForm();
75827         form.trackResetOnLoad = true;
75828     },
75829
75830     onFieldChange: function() {
75831         var me = this,
75832             form = me.getForm(),
75833             valid = form.isValid();
75834         if (me.errorSummary && me.isVisible()) {
75835             me[valid ? 'hideToolTip' : 'showToolTip']();
75836         }
75837         if (me.floatingButtons) {
75838             me.floatingButtons.child('#update').setDisabled(!valid);
75839         }
75840         me.isValid = valid;
75841     },
75842
75843     afterRender: function() {
75844         var me = this,
75845             plugin = me.editingPlugin;
75846
75847         me.callParent(arguments);
75848         me.mon(me.renderTo, 'scroll', me.onCtScroll, me, { buffer: 100 });
75849
75850         
75851         me.mon(me.el, {
75852             click: Ext.emptyFn,
75853             stopPropagation: true
75854         });
75855
75856         me.el.swallowEvent([
75857             'keypress',
75858             'keydown'
75859         ]);
75860
75861         me.keyNav = Ext.create('Ext.util.KeyNav', me.el, {
75862             enter: plugin.completeEdit,
75863             esc: plugin.onEscKey,
75864             scope: plugin
75865         });
75866
75867         me.mon(plugin.view, {
75868             beforerefresh: me.onBeforeViewRefresh,
75869             refresh: me.onViewRefresh,
75870             scope: me
75871         });
75872     },
75873
75874     onBeforeViewRefresh: function(view) {
75875         var me = this,
75876             viewDom = view.el.dom;
75877
75878         if (me.el.dom.parentNode === viewDom) {
75879             viewDom.removeChild(me.el.dom);
75880         }
75881     },
75882
75883     onViewRefresh: function(view) {
75884         var me = this,
75885             viewDom = view.el.dom,
75886             context = me.context,
75887             idx;
75888
75889         viewDom.appendChild(me.el.dom);
75890
75891         
75892         if (context && (idx = context.store.indexOf(context.record)) >= 0) {
75893             context.row = view.getNode(idx);
75894             me.reposition();
75895             if (me.tooltip && me.tooltip.isVisible()) {
75896                 me.tooltip.setTarget(context.row);
75897             }
75898         } else {
75899             me.editingPlugin.cancelEdit();
75900         }
75901     },
75902
75903     onCtScroll: function(e, target) {
75904         var me = this,
75905             scrollTop  = target.scrollTop,
75906             scrollLeft = target.scrollLeft;
75907
75908         if (scrollTop !== me.lastScrollTop) {
75909             me.lastScrollTop = scrollTop;
75910             if ((me.tooltip && me.tooltip.isVisible()) || me.hiddenTip) {
75911                 me.repositionTip();
75912             }
75913         }
75914         if (scrollLeft !== me.lastScrollLeft) {
75915             me.lastScrollLeft = scrollLeft;
75916             me.reposition();
75917         }
75918     },
75919
75920     onColumnAdd: function(column) {
75921         this.setField(column);
75922     },
75923
75924     onColumnRemove: function(column) {
75925         this.columns.remove(column);
75926     },
75927
75928     onColumnResize: function(column, width) {
75929         column.getEditor().setWidth(width - 2);
75930         if (this.isVisible()) {
75931             this.reposition();
75932         }
75933     },
75934
75935     onColumnHide: function(column) {
75936         column.getEditor().hide();
75937         if (this.isVisible()) {
75938             this.reposition();
75939         }
75940     },
75941
75942     onColumnShow: function(column) {
75943         var field = column.getEditor();
75944         field.setWidth(column.getWidth() - 2).show();
75945         if (this.isVisible()) {
75946             this.reposition();
75947         }
75948     },
75949
75950     onColumnMove: function(column, fromIdx, toIdx) {
75951         var field = column.getEditor();
75952         if (this.items.indexOf(field) != toIdx) {
75953             this.move(fromIdx, toIdx);
75954         }
75955     },
75956
75957     onFieldAdd: function(map, fieldId, column) {
75958         var me = this,
75959             colIdx = me.editingPlugin.grid.headerCt.getHeaderIndex(column),
75960             field = column.getEditor({ xtype: 'displayfield' });
75961
75962         me.insert(colIdx, field);
75963     },
75964
75965     onFieldRemove: function(map, fieldId, column) {
75966         var me = this,
75967             field = column.getEditor(),
75968             fieldEl = field.el;
75969         me.remove(field, false);
75970         if (fieldEl) {
75971             fieldEl.remove();
75972         }
75973     },
75974
75975     onFieldReplace: function(map, fieldId, column, oldColumn) {
75976         var me = this;
75977         me.onFieldRemove(map, fieldId, oldColumn);
75978     },
75979
75980     clearFields: function() {
75981         var me = this,
75982             map = me.columns;
75983         map.each(function(fieldId) {
75984             map.removeAtKey(fieldId);
75985         });
75986     },
75987
75988     getFloatingButtons: function() {
75989         var me = this,
75990             cssPrefix = Ext.baseCSSPrefix,
75991             btnsCss = cssPrefix + 'grid-row-editor-buttons',
75992             plugin = me.editingPlugin,
75993             btns;
75994
75995         if (!me.floatingButtons) {
75996             btns = me.floatingButtons = Ext.create('Ext.Container', {
75997                 renderTpl: [
75998                     '<div class="{baseCls}-ml"></div>',
75999                     '<div class="{baseCls}-mr"></div>',
76000                     '<div class="{baseCls}-bl"></div>',
76001                     '<div class="{baseCls}-br"></div>',
76002                     '<div class="{baseCls}-bc"></div>'
76003                 ],
76004
76005                 renderTo: me.el,
76006                 baseCls: btnsCss,
76007                 layout: {
76008                     type: 'hbox',
76009                     align: 'middle'
76010                 },
76011                 defaults: {
76012                     margins: '0 1 0 1'
76013                 },
76014                 items: [{
76015                     itemId: 'update',
76016                     flex: 1,
76017                     xtype: 'button',
76018                     handler: plugin.completeEdit,
76019                     scope: plugin,
76020                     text: me.saveBtnText,
76021                     disabled: !me.isValid
76022                 }, {
76023                     flex: 1,
76024                     xtype: 'button',
76025                     handler: plugin.cancelEdit,
76026                     scope: plugin,
76027                     text: me.cancelBtnText
76028                 }]
76029             });
76030
76031             
76032             me.mon(btns.el, {
76033                 
76034                 
76035                 mousedown: Ext.emptyFn,
76036                 click: Ext.emptyFn,
76037                 stopEvent: true
76038             });
76039         }
76040         return me.floatingButtons;
76041     },
76042
76043     reposition: function(animateConfig) {
76044         var me = this,
76045             context = me.context,
76046             row = context && Ext.get(context.row),
76047             btns = me.getFloatingButtons(),
76048             btnEl = btns.el,
76049             grid = me.editingPlugin.grid,
76050             viewEl = grid.view.el,
76051             scroller = grid.verticalScroller,
76052
76053             
76054             
76055             mainBodyWidth = grid.headerCt.getFullWidth(),
76056             scrollerWidth = grid.getWidth(),
76057
76058             
76059             
76060             width = Math.min(mainBodyWidth, scrollerWidth),
76061             scrollLeft = grid.view.el.dom.scrollLeft,
76062             btnWidth = btns.getWidth(),
76063             left = (width - btnWidth) / 2 + scrollLeft,
76064             y, rowH, newHeight,
76065
76066             invalidateScroller = function() {
76067                 if (scroller) {
76068                     scroller.invalidate();
76069                     btnEl.scrollIntoView(viewEl, false);
76070                 }
76071                 if (animateConfig && animateConfig.callback) {
76072                     animateConfig.callback.call(animateConfig.scope || me);
76073                 }
76074             };
76075
76076         
76077         if (row && Ext.isElement(row.dom)) {
76078             
76079             
76080             row.scrollIntoView(viewEl, false);
76081
76082             
76083             
76084             
76085             y = row.getXY()[1] - 5;
76086             rowH = row.getHeight();
76087             newHeight = rowH + 10;
76088
76089             
76090             
76091             
76092             
76093             if (Ext.isIE) {
76094                 newHeight += 2;
76095             }
76096
76097             
76098             if (me.getHeight() != newHeight) {
76099                 me.setHeight(newHeight);
76100                 me.el.setLeft(0);
76101             }
76102
76103             if (animateConfig) {
76104                 var animObj = {
76105                     to: {
76106                         y: y
76107                     },
76108                     duration: animateConfig.duration || 125,
76109                     listeners: {
76110                         afteranimate: function() {
76111                             invalidateScroller();
76112                             y = row.getXY()[1] - 5;
76113                             me.el.setY(y);
76114                         }
76115                     }
76116                 };
76117                 me.animate(animObj);
76118             } else {
76119                 me.el.setY(y);
76120                 invalidateScroller();
76121             }
76122         }
76123         if (me.getWidth() != mainBodyWidth) {
76124             me.setWidth(mainBodyWidth);
76125         }
76126         btnEl.setLeft(left);
76127     },
76128
76129     getEditor: function(fieldInfo) {
76130         var me = this;
76131
76132         if (Ext.isNumber(fieldInfo)) {
76133             
76134             
76135             
76136             return me.query('>[isFormField]')[fieldInfo];
76137         } else if (fieldInfo instanceof Ext.grid.column.Column) {
76138             return fieldInfo.getEditor();
76139         }
76140     },
76141
76142     removeField: function(field) {
76143         var me = this;
76144
76145         
76146         field = me.getEditor(field);
76147         me.mun(field, 'validitychange', me.onValidityChange, me);
76148
76149         
76150         
76151         me.columns.removeKey(field.id);
76152     },
76153
76154     setField: function(column) {
76155         var me = this,
76156             field;
76157
76158         if (Ext.isArray(column)) {
76159             Ext.Array.forEach(column, me.setField, me);
76160             return;
76161         }
76162
76163         
76164         field = column.getEditor(null, {
76165             xtype: 'displayfield',
76166             
76167             
76168             getModelData: function() {
76169                 return null;
76170             }
76171         });
76172         field.margins = '0 0 0 2';
76173         field.setWidth(column.getDesiredWidth() - 2);
76174         me.mon(field, 'change', me.onFieldChange, me);
76175
76176         
76177         
76178         me.columns.add(field.id, column);
76179         
76180         if (me.isVisible() && me.context) {
76181             me.renderColumnData(field, me.context.record);
76182         }
76183     },
76184
76185     loadRecord: function(record) {
76186         var me = this,
76187             form = me.getForm();
76188         form.loadRecord(record);
76189         if (form.isValid()) {
76190             me.hideToolTip();
76191         } else {
76192             me.showToolTip();
76193         }
76194
76195         
76196         Ext.Array.forEach(me.query('>displayfield'), function(field) {
76197             me.renderColumnData(field, record);
76198         }, me);
76199     },
76200
76201     renderColumnData: function(field, record) {
76202         var me = this,
76203             grid = me.editingPlugin.grid,
76204             headerCt = grid.headerCt,
76205             view = grid.view,
76206             store = view.store,
76207             column = me.columns.get(field.id),
76208             value = record.get(column.dataIndex);
76209
76210         
76211         if (column.renderer) {
76212             var metaData = { tdCls: '', style: '' },
76213                 rowIdx = store.indexOf(record),
76214                 colIdx = headerCt.getHeaderIndex(column);
76215
76216             value = column.renderer.call(
76217                 column.scope || headerCt.ownerCt,
76218                 value,
76219                 metaData,
76220                 record,
76221                 rowIdx,
76222                 colIdx,
76223                 store,
76224                 view
76225             );
76226         }
76227
76228         field.setRawValue(value);
76229         field.resetOriginalValue();
76230     },
76231
76232     beforeEdit: function() {
76233         var me = this;
76234
76235         if (me.isVisible() && !me.autoCancel && me.isDirty()) {
76236             me.showToolTip();
76237             return false;
76238         }
76239     },
76240
76241     
76242     startEdit: function(record, columnHeader) {
76243         var me = this,
76244             grid = me.editingPlugin.grid,
76245             view = grid.getView(),
76246             store = grid.store,
76247             context = me.context = Ext.apply(me.editingPlugin.context, {
76248                 view: grid.getView(),
76249                 store: store
76250             });
76251
76252         
76253         context.grid.getSelectionModel().select(record);
76254
76255         
76256         me.loadRecord(record);
76257
76258         if (!me.isVisible()) {
76259             me.show();
76260             me.focusContextCell();
76261         } else {
76262             me.reposition({
76263                 callback: this.focusContextCell
76264             });
76265         }
76266     },
76267
76268     
76269     focusContextCell: function() {
76270         var field = this.getEditor(this.context.colIdx);
76271         if (field && field.focus) {
76272             field.focus();
76273         }
76274     },
76275
76276     cancelEdit: function() {
76277         var me = this,
76278             form = me.getForm();
76279
76280         me.hide();
76281         form.clearInvalid();
76282         form.reset();
76283     },
76284
76285     completeEdit: function() {
76286         var me = this,
76287             form = me.getForm();
76288
76289         if (!form.isValid()) {
76290             return;
76291         }
76292
76293         form.updateRecord(me.context.record);
76294         me.hide();
76295         return true;
76296     },
76297
76298     onShow: function() {
76299         var me = this;
76300         me.callParent(arguments);
76301         me.reposition();
76302     },
76303
76304     onHide: function() {
76305         var me = this;
76306         me.callParent(arguments);
76307         me.hideToolTip();
76308         me.invalidateScroller();
76309         if (me.context) {
76310             me.context.view.focus();
76311             me.context = null;
76312         }
76313     },
76314
76315     isDirty: function() {
76316         var me = this,
76317             form = me.getForm();
76318         return form.isDirty();
76319     },
76320
76321     getToolTip: function() {
76322         var me = this,
76323             tip;
76324
76325         if (!me.tooltip) {
76326             tip = me.tooltip = Ext.createWidget('tooltip', {
76327                 cls: Ext.baseCSSPrefix + 'grid-row-editor-errors',
76328                 title: me.errorsText,
76329                 autoHide: false,
76330                 closable: true,
76331                 closeAction: 'disable',
76332                 anchor: 'left'
76333             });
76334         }
76335         return me.tooltip;
76336     },
76337
76338     hideToolTip: function() {
76339         var me = this,
76340             tip = me.getToolTip();
76341         if (tip.rendered) {
76342             tip.disable();
76343         }
76344         me.hiddenTip = false;
76345     },
76346
76347     showToolTip: function() {
76348         var me = this,
76349             tip = me.getToolTip(),
76350             context = me.context,
76351             row = Ext.get(context.row),
76352             viewEl = context.grid.view.el;
76353
76354         tip.setTarget(row);
76355         tip.showAt([-10000, -10000]);
76356         tip.body.update(me.getErrors());
76357         tip.mouseOffset = [viewEl.getWidth() - row.getWidth() + me.lastScrollLeft + 15, 0];
76358         me.repositionTip();
76359         tip.doLayout();
76360         tip.enable();
76361     },
76362
76363     repositionTip: function() {
76364         var me = this,
76365             tip = me.getToolTip(),
76366             context = me.context,
76367             row = Ext.get(context.row),
76368             viewEl = context.grid.view.el,
76369             viewHeight = viewEl.getHeight(),
76370             viewTop = me.lastScrollTop,
76371             viewBottom = viewTop + viewHeight,
76372             rowHeight = row.getHeight(),
76373             rowTop = row.dom.offsetTop,
76374             rowBottom = rowTop + rowHeight;
76375
76376         if (rowBottom > viewTop && rowTop < viewBottom) {
76377             tip.show();
76378             me.hiddenTip = false;
76379         } else {
76380             tip.hide();
76381             me.hiddenTip = true;
76382         }
76383     },
76384
76385     getErrors: function() {
76386         var me = this,
76387             dirtyText = !me.autoCancel && me.isDirty() ? me.dirtyText + '<br />' : '',
76388             errors = [];
76389
76390         Ext.Array.forEach(me.query('>[isFormField]'), function(field) {
76391             errors = errors.concat(
76392                 Ext.Array.map(field.getErrors(), function(e) {
76393                     return '<li>' + e + '</li>';
76394                 })
76395             );
76396         }, me);
76397
76398         return dirtyText + '<ul>' + errors.join('') + '</ul>';
76399     },
76400
76401     invalidateScroller: function() {
76402         var me = this,
76403             context = me.context,
76404             scroller = context.grid.verticalScroller;
76405
76406         if (scroller) {
76407             scroller.invalidate();
76408         }
76409     }
76410 });
76411
76412 Ext.define('Ext.grid.header.Container', {
76413     extend: 'Ext.container.Container',
76414     uses: [
76415         'Ext.grid.ColumnLayout',
76416         'Ext.grid.column.Column',
76417         'Ext.menu.Menu',
76418         'Ext.menu.CheckItem',
76419         'Ext.menu.Separator',
76420         'Ext.grid.plugin.HeaderResizer',
76421         'Ext.grid.plugin.HeaderReorderer'
76422     ],
76423     border: true,
76424
76425     alias: 'widget.headercontainer',
76426
76427     baseCls: Ext.baseCSSPrefix + 'grid-header-ct',
76428     dock: 'top',
76429
76430     
76431     weight: 100,
76432     defaultType: 'gridcolumn',
76433     
76434     defaultWidth: 100,
76435
76436
76437     sortAscText: 'Sort Ascending',
76438     sortDescText: 'Sort Descending',
76439     sortClearText: 'Clear Sort',
76440     columnsText: 'Columns',
76441
76442     lastHeaderCls: Ext.baseCSSPrefix + 'column-header-last',
76443     firstHeaderCls: Ext.baseCSSPrefix + 'column-header-first',
76444     headerOpenCls: Ext.baseCSSPrefix + 'column-header-open',
76445
76446     
76447     triStateSort: false,
76448
76449     ddLock: false,
76450
76451     dragging: false,
76452
76453     
76454
76455     
76456     sortable: true,
76457     
76458     initComponent: function() {
76459         var me = this;
76460         
76461         me.headerCounter = 0;
76462         me.plugins = me.plugins || [];
76463
76464         
76465         
76466
76467         
76468         
76469         if (!me.isHeader) {
76470             me.resizer   = Ext.create('Ext.grid.plugin.HeaderResizer');
76471             me.reorderer = Ext.create('Ext.grid.plugin.HeaderReorderer');
76472             if (!me.enableColumnResize) {
76473                 me.resizer.disable();
76474             } 
76475             if (!me.enableColumnMove) {
76476                 me.reorderer.disable();
76477             }
76478             me.plugins.push(me.reorderer, me.resizer);
76479         }
76480
76481         
76482         if (me.isHeader && !me.items) {
76483             me.layout = 'auto';
76484         }
76485         
76486         else {
76487             me.layout = {
76488                 type: 'gridcolumn',
76489                 availableSpaceOffset: me.availableSpaceOffset,
76490                 align: 'stretchmax',
76491                 resetStretch: true
76492             };
76493         }
76494         me.defaults = me.defaults || {};
76495         Ext.applyIf(me.defaults, {
76496             width: me.defaultWidth,
76497             triStateSort: me.triStateSort,
76498             sortable: me.sortable
76499         });
76500         me.callParent();
76501         me.addEvents(
76502             
76503             'columnresize',
76504
76505             
76506             'headerclick',
76507
76508             
76509             'headertriggerclick',
76510
76511             
76512             'columnmove',
76513             
76514             'columnhide',
76515             
76516             'columnshow',
76517             
76518             'sortchange',
76519             
76520             'menucreate'
76521         );
76522     },
76523
76524     onDestroy: function() {
76525         Ext.destroy(this.resizer, this.reorderer);
76526         this.callParent();
76527     },
76528
76529     
76530     
76531     
76532     onAdd: function(c) {
76533         var me = this;
76534         if (!c.headerId) {
76535             c.headerId = 'h' + (++me.headerCounter);
76536         }
76537         me.callParent(arguments);
76538         me.purgeCache();
76539     },
76540
76541     
76542     
76543     
76544     onRemove: function(c) {
76545         var me = this;
76546         me.callParent(arguments);
76547         me.purgeCache();
76548     },
76549
76550     afterRender: function() {
76551         this.callParent();
76552         var store   = this.up('[store]').store,
76553             sorters = store.sorters,
76554             first   = sorters.first(),
76555             hd;
76556
76557         if (first) {
76558             hd = this.down('gridcolumn[dataIndex=' + first.property  +']');
76559             if (hd) {
76560                 hd.setSortState(first.direction, false, true);
76561             }
76562         }
76563     },
76564
76565     afterLayout: function() {
76566         if (!this.isHeader) {
76567             var me = this,
76568                 topHeaders = me.query('>gridcolumn:not([hidden])'),
76569                 viewEl,
76570                 firstHeaderEl,
76571                 lastHeaderEl;
76572
76573             me.callParent(arguments);
76574
76575             if (topHeaders.length) {
76576                 firstHeaderEl = topHeaders[0].el;
76577                 if (firstHeaderEl !== me.pastFirstHeaderEl) {
76578                     if (me.pastFirstHeaderEl) {
76579                         me.pastFirstHeaderEl.removeCls(me.firstHeaderCls);
76580                     }
76581                     firstHeaderEl.addCls(me.firstHeaderCls);
76582                     me.pastFirstHeaderEl = firstHeaderEl;
76583                 }
76584                 
76585                 lastHeaderEl = topHeaders[topHeaders.length - 1].el;
76586                 if (lastHeaderEl !== me.pastLastHeaderEl) {
76587                     if (me.pastLastHeaderEl) {
76588                         me.pastLastHeaderEl.removeCls(me.lastHeaderCls);
76589                     }
76590                     lastHeaderEl.addCls(me.lastHeaderCls);
76591                     me.pastLastHeaderEl = lastHeaderEl
76592                 }
76593             }
76594         }
76595         
76596     },
76597
76598     onHeaderShow: function(header) {
76599         
76600         var me = this,
76601             gridSection = me.ownerCt,
76602             menu = me.getMenu(),
76603             topItems, topItemsVisible,
76604             colCheckItem,
76605             itemToEnable,
76606             len, i;
76607
76608         if (menu) {
76609
76610             colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
76611             if (colCheckItem) {
76612                 colCheckItem.setChecked(true, true);
76613             }
76614
76615             
76616             topItems = menu.query('#columnItem>menucheckitem[checked]');
76617             topItemsVisible = topItems.length;
76618             if ((me.getVisibleGridColumns().length > 1) && me.disabledMenuItems && me.disabledMenuItems.length) {
76619                 if (topItemsVisible == 1) {
76620                     Ext.Array.remove(me.disabledMenuItems, topItems[0]);
76621                 }
76622                 for (i = 0, len = me.disabledMenuItems.length; i < len; i++) {
76623                     itemToEnable = me.disabledMenuItems[i];
76624                     if (!itemToEnable.isDestroyed) {
76625                         itemToEnable[itemToEnable.menu ? 'enableCheckChange' : 'enable']();
76626                     }
76627                 }
76628                 if (topItemsVisible == 1) {
76629                     me.disabledMenuItems = topItems;
76630                 } else {
76631                     me.disabledMenuItems = [];
76632                 }
76633             }
76634         }
76635
76636         
76637         
76638         if (!header.isGroupHeader) {
76639             if (me.view) {
76640                 me.view.onHeaderShow(me, header, true);
76641             }
76642             if (gridSection) {
76643                 gridSection.onHeaderShow(me, header);
76644             }
76645         }
76646         me.fireEvent('columnshow', me, header);
76647
76648         
76649         me.doLayout();
76650     },
76651
76652     onHeaderHide: function(header, suppressLayout) {
76653         
76654         var me = this,
76655             gridSection = me.ownerCt,
76656             menu = me.getMenu(),
76657             colCheckItem;
76658
76659         if (menu) {
76660
76661             
76662             colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
76663             if (colCheckItem) {
76664                 colCheckItem.setChecked(false, true);
76665             }
76666             me.setDisabledItems();
76667         }
76668
76669         
76670         if (!header.isGroupHeader) {
76671             if (me.view) {
76672                 me.view.onHeaderHide(me, header, true);
76673             }
76674             if (gridSection) {
76675                 gridSection.onHeaderHide(me, header);
76676             }
76677
76678             
76679             if (!suppressLayout) {
76680                 me.doLayout();
76681             }
76682         }
76683         me.fireEvent('columnhide', me, header);
76684     },
76685
76686     setDisabledItems: function(){
76687         var me = this,
76688             menu = me.getMenu(),
76689             i = 0,
76690             len,
76691             itemsToDisable,
76692             itemToDisable;
76693
76694         
76695         itemsToDisable = menu.query('#columnItem>menucheckitem[checked]');
76696         if ((itemsToDisable.length === 1)) {
76697             if (!me.disabledMenuItems) {
76698                 me.disabledMenuItems = [];
76699             }
76700
76701             
76702             if ((me.getVisibleGridColumns().length === 1) && itemsToDisable[0].menu) {
76703                 itemsToDisable = itemsToDisable.concat(itemsToDisable[0].menu.query('menucheckitem[checked]'));
76704             }
76705
76706             len = itemsToDisable.length;
76707             
76708             for (i = 0; i < len; i++) {
76709                 itemToDisable = itemsToDisable[i];
76710                 if (!Ext.Array.contains(me.disabledMenuItems, itemToDisable)) {
76711                     itemToDisable[itemToDisable.menu ? 'disableCheckChange' : 'disable']();
76712                     me.disabledMenuItems.push(itemToDisable);
76713                 }
76714             }
76715         }
76716     },
76717
76718     
76719     tempLock: function() {
76720         this.ddLock = true;
76721         Ext.Function.defer(function() {
76722             this.ddLock = false;
76723         }, 200, this);
76724     },
76725
76726     onHeaderResize: function(header, w, suppressFocus) {
76727         this.tempLock();
76728         if (this.view && this.view.rendered) {
76729             this.view.onHeaderResize(header, w, suppressFocus);
76730         }
76731         this.fireEvent('columnresize', this, header, w);
76732     },
76733
76734     onHeaderClick: function(header, e, t) {
76735         this.fireEvent("headerclick", this, header, e, t);
76736     },
76737
76738     onHeaderTriggerClick: function(header, e, t) {
76739         
76740         if (this.fireEvent("headertriggerclick", this, header, e, t) !== false) {
76741             this.showMenuBy(t, header);
76742         }
76743     },
76744
76745     showMenuBy: function(t, header) {
76746         var menu = this.getMenu(),
76747             ascItem  = menu.down('#ascItem'),
76748             descItem = menu.down('#descItem'),
76749             sortableMth;
76750
76751         menu.activeHeader = menu.ownerCt = header;
76752         menu.setFloatParent(header);
76753         
76754         header.titleContainer.addCls(this.headerOpenCls);
76755
76756         
76757         sortableMth = header.sortable ? 'enable' : 'disable';
76758         if (ascItem) {
76759             ascItem[sortableMth]();
76760         }
76761         if (descItem) {
76762             descItem[sortableMth]();
76763         }
76764         menu.showBy(t);
76765     },
76766
76767     
76768     onMenuDeactivate: function() {
76769         var menu = this.getMenu();
76770         
76771         menu.activeHeader.titleContainer.removeCls(this.headerOpenCls);
76772     },
76773
76774     moveHeader: function(fromIdx, toIdx) {
76775
76776         
76777         this.tempLock();
76778         this.onHeaderMoved(this.move(fromIdx, toIdx), fromIdx, toIdx);
76779     },
76780
76781     purgeCache: function() {
76782         var me = this;
76783         
76784         delete me.gridDataColumns;
76785
76786         
76787         if (me.menu) {
76788             me.menu.destroy();
76789             delete me.menu;
76790         }
76791     },
76792
76793     onHeaderMoved: function(header, fromIdx, toIdx) {
76794         var me = this,
76795             gridSection = me.ownerCt;
76796
76797         if (gridSection) {
76798             gridSection.onHeaderMove(me, header, fromIdx, toIdx);
76799         }
76800         me.fireEvent("columnmove", me, header, fromIdx, toIdx);
76801     },
76802
76803     
76804     getMenu: function() {
76805         var me = this;
76806
76807         if (!me.menu) {
76808             me.menu = Ext.create('Ext.menu.Menu', {
76809                 items: me.getMenuItems(),
76810                 listeners: {
76811                     deactivate: me.onMenuDeactivate,
76812                     scope: me
76813                 }
76814             });
76815             me.setDisabledItems();
76816             me.fireEvent('menucreate', me, me.menu);
76817         }
76818         return me.menu;
76819     },
76820
76821     
76822     getMenuItems: function() {
76823         var me = this,
76824             menuItems = [{
76825                 itemId: 'columnItem',
76826                 text: me.columnsText,
76827                 cls: Ext.baseCSSPrefix + 'cols-icon',
76828                 menu: me.getColumnMenu(me)
76829             }];
76830
76831         if (me.sortable) {
76832             menuItems.unshift({
76833                 itemId: 'ascItem',
76834                 text: me.sortAscText,
76835                 cls: 'xg-hmenu-sort-asc',
76836                 handler: me.onSortAscClick,
76837                 scope: me
76838             },{
76839                 itemId: 'descItem',
76840                 text: me.sortDescText,
76841                 cls: 'xg-hmenu-sort-desc',
76842                 handler: me.onSortDescClick,
76843                 scope: me
76844             },'-');
76845         }
76846         return menuItems;
76847     },
76848
76849     
76850     onSortAscClick: function() {
76851         var menu = this.getMenu(),
76852             activeHeader = menu.activeHeader;
76853
76854         activeHeader.setSortState('ASC');
76855     },
76856
76857     
76858     onSortDescClick: function() {
76859         var menu = this.getMenu(),
76860             activeHeader = menu.activeHeader;
76861
76862         activeHeader.setSortState('DESC');
76863     },
76864
76865     
76866     getColumnMenu: function(headerContainer) {
76867         var menuItems = [],
76868             i = 0,
76869             item,
76870             items = headerContainer.query('>gridcolumn[hideable]'),
76871             itemsLn = items.length,
76872             menuItem;
76873
76874         for (; i < itemsLn; i++) {
76875             item = items[i];
76876             menuItem = Ext.create('Ext.menu.CheckItem', {
76877                 text: item.text,
76878                 checked: !item.hidden,
76879                 hideOnClick: false,
76880                 headerId: item.id,
76881                 menu: item.isGroupHeader ? this.getColumnMenu(item) : undefined,
76882                 checkHandler: this.onColumnCheckChange,
76883                 scope: this
76884             });
76885             if (itemsLn === 1) {
76886                 menuItem.disabled = true;
76887             }
76888             menuItems.push(menuItem);
76889
76890             
76891             
76892             item.on({
76893                 destroy: Ext.Function.bind(menuItem.destroy, menuItem)
76894             });
76895         }
76896         return menuItems;
76897     },
76898
76899     onColumnCheckChange: function(checkItem, checked) {
76900         var header = Ext.getCmp(checkItem.headerId);
76901         header[checked ? 'show' : 'hide']();
76902     },
76903
76904     
76905     getColumnsForTpl: function(flushCache) {
76906         var cols    = [],
76907             headers   = this.getGridColumns(flushCache),
76908             headersLn = headers.length,
76909             i = 0,
76910             header;
76911
76912         for (; i < headersLn; i++) {
76913             header = headers[i];
76914             cols.push({
76915                 dataIndex: header.dataIndex,
76916                 align: header.align,
76917                 width: header.hidden ? 0 : header.getDesiredWidth(),
76918                 id: header.id,
76919                 cls: header.tdCls,
76920                 columnId: header.getItemId()
76921             });
76922         }
76923         return cols;
76924     },
76925
76926     
76927     getColumnCount: function() {
76928         return this.getGridColumns().length;
76929     },
76930
76931     
76932     getFullWidth: function(flushCache) {
76933         var fullWidth = 0,
76934             headers     = this.getVisibleGridColumns(flushCache),
76935             headersLn   = headers.length,
76936             i         = 0;
76937
76938         for (; i < headersLn; i++) {
76939             if (!isNaN(headers[i].width)) {
76940                 
76941                 if (headers[i].getDesiredWidth) {
76942                     fullWidth += headers[i].getDesiredWidth();
76943                 
76944                 } else {
76945                     fullWidth += headers[i].getWidth();
76946                 }
76947             }
76948         }
76949         return fullWidth;
76950     },
76951
76952     
76953     clearOtherSortStates: function(activeHeader) {
76954         var headers   = this.getGridColumns(),
76955             headersLn = headers.length,
76956             i         = 0,
76957             oldSortState;
76958
76959         for (; i < headersLn; i++) {
76960             if (headers[i] !== activeHeader) {
76961                 oldSortState = headers[i].sortState;
76962                 
76963                 headers[i].setSortState(null, true);
76964                 
76965                 
76966                 
76967             }
76968         }
76969     },
76970
76971     
76972     getVisibleGridColumns: function(refreshCache) {
76973         return Ext.ComponentQuery.query(':not([hidden])', this.getGridColumns(refreshCache));
76974     },
76975
76976     
76977     getGridColumns: function(refreshCache) {
76978         var me = this,
76979             result = refreshCache ? null : me.gridDataColumns;
76980
76981         
76982         if (!result) {
76983             me.gridDataColumns = result = [];
76984             me.cascade(function(c) {
76985                 if ((c !== me) && !c.isGroupHeader) {
76986                     result.push(c);
76987                 }
76988             });
76989         }
76990
76991         return result;
76992     },
76993
76994     
76995     getHeaderIndex: function(header) {
76996         var columns = this.getGridColumns();
76997         return Ext.Array.indexOf(columns, header);
76998     },
76999
77000     
77001     getHeaderAtIndex: function(index) {
77002         var columns = this.getGridColumns();
77003         return columns[index];
77004     },
77005
77006     
77007     prepareData: function(data, rowIdx, record, view, panel) {
77008         var obj       = {},
77009             headers   = this.gridDataColumns || this.getGridColumns(),
77010             headersLn = headers.length,
77011             colIdx    = 0,
77012             header,
77013             headerId,
77014             renderer,
77015             value,
77016             metaData,
77017             store = panel.store;
77018
77019         for (; colIdx < headersLn; colIdx++) {
77020             metaData = {
77021                 tdCls: '',
77022                 style: ''
77023             };
77024             header = headers[colIdx];
77025             headerId = header.id;
77026             renderer = header.renderer;
77027             value = data[header.dataIndex];
77028
77029             
77030             
77031             if (typeof renderer === "string") {
77032                 header.renderer = renderer = Ext.util.Format[renderer];
77033             }
77034             
77035             if (typeof renderer === "function") {
77036                 value = renderer.call(
77037                     header.scope || this.ownerCt,
77038                     value,
77039                     
77040                     
77041                     metaData,
77042                     record,
77043                     rowIdx,
77044                     colIdx,
77045                     store,
77046                     view
77047                 );
77048             }
77049
77050             if (metaData.css) {
77051                 
77052                 obj.cssWarning = true;
77053                 metaData.tdCls = metaData.css;
77054                 delete metaData.css;
77055             }
77056             
77057             obj[headerId+'-modified'] = record.modified[header.dataIndex] ? Ext.baseCSSPrefix + 'grid-dirty-cell' : '';
77058             obj[headerId+'-tdCls'] = metaData.tdCls;
77059             obj[headerId+'-tdAttr'] = metaData.tdAttr;
77060             obj[headerId+'-style'] = metaData.style;
77061             if (value === undefined || value === null || value === '') {
77062                 value = '&#160;';
77063             }
77064             obj[headerId] = value;
77065         }
77066         return obj;
77067     },
77068
77069     expandToFit: function(header) {
77070         if (this.view) {
77071             this.view.expandToFit(header);
77072         }
77073     }
77074 });
77075
77076
77077 Ext.define('Ext.grid.column.Column', {
77078     extend: 'Ext.grid.header.Container',
77079     alias: 'widget.gridcolumn',
77080     requires: ['Ext.util.KeyNav'],
77081     alternateClassName: 'Ext.grid.Column',
77082
77083     baseCls: Ext.baseCSSPrefix + 'column-header ' + Ext.baseCSSPrefix + 'unselectable',
77084
77085     
77086     hoverCls: Ext.baseCSSPrefix + 'column-header-over',
77087
77088     handleWidth: 5,
77089
77090     sortState: null,
77091
77092     possibleSortStates: ['ASC', 'DESC'],
77093
77094     renderTpl:
77095         '<div class="' + Ext.baseCSSPrefix + 'column-header-inner">' +
77096             '<span class="' + Ext.baseCSSPrefix + 'column-header-text">' +
77097                 '{text}' +
77098             '</span>' +
77099             '<tpl if="!values.menuDisabled"><div class="' + Ext.baseCSSPrefix + 'column-header-trigger"></div></tpl>' +
77100         '</div>',
77101
77102     
77103
77104     
77105     dataIndex: null,
77106
77107     
77108     text: '&#160',
77109
77110     
77111     sortable: true,
77112     
77113     
77114      
77115     
77116     hideable: true,
77117
77118     
77119     menuDisabled: false,
77120
77121     
77122     renderer: false,
77123
77124     
77125     align: 'left',
77126
77127     
77128     draggable: true,
77129
77130     
77131     
77132     initDraggable: Ext.emptyFn,
77133
77134     
77135
77136     
77137
77138     
77139
77140     
77141     isHeader: true,
77142
77143     initComponent: function() {
77144         var me = this,
77145             i,
77146             len;
77147         
77148         if (Ext.isDefined(me.header)) {
77149             me.text = me.header;
77150             delete me.header;
77151         }
77152
77153         
77154         
77155         
77156         if (me.flex) {
77157             me.minWidth = me.minWidth || Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
77158         }
77159         
77160         
77161         else {
77162             me.minWidth = me.width;
77163         }
77164
77165         if (!me.triStateSort) {
77166             me.possibleSortStates.length = 2;
77167         }
77168
77169         
77170         if (Ext.isDefined(me.columns)) {
77171             me.isGroupHeader = true;
77172
77173             if (me.dataIndex) {
77174                 Ext.Error.raise('Ext.grid.column.Column: Group header may not accept a dataIndex');
77175             }
77176             if ((me.width && me.width !== Ext.grid.header.Container.prototype.defaultWidth) || me.flex) {
77177                 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.');
77178             }
77179
77180             
77181             me.items = me.columns;
77182             delete me.columns;
77183             delete me.flex;
77184             me.width = 0;
77185
77186             
77187             for (i = 0, len = me.items.length; i < len; i++) {
77188                 me.width += me.items[i].width || Ext.grid.header.Container.prototype.defaultWidth;
77189                 if (me.items[i].flex) {
77190                     Ext.Error.raise('Ext.grid.column.Column: items of a grouped header do not support flexed values. Each item must explicitly define its width.');
77191                 }
77192             }
77193             me.minWidth = me.width;
77194
77195             me.cls = (me.cls||'') + ' ' + Ext.baseCSSPrefix + 'group-header';
77196             me.sortable = false;
77197             me.fixed = true;
77198             me.align = 'center';
77199         }
77200
77201         Ext.applyIf(me.renderSelectors, {
77202             titleContainer: '.' + Ext.baseCSSPrefix + 'column-header-inner',
77203             triggerEl: '.' + Ext.baseCSSPrefix + 'column-header-trigger',
77204             textEl: '.' + Ext.baseCSSPrefix + 'column-header-text'
77205         });
77206
77207         
77208         me.callParent(arguments);
77209     },
77210
77211     onAdd: function(childHeader) {
77212         childHeader.isSubHeader = true;
77213         childHeader.addCls(Ext.baseCSSPrefix + 'group-sub-header');
77214     },
77215
77216     onRemove: function(childHeader) {
77217         childHeader.isSubHeader = false;
77218         childHeader.removeCls(Ext.baseCSSPrefix + 'group-sub-header');
77219     },
77220
77221     initRenderData: function() {
77222         var me = this;
77223         
77224         Ext.applyIf(me.renderData, {
77225             text: me.text,
77226             menuDisabled: me.menuDisabled
77227         });
77228         return me.callParent(arguments);
77229     },
77230
77231     
77232     setText: function(text) {
77233         this.text = text;
77234         if (this.rendered) {
77235             this.textEl.update(text);
77236         } 
77237     },
77238
77239     
77240     
77241     getOwnerHeaderCt: function() {
77242         return this.up(':not([isHeader])');
77243     },
77244
77245     
77246     getIndex: function() {
77247         return this.isGroupColumn ? false : this.getOwnerHeaderCt().getHeaderIndex(this);
77248     },
77249
77250     afterRender: function() {
77251         var me = this,
77252             el = me.el;
77253
77254         me.callParent(arguments);
77255
77256         el.addCls(Ext.baseCSSPrefix + 'column-header-align-' + me.align).addClsOnOver(me.overCls);
77257
77258         me.mon(el, {
77259             click:     me.onElClick,
77260             dblclick:  me.onElDblClick,
77261             scope:     me
77262         });
77263         
77264         
77265         
77266         if (!Ext.isIE8 || !Ext.isStrict) {
77267             me.mon(me.getFocusEl(), {
77268                 focus: me.onTitleMouseOver,
77269                 blur: me.onTitleMouseOut,
77270                 scope: me
77271             });
77272         }
77273
77274         me.mon(me.titleContainer, {
77275             mouseenter:  me.onTitleMouseOver,
77276             mouseleave:  me.onTitleMouseOut,
77277             scope:      me
77278         });
77279
77280         me.keyNav = Ext.create('Ext.util.KeyNav', el, {
77281             enter: me.onEnterKey,
77282             down: me.onDownKey,
77283             scope: me
77284         });
77285     },
77286
77287     setSize: function(width, height) {
77288         var me = this,
77289             headerCt = me.ownerCt,
77290             ownerHeaderCt = me.getOwnerHeaderCt(),
77291             siblings,
77292             len, i,
77293             oldWidth = me.getWidth(),
77294             newWidth = 0;
77295
77296         if (width !== oldWidth) {
77297
77298             
77299             if (headerCt.isGroupHeader) {
77300
77301                 siblings = headerCt.items.items;
77302                 len = siblings.length;
77303
77304                 
77305                 if (siblings[len - 1].rendered) {
77306
77307                     for (i = 0; i < len; i++) {
77308                         newWidth += (siblings[i] === me) ? width : siblings[i].getWidth();
77309                     }
77310                     headerCt.minWidth = newWidth;
77311                     headerCt.setWidth(newWidth);
77312                 }
77313             }
77314             me.callParent(arguments);
77315         }
77316     },
77317
77318     afterComponentLayout: function(width, height) {
77319         var me = this,
77320             ownerHeaderCt = this.getOwnerHeaderCt();
77321
77322         me.callParent(arguments);
77323
77324         
77325         
77326         
77327         if (width && !me.isGroupHeader && ownerHeaderCt) {
77328             ownerHeaderCt.onHeaderResize(me, width, true);
77329         }
77330     },
77331
77332     
77333     
77334     setPadding: function() {
77335         var me = this,
77336             headerHeight,
77337             lineHeight = parseInt(me.textEl.getStyle('line-height'), 10);
77338
77339         
77340         if (!me.isGroupHeader) {
77341             headerHeight = me.el.getViewSize().height;
77342             if (me.titleContainer.getHeight() < headerHeight) {
77343                 me.titleContainer.dom.style.height = headerHeight + 'px';
77344             }
77345         }
77346         headerHeight = me.titleContainer.getViewSize().height;
77347
77348         
77349         if (lineHeight) {
77350             me.titleContainer.setStyle({
77351                 paddingTop: Math.max(((headerHeight - lineHeight) / 2), 0) + 'px'
77352             });
77353         }
77354
77355         
77356         if (Ext.isIE && me.triggerEl) {
77357             me.triggerEl.setHeight(headerHeight);
77358         }
77359     },
77360
77361     onDestroy: function() {
77362         var me = this;
77363         Ext.destroy(me.keyNav);
77364         delete me.keyNav;
77365         me.callParent(arguments);
77366     },
77367
77368     onTitleMouseOver: function() {
77369         this.titleContainer.addCls(this.hoverCls);
77370     },
77371
77372     onTitleMouseOut: function() {
77373         this.titleContainer.removeCls(this.hoverCls);
77374     },
77375
77376     onDownKey: function(e) {
77377         if (this.triggerEl) {
77378             this.onElClick(e, this.triggerEl.dom || this.el.dom);
77379         }
77380     },
77381
77382     onEnterKey: function(e) {
77383         this.onElClick(e, this.el.dom);
77384     },
77385
77386     
77387     onElDblClick: function(e, t) {
77388         var me = this,
77389             ownerCt = me.ownerCt;
77390         if (ownerCt && Ext.Array.indexOf(ownerCt.items, me) !== 0 && me.isOnLeftEdge(e) ) {
77391             ownerCt.expandToFit(me.previousSibling('gridcolumn'));
77392         }
77393     },
77394
77395     onElClick: function(e, t) {
77396
77397         
77398         var me = this,
77399             ownerHeaderCt = me.getOwnerHeaderCt();
77400
77401         if (ownerHeaderCt && !ownerHeaderCt.ddLock) {
77402             
77403             
77404             if (me.triggerEl && (e.target === me.triggerEl.dom || t === me.triggerEl.dom || e.within(me.triggerEl))) {
77405                 ownerHeaderCt.onHeaderTriggerClick(me, e, t);
77406             
77407             } else if (e.getKey() || (!me.isOnLeftEdge(e) && !me.isOnRightEdge(e))) {
77408                 me.toggleSortState();
77409                 ownerHeaderCt.onHeaderClick(me, e, t);
77410             }
77411         }
77412     },
77413
77414     
77415     processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
77416         return this.fireEvent.apply(this, arguments);
77417     },
77418
77419     toggleSortState: function() {
77420         var me = this,
77421             idx,
77422             nextIdx;
77423             
77424         if (me.sortable) {
77425             idx = Ext.Array.indexOf(me.possibleSortStates, me.sortState);
77426
77427             nextIdx = (idx + 1) % me.possibleSortStates.length;
77428             me.setSortState(me.possibleSortStates[nextIdx]);
77429         }
77430     },
77431
77432     doSort: function(state) {
77433         var ds = this.up('tablepanel').store;
77434         ds.sort({
77435             property: this.getSortParam(),
77436             direction: state
77437         });
77438     },
77439
77440     
77441     getSortParam: function() {
77442         return this.dataIndex;
77443     },
77444
77445     
77446     
77447     setSortState: function(state, skipClear, initial) {
77448         var me = this,
77449             colSortClsPrefix = Ext.baseCSSPrefix + 'column-header-sort-',
77450             ascCls = colSortClsPrefix + 'ASC',
77451             descCls = colSortClsPrefix + 'DESC',
77452             nullCls = colSortClsPrefix + 'null',
77453             ownerHeaderCt = me.getOwnerHeaderCt(),
77454             oldSortState = me.sortState;
77455
77456         if (oldSortState !== state && me.getSortParam()) {
77457             me.addCls(colSortClsPrefix + state);
77458             
77459             if (state && !initial) {
77460                 me.doSort(state);
77461             }
77462             switch (state) {
77463                 case 'DESC':
77464                     me.removeCls([ascCls, nullCls]);
77465                     break;
77466                 case 'ASC':
77467                     me.removeCls([descCls, nullCls]);
77468                     break;
77469                 case null:
77470                     me.removeCls([ascCls, descCls]);
77471                     break;
77472             }
77473             if (ownerHeaderCt && !me.triStateSort && !skipClear) {
77474                 ownerHeaderCt.clearOtherSortStates(me);
77475             }
77476             me.sortState = state;
77477             ownerHeaderCt.fireEvent('sortchange', ownerHeaderCt, me, state);
77478         }
77479     },
77480
77481     hide: function() {
77482         var me = this,
77483             items,
77484             len, i,
77485             lb,
77486             newWidth = 0,
77487             ownerHeaderCt = me.getOwnerHeaderCt();
77488
77489         
77490         me.oldWidth = me.getWidth();
77491
77492         
77493         if (me.isGroupHeader) {
77494             items = me.items.items;
77495             me.callParent(arguments);
77496             ownerHeaderCt.onHeaderHide(me);
77497             for (i = 0, len = items.length; i < len; i++) {
77498                 items[i].hidden = true;
77499                 ownerHeaderCt.onHeaderHide(items[i], true);
77500             }
77501             return;
77502         }
77503
77504         
77505         lb = me.ownerCt.componentLayout.layoutBusy;
77506         me.ownerCt.componentLayout.layoutBusy = true;
77507         me.callParent(arguments);
77508         me.ownerCt.componentLayout.layoutBusy = lb;
77509
77510         
77511         ownerHeaderCt.onHeaderHide(me);
77512
77513         if (me.ownerCt.isGroupHeader) {
77514             
77515             items = me.ownerCt.query('>:not([hidden])');
77516             if (!items.length) {
77517                 me.ownerCt.hide();
77518             }
77519             
77520             else {
77521                 for (i = 0, len = items.length; i < len; i++) {
77522                     newWidth += items[i].getWidth();
77523                 }
77524                 me.ownerCt.minWidth = newWidth;
77525                 me.ownerCt.setWidth(newWidth);
77526             }
77527         }
77528     },
77529
77530     show: function() {
77531         var me = this,
77532             ownerCt = me.getOwnerHeaderCt(),
77533             lb,
77534             items,
77535             len, i,
77536             newWidth = 0;
77537
77538         
77539         lb = me.ownerCt.componentLayout.layoutBusy;
77540         me.ownerCt.componentLayout.layoutBusy = true;
77541         me.callParent(arguments);
77542         me.ownerCt.componentLayout.layoutBusy = lb;
77543
77544         
77545         if (me.isSubHeader) {
77546             if (!me.ownerCt.isVisible()) {
77547                 me.ownerCt.show();
77548             }
77549         }
77550
77551         
77552         if (me.isGroupHeader && !me.query(':not([hidden])').length) {
77553             items = me.query('>*');
77554             for (i = 0, len = items.length; i < len; i++) {
77555                 items[i].show();
77556             }
77557         }
77558
77559         
77560         if (me.ownerCt.isGroupHeader) {
77561             items = me.ownerCt.query('>:not([hidden])');
77562             for (i = 0, len = items.length; i < len; i++) {
77563                 newWidth += items[i].getWidth();
77564             }
77565             me.ownerCt.minWidth = newWidth;
77566             me.ownerCt.setWidth(newWidth);
77567         }
77568
77569         
77570         if (ownerCt) {
77571             ownerCt.onHeaderShow(me);
77572         }
77573     },
77574
77575     getDesiredWidth: function() {
77576         var me = this;
77577         if (me.rendered && me.componentLayout && me.componentLayout.lastComponentSize) {
77578             
77579             
77580             
77581             
77582             
77583             
77584             return me.componentLayout.lastComponentSize.width;
77585         
77586         
77587         
77588         }
77589         else if (me.flex) {
77590             
77591             return me.width;
77592         }
77593         else {
77594             return me.width;
77595         }
77596     },
77597
77598     getCellSelector: function() {
77599         return '.' + Ext.baseCSSPrefix + 'grid-cell-' + this.getItemId();
77600     },
77601
77602     getCellInnerSelector: function() {
77603         return this.getCellSelector() + ' .' + Ext.baseCSSPrefix + 'grid-cell-inner';
77604     },
77605
77606     isOnLeftEdge: function(e) {
77607         return (e.getXY()[0] - this.el.getLeft() <= this.handleWidth);
77608     },
77609
77610     isOnRightEdge: function(e) {
77611         return (this.el.getRight() - e.getXY()[0] <= this.handleWidth);
77612     }
77613     
77614     
77615     
77616     
77617     
77618     
77619     
77620 });
77621
77622 Ext.define('Ext.grid.RowNumberer', {
77623     extend: 'Ext.grid.column.Column',
77624     alias: 'widget.rownumberer',
77625     
77626     text: "&#160",
77627
77628     
77629     width: 23,
77630
77631     
77632     sortable: false,
77633
77634     align: 'right',
77635
77636     constructor : function(config){
77637         this.callParent(arguments);
77638         if (this.rowspan) {
77639             this.renderer = Ext.Function.bind(this.renderer, this);
77640         }
77641     },
77642
77643     
77644     fixed: true,
77645     hideable: false,
77646     menuDisabled: true,
77647     dataIndex: '',
77648     cls: Ext.baseCSSPrefix + 'row-numberer',
77649     rowspan: undefined,
77650
77651     
77652     renderer: function(value, metaData, record, rowIdx, colIdx, store) {
77653         if (this.rowspan){
77654             metaData.cellAttr = 'rowspan="'+this.rowspan+'"';
77655         }
77656
77657         metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
77658         return store.indexOfTotal(record) + 1;
77659     }
77660 });
77661
77662
77663 Ext.define('Ext.view.DropZone', {
77664     extend: 'Ext.dd.DropZone',
77665
77666     indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
77667     indicatorCls: 'x-grid-drop-indicator',
77668
77669     constructor: function(config) {
77670         var me = this;
77671         Ext.apply(me, config);
77672
77673         
77674         
77675         
77676         
77677         
77678         if (!me.ddGroup) {
77679             me.ddGroup = 'view-dd-zone-' + me.view.id;
77680         }
77681
77682         
77683         
77684         
77685         me.callParent([me.view.el]);
77686     },
77687
77688
77689
77690     fireViewEvent: function() {
77691         this.lock();
77692         var result = this.view.fireEvent.apply(this.view, arguments);
77693         this.unlock();
77694         return result;
77695     },
77696
77697     getTargetFromEvent : function(e) {
77698         var node = e.getTarget(this.view.getItemSelector()),
77699             mouseY, nodeList, testNode, i, len, box;
77700
77701
77702
77703         if (!node) {
77704             mouseY = e.getPageY();
77705             for (i = 0, nodeList = this.view.getNodes(), len = nodeList.length; i < len; i++) {
77706                 testNode = nodeList[i];
77707                 box = Ext.fly(testNode).getBox();
77708                 if (mouseY <= box.bottom) {
77709                     return testNode;
77710                 }
77711             }
77712         }
77713         return node;
77714     },
77715
77716     getIndicator: function() {
77717         var me = this;
77718
77719         if (!me.indicator) {
77720             me.indicator = Ext.createWidget('component', {
77721                 html: me.indicatorHtml,
77722                 cls: me.indicatorCls,
77723                 ownerCt: me.view,
77724                 floating: true,
77725                 shadow: false
77726             });
77727         }
77728         return me.indicator;
77729     },
77730
77731     getPosition: function(e, node) {
77732         var y      = e.getXY()[1],
77733             region = Ext.fly(node).getRegion(),
77734             pos;
77735
77736         if ((region.bottom - y) >= (region.bottom - region.top) / 2) {
77737             pos = "before";
77738         } else {
77739             pos = "after";
77740         }
77741         return pos;
77742     },
77743
77744     
77745     containsRecordAtOffset: function(records, record, offset) {
77746         if (!record) {
77747             return false;
77748         }
77749         var view = this.view,
77750             recordIndex = view.indexOf(record),
77751             nodeBefore = view.getNode(recordIndex + offset),
77752             recordBefore = nodeBefore ? view.getRecord(nodeBefore) : null;
77753
77754         return recordBefore && Ext.Array.contains(records, recordBefore);
77755     },
77756
77757     positionIndicator: function(node, data, e) {
77758         var me = this,
77759             view = me.view,
77760             pos = me.getPosition(e, node),
77761             overRecord = view.getRecord(node),
77762             draggingRecords = data.records,
77763             indicator, indicatorY;
77764
77765         if (!Ext.Array.contains(draggingRecords, overRecord) && (
77766             pos == 'before' && !me.containsRecordAtOffset(draggingRecords, overRecord, -1) ||
77767             pos == 'after' && !me.containsRecordAtOffset(draggingRecords, overRecord, 1)
77768         )) {
77769             me.valid = true;
77770
77771             if (me.overRecord != overRecord || me.currentPosition != pos) {
77772
77773                 indicatorY = Ext.fly(node).getY() - view.el.getY() - 1;
77774                 if (pos == 'after') {
77775                     indicatorY += Ext.fly(node).getHeight();
77776                 }
77777                 me.getIndicator().setWidth(Ext.fly(view.el).getWidth()).showAt(0, indicatorY);
77778
77779                 
77780                 me.overRecord = overRecord;
77781                 me.currentPosition = pos;
77782             }
77783         } else {
77784             me.invalidateDrop();
77785         }
77786     },
77787
77788     invalidateDrop: function() {
77789         if (this.valid) {
77790             this.valid = false;
77791             this.getIndicator().hide();
77792         }
77793     },
77794
77795     
77796     onNodeOver: function(node, dragZone, e, data) {
77797         if (!Ext.Array.contains(data.records, this.view.getRecord(node))) {
77798             this.positionIndicator(node, data, e);
77799         }
77800         return this.valid ? this.dropAllowed : this.dropNotAllowed;
77801     },
77802
77803     
77804     
77805     notifyOut: function(node, dragZone, e, data) {
77806         this.callParent(arguments);
77807         delete this.overRecord;
77808         delete this.currentPosition;
77809         if (this.indicator) {
77810             this.indicator.hide();
77811         }
77812     },
77813
77814     
77815     onContainerOver : function(dd, e, data) {
77816         var v = this.view,
77817             c = v.store.getCount();
77818
77819         
77820         if (c) {
77821             this.positionIndicator(v.getNode(c - 1), data, e);
77822         }
77823
77824         
77825         else {
77826             delete this.overRecord;
77827             delete this.currentPosition;
77828             this.getIndicator().setWidth(Ext.fly(v.el).getWidth()).showAt(0, 0);
77829             this.valid = true;
77830         }
77831         return this.dropAllowed;
77832     },
77833
77834     onContainerDrop : function(dd, e, data) {
77835         return this.onNodeDrop(dd, null, e, data);
77836     },
77837
77838     onNodeDrop: function(node, dragZone, e, data) {
77839         var me = this,
77840             dropped = false,
77841
77842             
77843             
77844             
77845             
77846             processDrop = function () {
77847                 me.invalidateDrop();
77848                 me.handleNodeDrop(data, me.overRecord, me.currentPosition);
77849                 dropped = true;
77850                 me.fireViewEvent('drop', node, data, me.overRecord, me.currentPosition);
77851             },
77852             performOperation;
77853
77854         if (me.valid) {
77855             performOperation = me.fireViewEvent('beforedrop', node, data, me.overRecord, me.currentPosition, processDrop);
77856             if (performOperation === 0) {
77857                 return;
77858             } else if (performOperation !== false) {
77859                 
77860                 if (!dropped) {
77861                     processDrop();
77862                 }
77863             } else {
77864                 return false;
77865             }
77866         } else {
77867             return false;
77868         }
77869     }
77870 });
77871
77872 Ext.define('Ext.grid.ViewDropZone', {
77873     extend: 'Ext.view.DropZone',
77874
77875     indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
77876     indicatorCls: 'x-grid-drop-indicator',
77877
77878     handleNodeDrop : function(data, record, position) {
77879         var view = this.view,
77880             store = view.getStore(),
77881             index, records, i, len;
77882
77883         
77884         if (data.copy) {
77885             records = data.records;
77886             data.records = [];
77887             for (i = 0, len = records.length; i < len; i++) {
77888                 data.records.push(records[i].copy(records[i].getId()));
77889             }
77890         } else {
77891             
77892             data.view.store.remove(data.records, data.view === view);
77893         }
77894
77895         index = store.indexOf(record);
77896         if (position == 'after') {
77897             index++;
77898         }
77899         store.insert(index, data.records);
77900         view.getSelectionModel().select(data.records);
77901     }
77902 });
77903
77904 Ext.define('Ext.grid.column.Action', {
77905     extend: 'Ext.grid.column.Column',
77906     alias: ['widget.actioncolumn'],
77907     alternateClassName: 'Ext.grid.ActionColumn',
77908
77909     
77910     
77911     
77912     
77913     
77914     
77915     
77916     
77917     header: '&#160;',
77918
77919     actionIdRe: /x-action-col-(\d+)/,
77920
77921     
77922     altText: '',
77923     
77924     sortable: false,
77925
77926     constructor: function(config) {
77927         var me = this,
77928             cfg = Ext.apply({}, config),
77929             items = cfg.items || [me],
77930             l = items.length,
77931             i,
77932             item;
77933
77934         
77935         delete cfg.items;
77936         me.callParent([cfg]);
77937
77938         
77939         me.items = items;
77940
77941
77942
77943         me.renderer = function(v, meta) {
77944
77945             v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments)||'' : '';
77946
77947             meta.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell';
77948             for (i = 0; i < l; i++) {
77949                 item = items[i];
77950                 v += '<img alt="' + me.altText + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
77951                     '" class="' + Ext.baseCSSPrefix + 'action-col-icon ' + Ext.baseCSSPrefix + 'action-col-' + String(i) + ' ' +  (item.iconCls || '') + 
77952                     ' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope||me.scope||me, arguments) : (me.iconCls || '')) + '"' +
77953                     ((item.tooltip) ? ' data-qtip="' + item.tooltip + '"' : '') + ' />';
77954             }
77955             return v;
77956         };
77957     },
77958
77959     destroy: function() {
77960         delete this.items;
77961         delete this.renderer;
77962         return this.callParent(arguments);
77963     },
77964
77965     
77966     processEvent : function(type, view, cell, recordIndex, cellIndex, e){
77967         var me = this,
77968             match = e.getTarget().className.match(me.actionIdRe),
77969             item, fn;
77970         if (match) {
77971             item = me.items[parseInt(match[1], 10)];
77972             if (item) {
77973                 if (type == 'click') {
77974                     fn = item.handler || me.handler;
77975                     if (fn) {
77976                         fn.call(item.scope || me.scope || me, view, recordIndex, cellIndex, item, e);
77977                     }
77978                 } else if (type == 'mousedown' && item.stopSelection !== false) {
77979                     return false;
77980                 }
77981             }
77982         }
77983         return me.callParent(arguments);
77984     },
77985
77986     cascade: function(fn, scope) {
77987         fn.call(scope||this, this);
77988     },
77989
77990     
77991     getRefItems: function() {
77992         return [];
77993     }
77994 });
77995
77996 Ext.define('Ext.grid.column.Boolean', {
77997     extend: 'Ext.grid.column.Column',
77998     alias: ['widget.booleancolumn'],
77999     alternateClassName: 'Ext.grid.BooleanColumn',
78000
78001     
78002     trueText: 'true',
78003
78004     
78005     falseText: 'false',
78006
78007     
78008     undefinedText: '&#160;',
78009
78010     constructor: function(cfg){
78011         this.callParent(arguments);
78012         var trueText      = this.trueText,
78013             falseText     = this.falseText,
78014             undefinedText = this.undefinedText;
78015
78016         this.renderer = function(value){
78017             if(value === undefined){
78018                 return undefinedText;
78019             }
78020             if(!value || value === 'false'){
78021                 return falseText;
78022             }
78023             return trueText;
78024         };
78025     }
78026 });
78027
78028 Ext.define('Ext.grid.column.Date', {
78029     extend: 'Ext.grid.column.Column',
78030     alias: ['widget.datecolumn'],
78031     requires: ['Ext.Date'],
78032     alternateClassName: 'Ext.grid.DateColumn',
78033
78034     
78035     format : Ext.Date.defaultFormat,
78036
78037     constructor: function(cfg){
78038         this.callParent(arguments);
78039         this.renderer = Ext.util.Format.dateRenderer(this.format);
78040     }
78041 });
78042
78043 Ext.define('Ext.grid.column.Number', {
78044     extend: 'Ext.grid.column.Column',
78045     alias: ['widget.numbercolumn'],
78046     requires: ['Ext.util.Format'],
78047     alternateClassName: 'Ext.grid.NumberColumn',
78048
78049     
78050     format : '0,000.00',
78051     constructor: function(cfg) {
78052         this.callParent(arguments);
78053         this.renderer = Ext.util.Format.numberRenderer(this.format);
78054     }
78055 });
78056
78057 Ext.define('Ext.grid.column.Template', {
78058     extend: 'Ext.grid.column.Column',
78059     alias: ['widget.templatecolumn'],
78060     requires: ['Ext.XTemplate'],
78061     alternateClassName: 'Ext.grid.TemplateColumn',
78062
78063     
78064     constructor: function(cfg){
78065         var me = this,
78066             tpl;
78067             
78068         me.callParent(arguments);
78069         tpl = me.tpl = (!Ext.isPrimitive(me.tpl) && me.tpl.compile) ? me.tpl : Ext.create('Ext.XTemplate', me.tpl);
78070
78071         me.renderer = function(value, p, record) {
78072             var data = Ext.apply({}, record.data, record.getAssociatedData());
78073             return tpl.apply(data);
78074         };
78075     }
78076 });
78077
78078
78079 Ext.define('Ext.grid.feature.Feature', {
78080     extend: 'Ext.util.Observable',
78081     alias: 'feature.feature',
78082     
78083     isFeature: true,
78084     disabled: false,
78085     
78086     
78087     hasFeatureEvent: true,
78088     
78089     
78090     eventPrefix: null,
78091     
78092     
78093     eventSelector: null,
78094     
78095     
78096     view: null,
78097     
78098     
78099     grid: null,
78100     
78101     
78102     collectData: false,
78103         
78104     getFeatureTpl: function() {
78105         return '';
78106     },
78107     
78108     
78109     getFireEventArgs: function(eventName, view, featureTarget, e) {
78110         return [eventName, view, featureTarget, e];
78111     },
78112     
78113     
78114     attachEvents: function() {
78115         
78116     },
78117     
78118     getFragmentTpl: function() {
78119         return;
78120     },
78121     
78122     
78123     mutateMetaRowTpl: function(metaRowTplArray) {
78124         
78125     },
78126     
78127     
78128     getMetaRowTplFragments: function() {
78129         return {};
78130     },
78131
78132     getTableFragments: function() {
78133         return {};
78134     },
78135     
78136     
78137     getAdditionalData: function(data, idx, record, orig) {
78138         return {};
78139     },
78140     
78141     
78142     enable: function() {
78143         this.disabled = false;
78144     },
78145     
78146     
78147     disable: function() {
78148         this.disabled = true;
78149     }
78150     
78151 });
78152
78153 Ext.define('Ext.grid.feature.AbstractSummary', {
78154     
78155     
78156    
78157     extend: 'Ext.grid.feature.Feature',
78158     
78159     alias: 'feature.abstractsummary',
78160    
78161     
78162    
78163    
78164     showSummaryRow: true,
78165     
78166     
78167     nestedIdRe: /\{\{id\}([\w\-]*)\}/g,
78168     
78169     
78170     toggleSummaryRow: function(visible){
78171         this.showSummaryRow = !!visible;
78172     },
78173     
78174     
78175     getSummaryFragments: function(){
78176         var fragments = {};
78177         if (this.showSummaryRow) {
78178             Ext.apply(fragments, {
78179                 printSummaryRow: Ext.bind(this.printSummaryRow, this)
78180             });
78181         }
78182         return fragments;
78183     },
78184     
78185     
78186     printSummaryRow: function(index){
78187         var inner = this.view.getTableChunker().metaRowTpl.join('');
78188         
78189         inner = inner.replace('x-grid-row', 'x-grid-row-summary');
78190         inner = inner.replace('{{id}}', '{gridSummaryValue}');
78191         inner = inner.replace(this.nestedIdRe, '{id$1}');  
78192         inner = inner.replace('{[this.embedRowCls()]}', '{rowCls}');
78193         inner = inner.replace('{[this.embedRowAttr()]}', '{rowAttr}');
78194         inner = Ext.create('Ext.XTemplate', inner, {
78195             firstOrLastCls: Ext.view.TableChunker.firstOrLastCls
78196         });
78197         
78198         return inner.applyTemplate({
78199             columns: this.getPrintData(index)
78200         });
78201     },
78202     
78203     
78204     getColumnValue: function(column, summaryData){
78205         var comp     = Ext.getCmp(column.id),
78206             value    = summaryData[column.dataIndex],
78207             renderer = comp.summaryRenderer;
78208
78209         if (renderer) {
78210             value = renderer.call(
78211                 comp.scope || this,
78212                 value,
78213                 summaryData,
78214                 column.dataIndex
78215             );
78216         }
78217         return value;
78218     },
78219     
78220     
78221     getSummary: function(store, type, field, group){
78222         if (type) {
78223             if (Ext.isFunction(type)) {
78224                 return store.aggregate(type, null, group);
78225             }
78226             
78227             switch (type) {
78228                 case 'count':
78229                     return store.count(group);
78230                 case 'min':
78231                     return store.min(field, group);
78232                 case 'max':
78233                     return store.max(field, group);
78234                 case 'sum':
78235                     return store.sum(field, group);
78236                 case 'average':
78237                     return store.average(field, group);
78238                 default:
78239                     return group ? {} : '';
78240                     
78241             }
78242         }
78243     }
78244     
78245 });
78246
78247
78248 Ext.define('Ext.grid.feature.Chunking', {
78249     extend: 'Ext.grid.feature.Feature',
78250     alias: 'feature.chunking',
78251     
78252     chunkSize: 20,
78253     rowHeight: Ext.isIE ? 27 : 26,
78254     visibleChunk: 0,
78255     hasFeatureEvent: false,
78256     attachEvents: function() {
78257         var grid = this.view.up('gridpanel'),
78258             scroller = grid.down('gridscroller[dock=right]');
78259         scroller.el.on('scroll', this.onBodyScroll, this, {buffer: 300});
78260         
78261     },
78262     
78263     onBodyScroll: function(e, t) {
78264         var view = this.view,
78265             top  = t.scrollTop,
78266             nextChunk = Math.floor(top / this.rowHeight / this.chunkSize);
78267         if (nextChunk !== this.visibleChunk) {
78268         
78269             this.visibleChunk = nextChunk;
78270             view.refresh();
78271             view.el.dom.scrollTop = top;
78272             
78273             view.el.dom.scrollTop = top;
78274         }
78275     },
78276     
78277     collectData: function(records, preppedRecords, startIndex, fullWidth, orig) {
78278         var o = {
78279             fullWidth: orig.fullWidth,
78280             chunks: []
78281         },
78282         
78283         
78284         recordCount = orig.rows.length,
78285         start = 0,
78286         i = 0,
78287         visibleChunk = this.visibleChunk,
78288         chunk,
78289         rows,
78290         chunkLength;
78291
78292         for (; start < recordCount; start+=this.chunkSize, i++) {
78293             if (start+this.chunkSize > recordCount) {
78294                 chunkLength = recordCount - start;
78295             } else {
78296                 chunkLength = this.chunkSize;
78297             }
78298             
78299             if (i >= visibleChunk - 1 && i <= visibleChunk + 1) {
78300                 rows = orig.rows.slice(start, start+this.chunkSize);
78301             } else {
78302                 rows = [];
78303             }
78304             o.chunks.push({
78305                 rows: rows,
78306                 fullWidth: fullWidth,
78307                 chunkHeight: chunkLength * this.rowHeight
78308             });
78309         }
78310         
78311         
78312         return o;
78313     },
78314     
78315     getTableFragments: function() {
78316         return {
78317             openTableWrap: function() {
78318                 return '<tpl for="chunks"><div class="' + Ext.baseCSSPrefix + 'grid-chunk" style="height: {chunkHeight}px;">';
78319             },
78320             closeTableWrap: function() {
78321                 return '</div></tpl>';
78322             }
78323         };
78324     }
78325 });
78326
78327
78328 Ext.define('Ext.grid.feature.Grouping', {
78329     extend: 'Ext.grid.feature.Feature',
78330     alias: 'feature.grouping',
78331
78332     eventPrefix: 'group',
78333     eventSelector: '.' + Ext.baseCSSPrefix + 'grid-group-hd',
78334
78335     constructor: function() {
78336         this.collapsedState = {};
78337         this.callParent(arguments);
78338     },
78339     
78340     
78341
78342     
78343
78344     
78345
78346     
78347
78348     
78349
78350     
78351     groupHeaderTpl: 'Group: {name}',
78352
78353     
78354     depthToIndent: 17,
78355
78356     collapsedCls: Ext.baseCSSPrefix + 'grid-group-collapsed',
78357     hdCollapsedCls: Ext.baseCSSPrefix + 'grid-group-hd-collapsed',
78358
78359     
78360     groupByText : 'Group By This Field',
78361     
78362     showGroupsText : 'Show in Groups',
78363
78364     
78365     hideGroupedHeader : false,
78366
78367     
78368     startCollapsed : false,
78369
78370     
78371     enableGroupingMenu : true,
78372
78373     
78374     enableNoGroups : true,
78375     
78376     enable: function() {
78377         var me    = this,
78378             view  = me.view,
78379             store = view.store,
78380             groupToggleMenuItem;
78381             
78382         if (me.lastGroupIndex) {
78383             store.group(me.lastGroupIndex);
78384         }
78385         me.callParent();
78386         groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
78387         groupToggleMenuItem.setChecked(true, true);
78388         view.refresh();
78389     },
78390
78391     disable: function() {
78392         var me    = this,
78393             view  = me.view,
78394             store = view.store,
78395             groupToggleMenuItem,
78396             lastGroup;
78397             
78398         lastGroup = store.groupers.first();
78399         if (lastGroup) {
78400             me.lastGroupIndex = lastGroup.property;
78401             store.groupers.clear();
78402         }
78403         
78404         me.callParent();
78405         groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
78406         groupToggleMenuItem.setChecked(true, true);
78407         groupToggleMenuItem.setChecked(false, true);
78408         view.refresh();
78409     },
78410
78411     getFeatureTpl: function(values, parent, x, xcount) {
78412         var me = this;
78413         
78414         return [
78415             '<tpl if="typeof rows !== \'undefined\'">',
78416                 
78417                 '<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>',
78418                 
78419                 '<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>',
78420             '</tpl>'
78421         ].join('');
78422     },
78423
78424     getFragmentTpl: function() {
78425         return {
78426             indentByDepth: this.indentByDepth,
78427             depthToIndent: this.depthToIndent
78428         };
78429     },
78430
78431     indentByDepth: function(values) {
78432         var depth = values.depth || 0;
78433         return 'style="padding-left:'+ depth * this.depthToIndent + 'px;"';
78434     },
78435
78436     
78437     
78438     destroy: function() {
78439         var me = this;
78440         
78441         delete me.view;
78442         delete me.prunedHeader;
78443     },
78444
78445     
78446     attachEvents: function() {
78447         var me = this,
78448             view = me.view,
78449             header, headerId, menu, menuItem;
78450
78451         view.on({
78452             scope: me,
78453             groupclick: me.onGroupClick,
78454             rowfocus: me.onRowFocus
78455         });
78456         view.store.on('groupchange', me.onGroupChange, me);
78457
78458         me.pruneGroupedHeader();
78459
78460         if (me.enableGroupingMenu) {
78461             me.injectGroupingMenu();
78462         }
78463
78464         if (me.hideGroupedHeader) {
78465             header = view.headerCt.down('gridcolumn[dataIndex=' + me.getGroupField() + ']');
78466             headerId = header.id;
78467             menu = view.headerCt.getMenu();
78468             menuItem = menu.down('menuitem[headerId='+ headerId +']');
78469             if (menuItem) {
78470                 menuItem.setChecked(false);
78471             }
78472         }
78473     },
78474     
78475     injectGroupingMenu: function() {
78476         var me       = this,
78477             view     = me.view,
78478             headerCt = view.headerCt;
78479         headerCt.showMenuBy = me.showMenuBy;
78480         headerCt.getMenuItems = me.getMenuItems();
78481     },
78482     
78483     showMenuBy: function(t, header) {
78484         var menu = this.getMenu(),
78485             groupMenuItem  = menu.down('#groupMenuItem'),
78486             groupableMth = header.groupable === false ?  'disable' : 'enable';
78487             
78488         groupMenuItem[groupableMth]();
78489         Ext.grid.header.Container.prototype.showMenuBy.apply(this, arguments);
78490     },
78491     
78492     getMenuItems: function() {
78493         var me                 = this,
78494             groupByText        = me.groupByText,
78495             disabled           = me.disabled,
78496             showGroupsText     = me.showGroupsText,
78497             enableNoGroups     = me.enableNoGroups,
78498             groupMenuItemClick = Ext.Function.bind(me.onGroupMenuItemClick, me),
78499             groupToggleMenuItemClick = Ext.Function.bind(me.onGroupToggleMenuItemClick, me);
78500         
78501         
78502         return function() {
78503             var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
78504             o.push('-', {
78505                 itemId: 'groupMenuItem',
78506                 text: groupByText,
78507                 handler: groupMenuItemClick
78508             });
78509             if (enableNoGroups) {
78510                 o.push({
78511                     itemId: 'groupToggleMenuItem',
78512                     text: showGroupsText,
78513                     checked: !disabled,
78514                     checkHandler: groupToggleMenuItemClick
78515                 });
78516             }
78517             return o;
78518         };
78519     },
78520
78521
78522     
78523     onGroupMenuItemClick: function(menuItem, e) {
78524         var menu = menuItem.parentMenu,
78525             hdr  = menu.activeHeader,
78526             view = this.view;
78527
78528         delete this.lastGroupIndex;
78529         this.enable();
78530         view.store.group(hdr.dataIndex);
78531         this.pruneGroupedHeader();
78532         
78533     },
78534
78535     
78536     onGroupToggleMenuItemClick: function(menuItem, checked) {
78537         this[checked ? 'enable' : 'disable']();
78538     },
78539
78540     
78541     pruneGroupedHeader: function() {
78542         var me         = this,
78543             view       = me.view,
78544             store      = view.store,
78545             groupField = me.getGroupField(),
78546             headerCt   = view.headerCt,
78547             header     = headerCt.down('header[dataIndex=' + groupField + ']');
78548
78549         if (header) {
78550             if (me.prunedHeader) {
78551                 me.prunedHeader.show();
78552             }
78553             me.prunedHeader = header;
78554             header.hide();
78555         }
78556     },
78557
78558     getGroupField: function(){
78559         var group = this.view.store.groupers.first();
78560         if (group) {
78561             return group.property;    
78562         }
78563         return ''; 
78564     },
78565
78566     
78567     onRowFocus: function(rowIdx) {
78568         var node    = this.view.getNode(rowIdx),
78569             groupBd = Ext.fly(node).up('.' + this.collapsedCls);
78570
78571         if (groupBd) {
78572             
78573             
78574             this.expand(groupBd);
78575         }
78576     },
78577
78578     
78579     expand: function(groupBd) {
78580         var me = this,
78581             view = me.view,
78582             grid = view.up('gridpanel'),
78583             groupBdDom = Ext.getDom(groupBd);
78584             
78585         me.collapsedState[groupBdDom.id] = false;
78586
78587         groupBd.removeCls(me.collapsedCls);
78588         groupBd.prev().removeCls(me.hdCollapsedCls);
78589
78590         grid.determineScrollbars();
78591         grid.invalidateScroller();
78592         view.fireEvent('groupexpand');
78593     },
78594
78595     
78596     collapse: function(groupBd) {
78597         var me = this,
78598             view = me.view,
78599             grid = view.up('gridpanel'),
78600             groupBdDom = Ext.getDom(groupBd);
78601             
78602         me.collapsedState[groupBdDom.id] = true;
78603
78604         groupBd.addCls(me.collapsedCls);
78605         groupBd.prev().addCls(me.hdCollapsedCls);
78606
78607         grid.determineScrollbars();
78608         grid.invalidateScroller();
78609         view.fireEvent('groupcollapse');
78610     },
78611     
78612     onGroupChange: function(){
78613         this.view.refresh();
78614     },
78615
78616     
78617     onGroupClick: function(view, group, idx, foo, e) {
78618         var me = this,
78619             toggleCls = me.toggleCls,
78620             groupBd = Ext.fly(group.nextSibling, '_grouping');
78621
78622         if (groupBd.hasCls(me.collapsedCls)) {
78623             me.expand(groupBd);
78624         } else {
78625             me.collapse(groupBd);
78626         }
78627     },
78628
78629     
78630     getMetaRowTplFragments: function() {
78631         return {
78632             isRow: this.isRow,
78633             closeRow: this.closeRow
78634         };
78635     },
78636
78637     
78638     
78639     isRow: function() {
78640         return '<tpl if="typeof rows === \'undefined\'">';
78641     },
78642
78643     
78644     
78645     closeRow: function() {
78646         return '</tpl>';
78647     },
78648
78649     
78650     mutateMetaRowTpl: function(metaRowTpl) {
78651         metaRowTpl.unshift('{[this.isRow()]}');
78652         metaRowTpl.push('{[this.closeRow()]}');
78653     },
78654
78655     
78656     
78657     getAdditionalData: function(data, idx, record, orig) {
78658         var view = this.view,
78659             hCt  = view.headerCt,
78660             col  = hCt.items.getAt(0),
78661             o = {},
78662             tdAttrKey = col.id + '-tdAttr';
78663
78664         
78665         o[tdAttrKey] = this.indentByDepth(data) + " " + (orig[tdAttrKey] ? orig[tdAttrKey] : '');
78666         o.collapsed = 'true';
78667         return o;
78668     },
78669
78670     
78671     getGroupRows: function(group, records, preppedRecords, fullWidth) {
78672         var me = this,
78673             children = group.children,
78674             rows = group.rows = [],
78675             view = me.view;
78676         group.viewId = view.id;
78677
78678         Ext.Array.each(records, function(record, idx) {
78679             if (Ext.Array.indexOf(children, record) != -1) {
78680                 rows.push(Ext.apply(preppedRecords[idx], {
78681                     depth: 1
78682                 }));
78683             }
78684         });
78685         delete group.children;
78686         group.fullWidth = fullWidth;
78687         if (me.collapsedState[view.id + '-gp-' + group.name]) {
78688             group.collapsedCls = me.collapsedCls;
78689             group.hdCollapsedCls = me.hdCollapsedCls;
78690         }
78691
78692         return group;
78693     },
78694
78695     
78696     collectData: function(records, preppedRecords, startIndex, fullWidth, o) {
78697         var me    = this,
78698             store = me.view.store,
78699             groups;
78700             
78701         if (!me.disabled && store.isGrouped()) {
78702             groups = store.getGroups();
78703             Ext.Array.each(groups, function(group, idx){
78704                 me.getGroupRows(group, records, preppedRecords, fullWidth);
78705             }, me);
78706             return {
78707                 rows: groups,
78708                 fullWidth: fullWidth
78709             };
78710         }
78711         return o;
78712     },
78713     
78714     
78715     
78716     
78717     
78718     getFireEventArgs: function(type, view, featureTarget, e) {
78719         var returnArray = [type, view, featureTarget],
78720             groupBd     = Ext.fly(featureTarget.nextSibling, '_grouping'),
78721             groupBdId   = Ext.getDom(groupBd).id,
78722             prefix      = view.id + '-gp-',
78723             groupName   = groupBdId.substr(prefix.length);
78724         
78725         returnArray.push(groupName, e);
78726         
78727         return returnArray;
78728     }
78729 });
78730
78731
78732 Ext.define('Ext.grid.feature.GroupingSummary', {
78733     
78734     
78735     
78736     extend: 'Ext.grid.feature.Grouping',
78737     
78738     alias: 'feature.groupingsummary',
78739     
78740     mixins: {
78741         summary: 'Ext.grid.feature.AbstractSummary'
78742     },
78743     
78744     
78745
78746      
78747    
78748    getFeatureTpl: function() {
78749         var tpl = this.callParent(arguments);
78750             
78751         if (this.showSummaryRow) {
78752             
78753             tpl = tpl.replace('</tpl>', '');
78754             tpl += '{[this.printSummaryRow(xindex)]}</tpl>';
78755         }
78756         return tpl;
78757     },
78758     
78759     
78760     getFragmentTpl: function() {
78761         var me = this,
78762             fragments = me.callParent();
78763             
78764         Ext.apply(fragments, me.getSummaryFragments());
78765         if (me.showSummaryRow) {
78766             
78767             me.summaryGroups = me.view.store.getGroups();
78768             me.summaryData = me.generateSummaryData();
78769         }
78770         return fragments;
78771     },
78772     
78773     
78774     getPrintData: function(index){
78775         var me = this,
78776             columns = me.view.headerCt.getColumnsForTpl(),
78777             i = 0,
78778             length = columns.length,
78779             data = [],
78780             name = me.summaryGroups[index - 1].name,
78781             active = me.summaryData[name],
78782             column;
78783             
78784         for (; i < length; ++i) {
78785             column = columns[i];
78786             column.gridSummaryValue = this.getColumnValue(column, active);
78787             data.push(column);
78788         }
78789         return data;
78790     },
78791     
78792     
78793     generateSummaryData: function(){
78794         var me = this,
78795             data = {},
78796             remoteData = {},
78797             store = me.view.store,
78798             groupField = this.getGroupField(),
78799             reader = store.proxy.reader,
78800             groups = me.summaryGroups,
78801             columns = me.view.headerCt.getColumnsForTpl(),
78802             i,
78803             length,
78804             fieldData,
78805             root,
78806             key,
78807             comp;
78808             
78809         for (i = 0, length = groups.length; i < length; ++i) {
78810             data[groups[i].name] = {};
78811         }
78812         
78813     
78814         if (me.remoteRoot && reader.rawData) {
78815             
78816             root = reader.root;
78817             reader.root = me.remoteRoot;
78818             reader.buildExtractors(true);
78819             Ext.Array.each(reader.getRoot(reader.rawData), function(value) {
78820                  data[value[groupField]] = value;
78821                  data[value[groupField]]._remote = true;
78822             });
78823             
78824             reader.root = root;
78825             reader.buildExtractors(true);
78826         }
78827         
78828         for (i = 0, length = columns.length; i < length; ++i) {
78829             comp = Ext.getCmp(columns[i].id);
78830             fieldData = me.getSummary(store, comp.summaryType, comp.dataIndex, true);
78831             
78832             for (key in fieldData) {
78833                 if (fieldData.hasOwnProperty(key)) {
78834                     if (!data[key]._remote) {
78835                         data[key][comp.dataIndex] = fieldData[key];
78836                     }
78837                 }
78838             }
78839         }
78840         return data;
78841     }
78842 });
78843
78844
78845 Ext.define('Ext.grid.feature.RowBody', {
78846     extend: 'Ext.grid.feature.Feature',
78847     alias: 'feature.rowbody',
78848     rowBodyHiddenCls: Ext.baseCSSPrefix + 'grid-row-body-hidden',
78849     rowBodyTrCls: Ext.baseCSSPrefix + 'grid-rowbody-tr',
78850     rowBodyTdCls: Ext.baseCSSPrefix + 'grid-cell-rowbody',
78851     rowBodyDivCls: Ext.baseCSSPrefix + 'grid-rowbody',
78852
78853     eventPrefix: 'rowbody',
78854     eventSelector: '.' + Ext.baseCSSPrefix + 'grid-rowbody-tr',
78855     
78856     getRowBody: function(values) {
78857         return [
78858             '<tr class="' + this.rowBodyTrCls + ' {rowBodyCls}">',
78859                 '<td class="' + this.rowBodyTdCls + '" colspan="{rowBodyColspan}">',
78860                     '<div class="' + this.rowBodyDivCls + '">{rowBody}</div>',
78861                 '</td>',
78862             '</tr>'
78863         ].join('');
78864     },
78865     
78866     
78867     getMetaRowTplFragments: function() {
78868         return {
78869             getRowBody: this.getRowBody,
78870             rowBodyTrCls: this.rowBodyTrCls,
78871             rowBodyTdCls: this.rowBodyTdCls,
78872             rowBodyDivCls: this.rowBodyDivCls
78873         };
78874     },
78875
78876     mutateMetaRowTpl: function(metaRowTpl) {
78877         metaRowTpl.push('{[this.getRowBody(values)]}');
78878     },
78879
78880     
78881     getAdditionalData: function(data, idx, record, orig) {
78882         var headerCt = this.view.headerCt,
78883             colspan  = headerCt.getColumnCount();
78884
78885         return {
78886             rowBody: "",
78887             rowBodyCls: this.rowBodyCls,
78888             rowBodyColspan: colspan
78889         };
78890     }
78891 });
78892
78893 Ext.define('Ext.grid.feature.RowWrap', {
78894     extend: 'Ext.grid.feature.Feature',
78895     alias: 'feature.rowwrap',
78896
78897     
78898     hasFeatureEvent: false,
78899     
78900     mutateMetaRowTpl: function(metaRowTpl) {        
78901         
78902         
78903         metaRowTpl[0] = metaRowTpl[0].replace(Ext.baseCSSPrefix + 'grid-row', '');
78904         metaRowTpl[0] = metaRowTpl[0].replace("{[this.embedRowCls()]}", "");
78905         
78906         metaRowTpl.unshift('<table class="' + Ext.baseCSSPrefix + 'grid-table ' + Ext.baseCSSPrefix + 'grid-table-resizer" style="width: {[this.embedFullWidth()]}px;">');
78907         
78908         metaRowTpl.unshift('<tr class="' + Ext.baseCSSPrefix + 'grid-row {[this.embedRowCls()]}"><td colspan="{[this.embedColSpan()]}"><div class="' + Ext.baseCSSPrefix + 'grid-rowwrap-div">');
78909         
78910         
78911         metaRowTpl.push('</table>');
78912         
78913         metaRowTpl.push('</div></td></tr>');
78914     },
78915     
78916     embedColSpan: function() {
78917         return '{colspan}';
78918     },
78919     
78920     embedFullWidth: function() {
78921         return '{fullWidth}';
78922     },
78923     
78924     getAdditionalData: function(data, idx, record, orig) {
78925         var headerCt = this.view.headerCt,
78926             colspan  = headerCt.getColumnCount(),
78927             fullWidth = headerCt.getFullWidth(),
78928             items    = headerCt.query('gridcolumn'),
78929             itemsLn  = items.length,
78930             i = 0,
78931             o = {
78932                 colspan: colspan,
78933                 fullWidth: fullWidth
78934             },
78935             id,
78936             tdClsKey,
78937             colResizerCls;
78938
78939         for (; i < itemsLn; i++) {
78940             id = items[i].id;
78941             tdClsKey = id + '-tdCls';
78942             colResizerCls = Ext.baseCSSPrefix + 'grid-col-resizer-'+id;
78943             
78944             
78945             
78946             o[tdClsKey] = colResizerCls + " " + (orig[tdClsKey] ? orig[tdClsKey] : '');
78947             
78948             o[id+'-tdAttr'] = " style=\"width: " + (items[i].hidden ? 0 : items[i].getDesiredWidth()) + "px;\" ";
78949             if (orig[id+'-tdAttr']) {
78950                 o[id+'-tdAttr'] += orig[id+'-tdAttr'];
78951             }
78952             
78953         }
78954
78955         return o;
78956     },
78957     
78958     getMetaRowTplFragments: function() {
78959         return {
78960             embedFullWidth: this.embedFullWidth,
78961             embedColSpan: this.embedColSpan
78962         };
78963     }
78964     
78965 });
78966
78967 Ext.define('Ext.grid.feature.Summary', {
78968     
78969     
78970     
78971     extend: 'Ext.grid.feature.AbstractSummary',
78972     
78973     alias: 'feature.summary',
78974     
78975     
78976     
78977     
78978     getFragmentTpl: function() {
78979         
78980         this.summaryData = this.generateSummaryData(); 
78981         return this.getSummaryFragments();
78982     },
78983     
78984     
78985     getTableFragments: function(){
78986         if (this.showSummaryRow) {
78987             return {
78988                 closeRows: this.closeRows
78989             };
78990         }
78991     },
78992     
78993     
78994     closeRows: function() {
78995         return '</tpl>{[this.printSummaryRow()]}';
78996     },
78997     
78998     
78999     getPrintData: function(index){
79000         var me = this,
79001             columns = me.view.headerCt.getColumnsForTpl(),
79002             i = 0,
79003             length = columns.length,
79004             data = [],
79005             active = me.summaryData,
79006             column;
79007             
79008         for (; i < length; ++i) {
79009             column = columns[i];
79010             column.gridSummaryValue = this.getColumnValue(column, active);
79011             data.push(column);
79012         }
79013         return data;
79014     },
79015     
79016     
79017     generateSummaryData: function(){
79018         var me = this,
79019             data = {},
79020             store = me.view.store,
79021             columns = me.view.headerCt.getColumnsForTpl(),
79022             i = 0,
79023             length = columns.length,
79024             fieldData,
79025             key,
79026             comp;
79027             
79028         for (i = 0, length = columns.length; i < length; ++i) {
79029             comp = Ext.getCmp(columns[i].id);
79030             data[comp.dataIndex] = me.getSummary(store, comp.summaryType, comp.dataIndex, false);
79031         }
79032         return data;
79033     }
79034 });
79035
79036 Ext.define('Ext.grid.header.DragZone', {
79037     extend: 'Ext.dd.DragZone',
79038     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
79039     maxProxyWidth: 120,
79040
79041     constructor: function(headerCt) {
79042         this.headerCt = headerCt;
79043         this.ddGroup =  this.getDDGroup();
79044         this.callParent([headerCt.el]);
79045         this.proxy.el.addCls(Ext.baseCSSPrefix + 'grid-col-dd');
79046     },
79047
79048     getDDGroup: function() {
79049         return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
79050     },
79051
79052     getDragData: function(e) {
79053         var header = e.getTarget('.'+this.colHeaderCls),
79054             headerCmp;
79055
79056         if (header) {
79057             headerCmp = Ext.getCmp(header.id);
79058             if (!this.headerCt.dragging && headerCmp.draggable && !(headerCmp.isOnLeftEdge(e) || headerCmp.isOnRightEdge(e))) {
79059                 var ddel = document.createElement('div');
79060                 ddel.innerHTML = Ext.getCmp(header.id).text;
79061                 return {
79062                     ddel: ddel,
79063                     header: headerCmp
79064                 };
79065             }
79066         }
79067         return false;
79068     },
79069
79070     onBeforeDrag: function() {
79071         return !(this.headerCt.dragging || this.disabled);
79072     },
79073
79074     onInitDrag: function() {
79075         this.headerCt.dragging = true;
79076         this.callParent(arguments);
79077     },
79078
79079     onDragDrop: function() {
79080         this.headerCt.dragging = false;
79081         this.callParent(arguments);
79082     },
79083
79084     afterRepair: function() {
79085         this.callParent();
79086         this.headerCt.dragging = false;
79087     },
79088
79089     getRepairXY: function() {
79090         return this.dragData.header.el.getXY();
79091     },
79092     
79093     disable: function() {
79094         this.disabled = true;
79095     },
79096     
79097     enable: function() {
79098         this.disabled = false;
79099     }
79100 });
79101
79102
79103 Ext.define('Ext.grid.header.DropZone', {
79104     extend: 'Ext.dd.DropZone',
79105     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
79106     proxyOffsets: [-4, -9],
79107
79108     constructor: function(headerCt){
79109         this.headerCt = headerCt;
79110         this.ddGroup = this.getDDGroup();
79111         this.callParent([headerCt.el]);
79112     },
79113
79114     getDDGroup: function() {
79115         return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
79116     },
79117
79118     getTargetFromEvent : function(e){
79119         return e.getTarget('.' + this.colHeaderCls);
79120     },
79121
79122     getTopIndicator: function() {
79123         if (!this.topIndicator) {
79124             this.topIndicator = Ext.core.DomHelper.append(Ext.getBody(), {
79125                 cls: "col-move-top",
79126                 html: "&#160;"
79127             }, true);
79128         }
79129         return this.topIndicator;
79130     },
79131
79132     getBottomIndicator: function() {
79133         if (!this.bottomIndicator) {
79134             this.bottomIndicator = Ext.core.DomHelper.append(Ext.getBody(), {
79135                 cls: "col-move-bottom",
79136                 html: "&#160;"
79137             }, true);
79138         }
79139         return this.bottomIndicator;
79140     },
79141
79142     getLocation: function(e, t) {
79143         var x      = e.getXY()[0],
79144             region = Ext.fly(t).getRegion(),
79145             pos, header;
79146
79147         if ((region.right - x) <= (region.right - region.left) / 2) {
79148             pos = "after";
79149         } else {
79150             pos = "before";
79151         }
79152         return {
79153             pos: pos,
79154             header: Ext.getCmp(t.id),
79155             node: t
79156         };
79157     },
79158
79159     positionIndicator: function(draggedHeader, node, e){
79160         var location = this.getLocation(e, node),
79161             header = location.header,
79162             pos    = location.pos,
79163             nextHd = draggedHeader.nextSibling('gridcolumn:not([hidden])'),
79164             prevHd = draggedHeader.previousSibling('gridcolumn:not([hidden])'),
79165             region, topIndicator, bottomIndicator, topAnchor, bottomAnchor,
79166             topXY, bottomXY, headerCtEl, minX, maxX;
79167
79168         
79169         if (!header.draggable && header.getIndex() == 0) {
79170             return false;
79171         }
79172
79173         this.lastLocation = location;
79174
79175         if ((draggedHeader !== header) &&
79176             ((pos === "before" && nextHd !== header) ||
79177             (pos === "after" && prevHd !== header)) &&
79178             !header.isDescendantOf(draggedHeader)) {
79179
79180             
79181             
79182             
79183             var allDropZones = Ext.dd.DragDropManager.getRelated(this),
79184                 ln = allDropZones.length,
79185                 i  = 0,
79186                 dropZone;
79187
79188             for (; i < ln; i++) {
79189                 dropZone = allDropZones[i];
79190                 if (dropZone !== this && dropZone.invalidateDrop) {
79191                     dropZone.invalidateDrop();
79192                 }
79193             }
79194
79195
79196             this.valid = true;
79197             topIndicator = this.getTopIndicator();
79198             bottomIndicator = this.getBottomIndicator();
79199             if (pos === 'before') {
79200                 topAnchor = 'tl';
79201                 bottomAnchor = 'bl';
79202             } else {
79203                 topAnchor = 'tr';
79204                 bottomAnchor = 'br';
79205             }
79206             topXY = header.el.getAnchorXY(topAnchor);
79207             bottomXY = header.el.getAnchorXY(bottomAnchor);
79208
79209             
79210             headerCtEl = this.headerCt.el;
79211             minX = headerCtEl.getLeft();
79212             maxX = headerCtEl.getRight();
79213
79214             topXY[0] = Ext.Number.constrain(topXY[0], minX, maxX);
79215             bottomXY[0] = Ext.Number.constrain(bottomXY[0], minX, maxX);
79216
79217             
79218             
79219             topXY[0] -= 4;
79220             topXY[1] -= 9;
79221             bottomXY[0] -= 4;
79222
79223             
79224             topIndicator.setXY(topXY);
79225             bottomIndicator.setXY(bottomXY);
79226             topIndicator.show();
79227             bottomIndicator.show();
79228         
79229         } else {
79230             this.invalidateDrop();
79231         }
79232     },
79233
79234     invalidateDrop: function() {
79235         this.valid = false;
79236         this.hideIndicators();
79237     },
79238
79239     onNodeOver: function(node, dragZone, e, data) {
79240         if (data.header.el.dom !== node) {
79241             this.positionIndicator(data.header, node, e);
79242         }
79243         return this.valid ? this.dropAllowed : this.dropNotAllowed;
79244     },
79245
79246     hideIndicators: function() {
79247         this.getTopIndicator().hide();
79248         this.getBottomIndicator().hide();
79249     },
79250
79251     onNodeOut: function() {
79252         this.hideIndicators();
79253     },
79254
79255     onNodeDrop: function(node, dragZone, e, data) {
79256         if (this.valid) {
79257             this.invalidateDrop();
79258             var hd = data.header,
79259                 lastLocation = this.lastLocation,
79260                 fromCt  = hd.ownerCt,
79261                 fromIdx = fromCt.items.indexOf(hd), 
79262                 toCt    = lastLocation.header.ownerCt,
79263                 toIdx   = toCt.items.indexOf(lastLocation.header),
79264                 headerCt = this.headerCt,
79265                 groupCt,
79266                 scrollerOwner;
79267
79268             if (lastLocation.pos === 'after') {
79269                 toIdx++;
79270             }
79271
79272             
79273             
79274             
79275             if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && toCt.lockedCt) {
79276                 scrollerOwner = fromCt.up('[scrollerOwner]');
79277                 scrollerOwner.lock(hd, toIdx);
79278             } else if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && fromCt.lockedCt) {
79279                 scrollerOwner = fromCt.up('[scrollerOwner]');
79280                 scrollerOwner.unlock(hd, toIdx);
79281             } else {
79282                 
79283                 
79284                 if ((fromCt === toCt) && (toIdx > fromCt.items.indexOf(hd))) {
79285                     toIdx--;
79286                 }
79287
79288                 
79289                 if (fromCt !== toCt) {
79290                     fromCt.suspendLayout = true;
79291                     fromCt.remove(hd, false);
79292                     fromCt.suspendLayout = false;
79293                 }
79294
79295                 
79296                 if (fromCt.isGroupHeader) {
79297                     if (!fromCt.items.getCount()) {
79298                         groupCt = fromCt.ownerCt;
79299                         groupCt.suspendLayout = true;
79300                         groupCt.remove(fromCt, false);
79301                         fromCt.el.dom.parentNode.removeChild(fromCt.el.dom);
79302                         groupCt.suspendLayout = false;
79303                     } else {
79304                         fromCt.minWidth = fromCt.getWidth() - hd.getWidth();
79305                         fromCt.setWidth(fromCt.minWidth);
79306                     }
79307                 }
79308
79309                 
79310                 toCt.suspendLayout = true;
79311                 if (fromCt === toCt) {
79312                     toCt.move(fromIdx, toIdx);
79313                 } else {
79314                     toCt.insert(toIdx, hd);
79315                 }
79316                 toCt.suspendLayout = false;
79317
79318                 
79319                 
79320                 
79321                 if (toCt.isGroupHeader) {
79322                     hd.savedFlex = hd.flex;
79323                     delete hd.flex;
79324                     hd.width = hd.getWidth();
79325                     
79326                     
79327                     toCt.minWidth = toCt.getWidth() + hd.getWidth() - (hd.savedFlex ? 1 : 0);
79328                     toCt.setWidth(toCt.minWidth);
79329                 } else {
79330                     if (hd.savedFlex) {
79331                         hd.flex = hd.savedFlex;
79332                         delete hd.width;
79333                     }
79334                 }
79335
79336
79337                 
79338                 headerCt.purgeCache();
79339                 headerCt.doLayout();
79340                 headerCt.onHeaderMoved(hd, fromIdx, toIdx);
79341                 
79342                 if (!fromCt.items.getCount()) {
79343                     fromCt.destroy();
79344                 }
79345             }
79346         }
79347     }
79348 });
79349
79350
79351
79352 Ext.define('Ext.grid.plugin.Editing', {
79353     alias: 'editing.editing',
79354
79355     requires: [
79356         'Ext.grid.column.Column',
79357         'Ext.util.KeyNav'
79358     ],
79359
79360     mixins: {
79361         observable: 'Ext.util.Observable'
79362     },
79363
79364     
79365     clicksToEdit: 2,
79366
79367     
79368     defaultFieldXType: 'textfield',
79369
79370     
79371     editStyle: '',
79372
79373     constructor: function(config) {
79374         var me = this;
79375         Ext.apply(me, config);
79376
79377         me.addEvents(
79378             
79379             'beforeedit',
79380
79381             
79382             'edit',
79383
79384             
79385             'validateedit'
79386         );
79387         me.mixins.observable.constructor.call(me);
79388         
79389         me.relayEvents(me, ['afteredit'], 'after');
79390     },
79391
79392     
79393     init: function(grid) {
79394         var me = this;
79395
79396         me.grid = grid;
79397         me.view = grid.view;
79398         me.initEvents();
79399         me.initFieldAccessors(me.view.getGridColumns());
79400
79401         grid.relayEvents(me, ['beforeedit', 'edit', 'validateedit']);
79402         
79403         
79404         grid.isEditable = true;
79405         grid.editingPlugin = grid.view.editingPlugin = me;
79406     },
79407
79408     
79409     destroy: function() {
79410         var me = this,
79411             grid = me.grid,
79412             headerCt = grid.headerCt,
79413             events = grid.events;
79414
79415         Ext.destroy(me.keyNav);
79416         me.removeFieldAccessors(grid.getView().getGridColumns());
79417
79418         
79419         me.clearListeners();
79420
79421         delete me.grid.editingPlugin;
79422         delete me.grid.view.editingPlugin;
79423         delete me.grid;
79424         delete me.view;
79425         delete me.editor;
79426         delete me.keyNav;
79427     },
79428
79429     
79430     getEditStyle: function() {
79431         return this.editStyle;
79432     },
79433
79434     
79435     initFieldAccessors: function(column) {
79436         var me = this;
79437
79438         if (Ext.isArray(column)) {
79439             Ext.Array.forEach(column, me.initFieldAccessors, me);
79440             return;
79441         }
79442
79443         
79444         
79445         Ext.applyIf(column, {
79446             getEditor: function(record, defaultField) {
79447                 return me.getColumnField(this, defaultField);
79448             },
79449
79450             setEditor: function(field) {
79451                 me.setColumnField(this, field);
79452             }
79453         });
79454     },
79455
79456     
79457     removeFieldAccessors: function(column) {
79458         var me = this;
79459
79460         if (Ext.isArray(column)) {
79461             Ext.Array.forEach(column, me.removeFieldAccessors, me);
79462             return;
79463         }
79464
79465         delete column.getEditor;
79466         delete column.setEditor;
79467     },
79468
79469     
79470     
79471     getColumnField: function(columnHeader, defaultField) {
79472         var field = columnHeader.field;
79473
79474         if (!field && columnHeader.editor) {
79475             field = columnHeader.editor;
79476             delete columnHeader.editor;
79477         }
79478
79479         if (!field && defaultField) {
79480             field = defaultField;
79481         }
79482
79483         if (field) {
79484             if (Ext.isString(field)) {
79485                 field = { xtype: field };
79486             }
79487             if (Ext.isObject(field) && !field.isFormField) {
79488                 field = Ext.ComponentManager.create(field, this.defaultFieldXType);
79489                 columnHeader.field = field;
79490             }
79491
79492             Ext.apply(field, {
79493                 name: columnHeader.dataIndex
79494             });
79495
79496             return field;
79497         }
79498     },
79499
79500     
79501     
79502     setColumnField: function(column, field) {
79503         if (Ext.isObject(field) && !field.isFormField) {
79504             field = Ext.ComponentManager.create(field, this.defaultFieldXType);
79505         }
79506         column.field = field;
79507     },
79508
79509     
79510     initEvents: function() {
79511         var me = this;
79512         me.initEditTriggers();
79513         me.initCancelTriggers();
79514     },
79515
79516     
79517     initCancelTriggers: Ext.emptyFn,
79518
79519     
79520     initEditTriggers: function() {
79521         var me = this,
79522             view = me.view,
79523             clickEvent = me.clicksToEdit === 1 ? 'click' : 'dblclick';
79524
79525         
79526         me.mon(view, 'cell' + clickEvent, me.startEditByClick, me);
79527         view.on('render', function() {
79528             me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
79529                 enter: me.onEnterKey,
79530                 esc: me.onEscKey,
79531                 scope: me
79532             });
79533         }, me, { single: true });
79534     },
79535
79536     
79537     onEnterKey: function(e) {
79538         var me = this,
79539             grid = me.grid,
79540             selModel = grid.getSelectionModel(),
79541             record,
79542             columnHeader = grid.headerCt.getHeaderAtIndex(0);
79543
79544         
79545         
79546         if (selModel.getCurrentPosition) {
79547             pos = selModel.getCurrentPosition();
79548             record = grid.store.getAt(pos.row);
79549             columnHeader = grid.headerCt.getHeaderAtIndex(pos.column);
79550         }
79551         
79552         else {
79553             record = selModel.getLastSelected();
79554         }
79555         me.startEdit(record, columnHeader);
79556     },
79557
79558     
79559     onEscKey: function(e) {
79560         this.cancelEdit();
79561     },
79562
79563     
79564     startEditByClick: function(view, cell, colIdx, record, row, rowIdx, e) {
79565         this.startEdit(record, view.getHeaderAtIndex(colIdx));
79566     },
79567
79568     
79569     beforeEdit: Ext.emptyFn,
79570
79571     
79572     startEdit: function(record, columnHeader) {
79573         var me = this,
79574             context = me.getEditingContext(record, columnHeader);
79575
79576         if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
79577             return false;
79578         }
79579
79580         me.context = context;
79581         me.editing = true;
79582     },
79583
79584     
79585     getEditingContext: function(record, columnHeader) {
79586         var me = this,
79587             grid = me.grid,
79588             store = grid.store,
79589             rowIdx,
79590             colIdx,
79591             view = grid.getView(),
79592             value;
79593
79594         
79595         if (Ext.isNumber(record)) {
79596             rowIdx = record;
79597             record = store.getAt(rowIdx);
79598         } else {
79599             rowIdx = store.indexOf(record);
79600         }
79601         if (Ext.isNumber(columnHeader)) {
79602             colIdx = columnHeader;
79603             columnHeader = grid.headerCt.getHeaderAtIndex(colIdx);
79604         } else {
79605             colIdx = columnHeader.getIndex();
79606         }
79607
79608         value = record.get(columnHeader.dataIndex);
79609         return {
79610             grid: grid,
79611             record: record,
79612             field: columnHeader.dataIndex,
79613             value: value,
79614             row: view.getNode(rowIdx),
79615             column: columnHeader,
79616             rowIdx: rowIdx,
79617             colIdx: colIdx
79618         };
79619     },
79620
79621     
79622     cancelEdit: function() {
79623         this.editing = false;
79624     },
79625
79626     
79627     completeEdit: function() {
79628         var me = this;
79629
79630         if (me.editing && me.validateEdit()) {
79631             me.fireEvent('edit', me.context);
79632         }
79633
79634         delete me.context;
79635         me.editing = false;
79636     },
79637
79638     
79639     validateEdit: function() {
79640         var me = this,
79641             context = me.context;
79642
79643         return me.fireEvent('validateedit', me, context) !== false && !context.cancel;
79644     }
79645 });
79646
79647 Ext.define('Ext.grid.plugin.CellEditing', {
79648     alias: 'plugin.cellediting',
79649     extend: 'Ext.grid.plugin.Editing',
79650     requires: ['Ext.grid.CellEditor'],
79651
79652     constructor: function() {
79653         
79654         
79655         
79656         this.callParent(arguments);
79657         this.editors = Ext.create('Ext.util.MixedCollection', false, function(editor) {
79658             return editor.editorId;
79659         });
79660     },
79661
79662     
79663     destroy: function() {
79664         var me = this;
79665         me.editors.each(Ext.destroy, Ext);
79666         me.editors.clear();
79667         me.callParent(arguments);
79668     },
79669     
79670     onBodyScroll: function() {
79671         var ed = this.getActiveEditor();
79672         if (ed && ed.field) {
79673             if (ed.field.triggerBlur) {
79674                 ed.field.triggerBlur();
79675             } else {
79676                 ed.field.blur();
79677             }
79678         }
79679     },
79680
79681     
79682     
79683     initCancelTriggers: function() {
79684         var me   = this,
79685             grid = me.grid,
79686             view = grid.view;
79687             
79688         view.addElListener('mousewheel', me.cancelEdit, me);
79689         me.mon(view, 'bodyscroll', me.onBodyScroll, me);
79690         me.mon(grid, {
79691             columnresize: me.cancelEdit,
79692             columnmove: me.cancelEdit,
79693             scope: me
79694         });
79695     },
79696
79697     
79698     startEdit: function(record, columnHeader) {
79699         var me = this,
79700             ed   = me.getEditor(record, columnHeader),
79701             value = record.get(columnHeader.dataIndex),
79702             context = me.getEditingContext(record, columnHeader);
79703
79704         record = context.record;
79705         columnHeader = context.column;
79706
79707         
79708         
79709         me.completeEdit();
79710
79711         
79712         if (columnHeader && !columnHeader.getEditor(record)) {
79713             return false;
79714         }
79715
79716         if (ed) {
79717             context.originalValue = context.value = value;
79718             if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
79719                 return false;
79720             }
79721
79722             me.context = context;
79723             me.setActiveEditor(ed);
79724             me.setActiveRecord(record);
79725             me.setActiveColumn(columnHeader);
79726
79727             
79728             Ext.defer(ed.startEdit, 15, ed, [me.getCell(record, columnHeader), value]);
79729         } else {
79730             
79731             
79732             
79733             
79734             me.grid.getView().el.focus((Ext.isWebKit || Ext.isIE) ? 10 : false);
79735         }
79736     },
79737
79738     completeEdit: function() {
79739         var activeEd = this.getActiveEditor();
79740         if (activeEd) {
79741             activeEd.completeEdit();
79742         }
79743     },
79744
79745     
79746     setActiveEditor: function(ed) {
79747         this.activeEditor = ed;
79748     },
79749
79750     getActiveEditor: function() {
79751         return this.activeEditor;
79752     },
79753
79754     setActiveColumn: function(column) {
79755         this.activeColumn = column;
79756     },
79757
79758     getActiveColumn: function() {
79759         return this.activeColumn;
79760     },
79761
79762     setActiveRecord: function(record) {
79763         this.activeRecord = record;
79764     },
79765
79766     getActiveRecord: function() {
79767         return this.activeRecord;
79768     },
79769
79770     getEditor: function(record, column) {
79771         var me = this,
79772             editors = me.editors,
79773             editorId = column.itemId || column.id,
79774             editor = editors.getByKey(editorId);
79775
79776         if (editor) {
79777             return editor;
79778         } else {
79779             editor = column.getEditor(record);
79780             if (!editor) {
79781                 return false;
79782             }
79783
79784             
79785             if (!(editor instanceof Ext.grid.CellEditor)) {
79786                 editor = Ext.create('Ext.grid.CellEditor', {
79787                     editorId: editorId,
79788                     field: editor
79789                 });
79790             }
79791             editor.parentEl = me.grid.getEditorParent();
79792             
79793             editor.on({
79794                 scope: me,
79795                 specialkey: me.onSpecialKey,
79796                 complete: me.onEditComplete,
79797                 canceledit: me.cancelEdit
79798             });
79799             editors.add(editor);
79800             return editor;
79801         }
79802     },
79803
79804     
79805     getCell: function(record, column) {
79806         return this.grid.getView().getCell(record, column);
79807     },
79808
79809     onSpecialKey: function(ed, field, e) {
79810         var grid = this.grid,
79811             sm;
79812         if (e.getKey() === e.TAB) {
79813             e.stopEvent();
79814             sm = grid.getSelectionModel();
79815             if (sm.onEditorTab) {
79816                 sm.onEditorTab(this, e);
79817             }
79818         }
79819     },
79820
79821     onEditComplete : function(ed, value, startValue) {
79822         var me = this,
79823             grid = me.grid,
79824             sm = grid.getSelectionModel(),
79825             activeColumn = me.getActiveColumn(),
79826             dataIndex;
79827
79828         if (activeColumn) {
79829             dataIndex = activeColumn.dataIndex;
79830
79831             me.setActiveEditor(null);
79832             me.setActiveColumn(null);
79833             me.setActiveRecord(null);
79834             delete sm.wasEditing;
79835     
79836             if (!me.validateEdit()) {
79837                 return;
79838             }
79839             
79840             
79841             if (value !== startValue) {
79842                 me.context.record.set(dataIndex, value);
79843             
79844             } else {
79845                 grid.getView().el.focus();
79846             }
79847             me.context.value = value;
79848             me.fireEvent('edit', me, me.context);
79849             
79850
79851         }
79852     },
79853
79854     
79855     cancelEdit: function() {
79856         var me = this,
79857             activeEd = me.getActiveEditor(),
79858             viewEl = me.grid.getView().el;
79859
79860         me.setActiveEditor(null);
79861         me.setActiveColumn(null);
79862         me.setActiveRecord(null);
79863         if (activeEd) {
79864             activeEd.cancelEdit();
79865             viewEl.focus();
79866         }
79867     },
79868
79869     
79870     startEditByPosition: function(position) {
79871         var me = this,
79872             grid = me.grid,
79873             sm = grid.getSelectionModel(),
79874             editRecord = grid.store.getAt(position.row),
79875             editColumnHeader = grid.headerCt.getHeaderAtIndex(position.column);
79876
79877         if (sm.selectByPosition) {
79878             sm.selectByPosition(position);
79879         }
79880         me.startEdit(editRecord, editColumnHeader);
79881     }
79882 });
79883
79884 Ext.define('Ext.grid.plugin.DragDrop', {
79885     extend: 'Ext.AbstractPlugin',
79886     alias: 'plugin.gridviewdragdrop',
79887
79888     uses: [
79889         'Ext.view.DragZone',
79890         'Ext.grid.ViewDropZone'
79891     ],
79892
79893     
79894
79895     
79896
79897     dragText : '{0} selected row{1}',
79898
79899     
79900     ddGroup : "GridDD",
79901
79902     
79903
79904     
79905
79906     
79907     enableDrop: true,
79908
79909     
79910     enableDrag: true,
79911
79912     init : function(view) {
79913         view.on('render', this.onViewRender, this, {single: true});
79914     },
79915
79916     
79917     destroy: function() {
79918         Ext.destroy(this.dragZone, this.dropZone);
79919     },
79920
79921     onViewRender : function(view) {
79922         var me = this;
79923
79924         if (me.enableDrag) {
79925             me.dragZone = Ext.create('Ext.view.DragZone', {
79926                 view: view,
79927                 ddGroup: me.dragGroup || me.ddGroup,
79928                 dragText: me.dragText
79929             });
79930         }
79931
79932         if (me.enableDrop) {
79933             me.dropZone = Ext.create('Ext.grid.ViewDropZone', {
79934                 view: view,
79935                 ddGroup: me.dropGroup || me.ddGroup
79936             });
79937         }
79938     }
79939 });
79940
79941 Ext.define('Ext.grid.plugin.HeaderReorderer', {
79942     extend: 'Ext.util.Observable',
79943     requires: ['Ext.grid.header.DragZone', 'Ext.grid.header.DropZone'],
79944     alias: 'plugin.gridheaderreorderer',
79945
79946     init: function(headerCt) {
79947         this.headerCt = headerCt;
79948         headerCt.on('render', this.onHeaderCtRender, this);
79949     },
79950
79951     
79952     destroy: function() {
79953         Ext.destroy(this.dragZone, this.dropZone);
79954     },
79955
79956     onHeaderCtRender: function() {
79957         this.dragZone = Ext.create('Ext.grid.header.DragZone', this.headerCt);
79958         this.dropZone = Ext.create('Ext.grid.header.DropZone', this.headerCt);
79959         if (this.disabled) {
79960             this.dragZone.disable();
79961         }
79962     },
79963     
79964     enable: function() {
79965         this.disabled = false;
79966         if (this.dragZone) {
79967             this.dragZone.enable();
79968         }
79969     },
79970     
79971     disable: function() {
79972         this.disabled = true;
79973         if (this.dragZone) {
79974             this.dragZone.disable();
79975         }
79976     }
79977 });
79978
79979 Ext.define('Ext.grid.plugin.HeaderResizer', {
79980     extend: 'Ext.util.Observable',
79981     requires: ['Ext.dd.DragTracker', 'Ext.util.Region'],
79982     alias: 'plugin.gridheaderresizer',
79983     
79984     disabled: false,
79985
79986     
79987     configs: {
79988         dynamic: true
79989     },
79990
79991     colHeaderCls: Ext.baseCSSPrefix + 'column-header',
79992
79993     minColWidth: 40,
79994     maxColWidth: 1000,
79995     wResizeCursor: 'col-resize',
79996     eResizeCursor: 'col-resize',
79997     
79998     
79999     
80000     
80001
80002     init: function(headerCt) {
80003         this.headerCt = headerCt;
80004         headerCt.on('render', this.afterHeaderRender, this, {single: true});
80005     },
80006
80007     
80008     destroy: function() {
80009         if (this.tracker) {
80010             this.tracker.destroy();
80011         }
80012     },
80013
80014     afterHeaderRender: function() {
80015         var headerCt = this.headerCt,
80016             el = headerCt.el;
80017
80018         headerCt.mon(el, 'mousemove', this.onHeaderCtMouseMove, this);
80019
80020         this.tracker = Ext.create('Ext.dd.DragTracker', {
80021             disabled: this.disabled,
80022             onBeforeStart: Ext.Function.bind(this.onBeforeStart, this),
80023             onStart: Ext.Function.bind(this.onStart, this),
80024             onDrag: Ext.Function.bind(this.onDrag, this),
80025             onEnd: Ext.Function.bind(this.onEnd, this),
80026             tolerance: 3,
80027             autoStart: 300,
80028             el: el
80029         });
80030     },
80031
80032     
80033     
80034     
80035     onHeaderCtMouseMove: function(e, t) {
80036         if (this.headerCt.dragging) {
80037             if (this.activeHd) {
80038                 this.activeHd.el.dom.style.cursor = '';
80039                 delete this.activeHd;
80040             }
80041         } else {
80042             var headerEl = e.getTarget('.' + this.colHeaderCls, 3, true),
80043                 overHeader, resizeHeader;
80044
80045             if (headerEl){
80046                 overHeader = Ext.getCmp(headerEl.id);
80047
80048                 
80049                 if (overHeader.isOnLeftEdge(e)) {
80050                     resizeHeader = overHeader.previousNode('gridcolumn:not([hidden]):not([isGroupHeader])');
80051                 }
80052                 
80053                 else if (overHeader.isOnRightEdge(e)) {
80054                     resizeHeader = overHeader;
80055                 }
80056                 
80057                 else {
80058                     resizeHeader = null;
80059                 }
80060
80061                 
80062                 if (resizeHeader) {
80063                     
80064                     
80065                     
80066                     if (resizeHeader.isGroupHeader) {
80067                         resizeHeader = resizeHeader.getVisibleGridColumns();
80068                         resizeHeader = resizeHeader[resizeHeader.length - 1];
80069                     }
80070
80071                     if (resizeHeader && !resizeHeader.fixed) {
80072                         this.activeHd = resizeHeader;
80073                         overHeader.el.dom.style.cursor = this.eResizeCursor;
80074                     }
80075                 
80076                 } else {
80077                     overHeader.el.dom.style.cursor = '';
80078                     delete this.activeHd;
80079                 }
80080             }
80081         }
80082     },
80083
80084     
80085     onBeforeStart : function(e){
80086         var t = e.getTarget();
80087         
80088         this.dragHd = this.activeHd;
80089
80090         if (!!this.dragHd && !Ext.fly(t).hasCls('x-column-header-trigger') && !this.headerCt.dragging) {
80091             
80092             this.tracker.constrainTo = this.getConstrainRegion();
80093             return true;
80094         } else {
80095             this.headerCt.dragging = false;
80096             return false;
80097         }
80098     },
80099
80100     
80101     getConstrainRegion: function() {
80102         var dragHdEl = this.dragHd.el,
80103             region   = Ext.util.Region.getRegion(dragHdEl);
80104
80105         return region.adjust(
80106             0,
80107             this.maxColWidth - dragHdEl.getWidth(),
80108             0,
80109             this.minColWidth
80110         );
80111     },
80112
80113     
80114     
80115     onStart: function(e){
80116         var me       = this,
80117             dragHd   = me.dragHd,
80118             dragHdEl = dragHd.el,
80119             width    = dragHdEl.getWidth(),
80120             headerCt = me.headerCt,
80121             t        = e.getTarget();
80122
80123         if (me.dragHd && !Ext.fly(t).hasCls('x-column-header-trigger')) {
80124             headerCt.dragging = true;
80125         }
80126
80127         me.origWidth = width;
80128
80129         
80130         if (!me.dynamic) {
80131             var xy           = dragHdEl.getXY(),
80132                 gridSection  = headerCt.up('[scrollerOwner]'),
80133                 dragHct      = me.dragHd.up(':not([isGroupHeader])'),
80134                 firstSection = dragHct.up(),
80135                 lhsMarker    = gridSection.getLhsMarker(),
80136                 rhsMarker    = gridSection.getRhsMarker(),
80137                 el           = rhsMarker.parent(),
80138                 offsetLeft   = el.getLeft(true),
80139                 offsetTop    = el.getTop(true),
80140                 topLeft      = el.translatePoints(xy),
80141                 markerHeight = firstSection.body.getHeight() + headerCt.getHeight(),
80142                 top = topLeft.top - offsetTop;
80143
80144             lhsMarker.setTop(top);
80145             rhsMarker.setTop(top);
80146             lhsMarker.setHeight(markerHeight);
80147             rhsMarker.setHeight(markerHeight);
80148             lhsMarker.setLeft(topLeft.left - offsetLeft);
80149             rhsMarker.setLeft(topLeft.left + width - offsetLeft);
80150         }
80151     },
80152
80153     
80154     onDrag: function(e){
80155         if (!this.dynamic) {
80156             var xy          = this.tracker.getXY('point'),
80157                 gridSection = this.headerCt.up('[scrollerOwner]'),
80158                 rhsMarker   = gridSection.getRhsMarker(),
80159                 el          = rhsMarker.parent(),
80160                 topLeft     = el.translatePoints(xy),
80161                 offsetLeft  = el.getLeft(true);
80162
80163             rhsMarker.setLeft(topLeft.left - offsetLeft);
80164         
80165         } else {
80166             this.doResize();
80167         }
80168     },
80169
80170     onEnd: function(e){
80171         this.headerCt.dragging = false;
80172         if (this.dragHd) {
80173             if (!this.dynamic) {
80174                 var dragHd      = this.dragHd,
80175                     gridSection = this.headerCt.up('[scrollerOwner]'),
80176                     lhsMarker   = gridSection.getLhsMarker(),
80177                     rhsMarker   = gridSection.getRhsMarker(),
80178                     currWidth   = dragHd.getWidth(),
80179                     offset      = this.tracker.getOffset('point'),
80180                     offscreen   = -9999;
80181
80182                 
80183                 lhsMarker.setLeft(offscreen);
80184                 rhsMarker.setLeft(offscreen);
80185             }
80186             this.doResize();
80187         }
80188     },
80189
80190     doResize: function() {
80191         if (this.dragHd) {
80192             var dragHd = this.dragHd,
80193                 nextHd,
80194                 offset = this.tracker.getOffset('point');
80195
80196             
80197             if (dragHd.flex) {
80198                 delete dragHd.flex;
80199             }
80200
80201             
80202             
80203             if (this.headerCt.forceFit) {
80204                 nextHd = dragHd.nextNode('gridcolumn:not([hidden]):not([isGroupHeader])');
80205                 if (nextHd) {
80206                     this.headerCt.componentLayout.layoutBusy = true;
80207                 }
80208             }
80209
80210             
80211             
80212             dragHd.minWidth = this.origWidth + offset[0];
80213             dragHd.setWidth(dragHd.minWidth);
80214
80215             
80216             
80217             if (nextHd) {
80218                 delete nextHd.flex;
80219                 nextHd.setWidth(nextHd.getWidth() - offset[0]);
80220                 this.headerCt.componentLayout.layoutBusy = false;
80221                 this.headerCt.doComponentLayout();
80222             }
80223         }
80224     },
80225     
80226     disable: function() {
80227         this.disabled = true;
80228         if (this.tracker) {
80229             this.tracker.disable();
80230         }
80231     },
80232     
80233     enable: function() {
80234         this.disabled = false;
80235         if (this.tracker) {
80236             this.tracker.enable();
80237         }
80238     }
80239 });
80240
80241 Ext.define('Ext.grid.plugin.RowEditing', {
80242     extend: 'Ext.grid.plugin.Editing',
80243     alias: 'plugin.rowediting',
80244
80245     requires: [
80246         'Ext.grid.RowEditor'
80247     ],
80248
80249     editStyle: 'row',
80250
80251     
80252     autoCancel: true,
80253
80254     
80255
80256     
80257     errorSummary: true,
80258
80259     
80260     
80261     
80262
80263     constructor: function() {
80264         var me = this;
80265         me.callParent(arguments);
80266
80267         if (!me.clicksToMoveEditor) {
80268             me.clicksToMoveEditor = me.clicksToEdit;
80269         }
80270
80271         me.autoCancel = !!me.autoCancel;
80272     },
80273
80274     
80275     destroy: function() {
80276         var me = this;
80277         Ext.destroy(me.editor);
80278         me.callParent(arguments);
80279     },
80280
80281     
80282     startEdit: function(record, columnHeader) {
80283         var me = this,
80284             editor = me.getEditor();
80285
80286         if (me.callParent(arguments) === false) {
80287             return false;
80288         }
80289
80290         
80291         if (editor.beforeEdit() !== false) {
80292             editor.startEdit(me.context.record, me.context.column);
80293         }
80294     },
80295
80296     
80297     cancelEdit: function() {
80298         var me = this;
80299
80300         if (me.editing) {
80301             me.getEditor().cancelEdit();
80302             me.callParent(arguments);
80303         }
80304     },
80305
80306     
80307     completeEdit: function() {
80308         var me = this;
80309
80310         if (me.editing && me.validateEdit()) {
80311             me.editing = false;
80312             me.fireEvent('edit', me.context);
80313         }
80314     },
80315
80316     
80317     validateEdit: function() {
80318         var me = this;
80319         return me.callParent(arguments) && me.getEditor().completeEdit();
80320     },
80321
80322     
80323     getEditor: function() {
80324         var me = this;
80325
80326         if (!me.editor) {
80327             me.editor = me.initEditor();
80328         }
80329         return me.editor;
80330     },
80331
80332     
80333     initEditor: function() {
80334         var me = this,
80335             grid = me.grid,
80336             view = me.view,
80337             headerCt = grid.headerCt;
80338
80339         return Ext.create('Ext.grid.RowEditor', {
80340             autoCancel: me.autoCancel,
80341             errorSummary: me.errorSummary,
80342             fields: headerCt.getGridColumns(),
80343             hidden: true,
80344
80345             
80346             editingPlugin: me,
80347             renderTo: view.el
80348         });
80349     },
80350
80351     
80352     initEditTriggers: function() {
80353         var me = this,
80354             grid = me.grid,
80355             view = me.view,
80356             headerCt = grid.headerCt,
80357             moveEditorEvent = me.clicksToMoveEditor === 1 ? 'click' : 'dblclick';
80358
80359         me.callParent(arguments);
80360
80361         if (me.clicksToMoveEditor !== me.clicksToEdit) {
80362             me.mon(view, 'cell' + moveEditorEvent, me.moveEditorByClick, me);
80363         }
80364
80365         view.on('render', function() {
80366             
80367             me.mon(headerCt, {
80368                 add: me.onColumnAdd,
80369                 remove: me.onColumnRemove,
80370                 columnresize: me.onColumnResize,
80371                 columnhide: me.onColumnHide,
80372                 columnshow: me.onColumnShow,
80373                 columnmove: me.onColumnMove,
80374                 scope: me
80375             });
80376         }, me, { single: true });
80377     },
80378
80379     startEditByClick: function() {
80380         var me = this;
80381         if (!me.editing || me.clicksToMoveEditor === me.clicksToEdit) {
80382             me.callParent(arguments);
80383         }
80384     },
80385
80386     moveEditorByClick: function() {
80387         var me = this;
80388         if (me.editing) {
80389             me.superclass.startEditByClick.apply(me, arguments);
80390         }
80391     },
80392
80393     
80394     onColumnAdd: function(ct, column) {
80395         if (column.isHeader) {
80396             var me = this,
80397                 editor;
80398             
80399             me.initFieldAccessors(column);
80400             editor = me.getEditor();
80401             
80402             if (editor && editor.onColumnAdd) {
80403                 editor.onColumnAdd(column);
80404             }
80405         }
80406     },
80407
80408     
80409     onColumnRemove: function(ct, column) {
80410         if (column.isHeader) {
80411             var me = this,
80412                 editor = me.getEditor();
80413     
80414             if (editor && editor.onColumnRemove) {
80415                 editor.onColumnRemove(column);
80416             }
80417             me.removeFieldAccessors(column);  
80418         }
80419     },
80420
80421     
80422     onColumnResize: function(ct, column, width) {
80423         if (column.isHeader) {
80424             var me = this,
80425                 editor = me.getEditor();
80426     
80427             if (editor && editor.onColumnResize) {
80428                 editor.onColumnResize(column, width);
80429             }
80430         }
80431     },
80432
80433     
80434     onColumnHide: function(ct, column) {
80435         
80436         var me = this,
80437             editor = me.getEditor();
80438
80439         if (editor && editor.onColumnHide) {
80440             editor.onColumnHide(column);
80441         }
80442     },
80443
80444     
80445     onColumnShow: function(ct, column) {
80446         
80447         var me = this,
80448             editor = me.getEditor();
80449
80450         if (editor && editor.onColumnShow) {
80451             editor.onColumnShow(column);
80452         }
80453     },
80454
80455     
80456     onColumnMove: function(ct, column, fromIdx, toIdx) {
80457         
80458         var me = this,
80459             editor = me.getEditor();
80460
80461         if (editor && editor.onColumnMove) {
80462             editor.onColumnMove(column, fromIdx, toIdx);
80463         }
80464     },
80465
80466     
80467     setColumnField: function(column, field) {
80468         var me = this;
80469         me.callParent(arguments);
80470         me.getEditor().setField(column.field, column);
80471     }
80472 });
80473
80474 Ext.define('Ext.grid.property.Grid', {
80475
80476     extend: 'Ext.grid.Panel',
80477     
80478     alias: 'widget.propertygrid',
80479
80480     alternateClassName: 'Ext.grid.PropertyGrid',
80481
80482     uses: [
80483        'Ext.grid.plugin.CellEditing',
80484        'Ext.grid.property.Store',
80485        'Ext.grid.property.HeaderContainer',
80486        'Ext.XTemplate',
80487        'Ext.grid.CellEditor',
80488        'Ext.form.field.Date',
80489        'Ext.form.field.Text',
80490        'Ext.form.field.Number'
80491     ],
80492
80493    
80494
80495     
80496
80497     
80498
80499     
80500
80501     
80502
80503     
80504     valueField: 'value',
80505
80506     
80507     nameField: 'name',
80508
80509     
80510     enableColumnMove: false,
80511     columnLines: true,
80512     stripeRows: false,
80513     trackMouseOver: false,
80514     clicksToEdit: 1,
80515     enableHdMenu: false,
80516
80517     
80518     initComponent : function(){
80519         var me = this;
80520
80521         me.addCls(Ext.baseCSSPrefix + 'property-grid');
80522         me.plugins = me.plugins || [];
80523
80524         
80525         me.plugins.push(Ext.create('Ext.grid.plugin.CellEditing', {
80526             clicksToEdit: me.clicksToEdit,
80527
80528             
80529             startEdit: function(record, column) {
80530                 
80531                 Ext.grid.plugin.CellEditing.prototype.startEdit.call(this, record, me.headerCt.child('#' + me.valueField));
80532             }
80533         }));
80534
80535         me.selModel = {
80536             selType: 'cellmodel',
80537             onCellSelect: function(position) {
80538                 if (position.column != 1) {
80539                     position.column = 1;
80540                     Ext.selection.CellModel.prototype.onCellSelect.call(this, position);
80541                 }
80542             }
80543         };
80544         me.customRenderers = me.customRenderers || {};
80545         me.customEditors = me.customEditors || {};
80546
80547         
80548         if (!me.store) {
80549             me.propStore = me.store = Ext.create('Ext.grid.property.Store', me, me.source);
80550         }
80551
80552         me.store.sort('name', 'ASC');
80553         me.columns = Ext.create('Ext.grid.property.HeaderContainer', me, me.store);
80554
80555         me.addEvents(
80556             
80557             'beforepropertychange',
80558             
80559             'propertychange'
80560         );
80561         me.callParent();
80562
80563         
80564         me.getView().walkCells = this.walkCells;
80565
80566         
80567         me.editors = {
80568             'date'    : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Date',   {selectOnFocus: true})}),
80569             'string'  : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Text',   {selectOnFocus: true})}),
80570             'number'  : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Number', {selectOnFocus: true})}),
80571             'boolean' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.ComboBox', {
80572                 editable: false,
80573                 store: [[ true, me.headerCt.trueText ], [false, me.headerCt.falseText ]]
80574             })})
80575         };
80576
80577         
80578         this.store.on('update', me.onUpdate, me);
80579     },
80580
80581     
80582     onUpdate : function(store, record, operation) {
80583         var me = this,
80584             v, oldValue;
80585
80586         if (operation == Ext.data.Model.EDIT) {
80587             v = record.get(me.valueField);
80588             oldValue = record.modified.value;
80589             if (me.fireEvent('beforepropertychange', me.source, record.getId(), v, oldValue) !== false) {
80590                 if (me.source) {
80591                     me.source[record.getId()] = v;
80592                 }
80593                 record.commit();
80594                 me.fireEvent('propertychange', me.source, record.getId(), v, oldValue);
80595             } else {
80596                 record.reject();
80597             }
80598         }
80599     },
80600
80601     
80602     walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
80603         if (direction == 'left') {
80604             direction = 'up';
80605         } else if (direction == 'right') {
80606             direction = 'down';
80607         }
80608         pos = Ext.view.Table.prototype.walkCells.call(this, pos, direction, e, preventWrap, verifierFn, scope);
80609         if (!pos.column) {
80610             pos.column = 1;
80611         }
80612         return pos;
80613     },
80614
80615     
80616     
80617     getCellEditor : function(record, column) {
80618         var me = this,
80619             propName = record.get(me.nameField), 
80620             val = record.get(me.valueField),
80621             editor = me.customEditors[propName];
80622
80623         
80624         
80625         if (editor) {
80626             if (!(editor instanceof Ext.grid.CellEditor)) {
80627                 if (!(editor instanceof Ext.form.field.Base)) {
80628                     editor = Ext.ComponentManager.create(editor, 'textfield');
80629                 }
80630                 editor = me.customEditors[propName] = Ext.create('Ext.grid.CellEditor', { field: editor });
80631             }
80632         } else if (Ext.isDate(val)) {
80633             editor = me.editors.date;
80634         } else if (Ext.isNumber(val)) {
80635             editor = me.editors.number;
80636         } else if (Ext.isBoolean(val)) {
80637             editor = me.editors['boolean'];
80638         } else {
80639             editor = me.editors.string;
80640         }
80641
80642         
80643         editor.editorId = propName;
80644         return editor;
80645     },
80646
80647     beforeDestroy: function() {
80648         var me = this;
80649         me.callParent();
80650         me.destroyEditors(me.editors);
80651         me.destroyEditors(me.customEditors);
80652         delete me.source;
80653     },
80654
80655     destroyEditors: function (editors) {
80656         for (var ed in editors) {
80657             if (editors.hasOwnProperty(ed)) {
80658                 Ext.destroy(editors[ed]);
80659             }
80660         }
80661     },
80662
80663     
80664     setSource: function(source) {
80665         this.source = source;
80666         this.propStore.setSource(source);
80667     },
80668
80669     
80670     getSource: function() {
80671         return this.propStore.getSource();
80672     },
80673
80674     
80675     setProperty: function(prop, value, create) {
80676         this.propStore.setValue(prop, value, create);
80677     },
80678
80679     
80680     removeProperty: function(prop) {
80681         this.propStore.remove(prop);
80682     }
80683
80684     
80685     
80686     
80687     
80688 });
80689
80690 Ext.define('Ext.grid.property.HeaderContainer', {
80691
80692     extend: 'Ext.grid.header.Container',
80693
80694     alternateClassName: 'Ext.grid.PropertyColumnModel',
80695
80696     
80697     nameText : 'Name',
80698     valueText : 'Value',
80699     dateFormat : 'm/j/Y',
80700     trueText: 'true',
80701     falseText: 'false',
80702
80703     
80704     nameColumnCls: Ext.baseCSSPrefix + 'grid-property-name',
80705     
80706     constructor : function(grid, store) {
80707
80708         this.grid = grid;
80709         this.store = store;
80710         this.callParent([{
80711             items: [{
80712                 header: this.nameText,
80713                 width: 115,
80714                 sortable: true,
80715                 dataIndex: grid.nameField,
80716                 renderer: Ext.Function.bind(this.renderProp, this),
80717                 itemId: grid.nameField,
80718                 menuDisabled :true,
80719                 tdCls: this.nameColumnCls
80720             }, {
80721                 header: this.valueText,
80722                 renderer: Ext.Function.bind(this.renderCell, this),
80723                 getEditor: function(record) {
80724                     return grid.getCellEditor(record, this);
80725                 },
80726                 flex: 1,
80727                 fixed: true,
80728                 dataIndex: grid.valueField,
80729                 itemId: grid.valueField,
80730                 menuDisabled: true
80731             }]
80732         }]);
80733     },
80734
80735     
80736     
80737     renderProp : function(v) {
80738         return this.getPropertyName(v);
80739     },
80740
80741     
80742     
80743     renderCell : function(val, meta, rec) {
80744         var me = this,
80745             renderer = this.grid.customRenderers[rec.get(me.grid.nameField)],
80746             result = val;
80747
80748         if (renderer) {
80749             return renderer.apply(this, arguments);
80750         }
80751         if (Ext.isDate(val)) {
80752             result = this.renderDate(val);
80753         } else if (Ext.isBoolean(val)) {
80754             result = this.renderBool(val);
80755         }
80756         return Ext.util.Format.htmlEncode(result);
80757     },
80758
80759     
80760     renderDate : Ext.util.Format.date,
80761
80762     
80763     renderBool : function(bVal) {
80764         return this[bVal ? 'trueText' : 'falseText'];
80765     },
80766
80767     
80768     
80769     getPropertyName : function(name) {
80770         var pn = this.grid.propertyNames;
80771         return pn && pn[name] ? pn[name] : name;
80772     }
80773 });
80774
80775 Ext.define('Ext.grid.property.Property', {
80776     extend: 'Ext.data.Model',
80777
80778     alternateClassName: 'Ext.PropGridProperty',
80779
80780     fields: [{
80781         name: 'name',
80782         type: 'string'
80783     }, {
80784         name: 'value'
80785     }],
80786     idProperty: 'name'
80787 });
80788
80789 Ext.define('Ext.grid.property.Store', {
80790
80791     extend: 'Ext.data.Store',
80792
80793     alternateClassName: 'Ext.grid.PropertyStore',
80794
80795     uses: ['Ext.data.reader.Reader', 'Ext.data.proxy.Proxy', 'Ext.data.ResultSet', 'Ext.grid.property.Property'],
80796
80797     constructor : function(grid, source){
80798         var me = this;
80799         
80800         me.grid = grid;
80801         me.source = source;
80802         me.callParent([{
80803             data: source,
80804             model: Ext.grid.property.Property,
80805             proxy: me.getProxy()
80806         }]);
80807     },
80808
80809     
80810     getProxy: function() {
80811         if (!this.proxy) {
80812             Ext.grid.property.Store.prototype.proxy = Ext.create('Ext.data.proxy.Memory', {
80813                 model: Ext.grid.property.Property,
80814                 reader: this.getReader()
80815             });
80816         }
80817         return this.proxy;
80818     },
80819
80820     
80821     getReader: function() {
80822         if (!this.reader) {
80823             Ext.grid.property.Store.prototype.reader = Ext.create('Ext.data.reader.Reader', {
80824                 model: Ext.grid.property.Property,
80825
80826                 buildExtractors: Ext.emptyFn,
80827
80828                 read: function(dataObject) {
80829                     return this.readRecords(dataObject);
80830                 },
80831
80832                 readRecords: function(dataObject) {
80833                     var val,
80834                         propName,
80835                         result = {
80836                             records: [],
80837                             success: true
80838                         };
80839
80840                     for (propName in dataObject) {
80841                         if (dataObject.hasOwnProperty(propName)) {
80842                             val = dataObject[propName];
80843                             if (this.isEditableValue(val)) {
80844                                 result.records.push(new Ext.grid.property.Property({
80845                                     name: propName,
80846                                     value: val
80847                                 }, propName));
80848                             }
80849                         }
80850                     }
80851                     result.total = result.count = result.records.length;
80852                     return Ext.create('Ext.data.ResultSet', result);
80853                 },
80854
80855                 
80856                 isEditableValue: function(val){
80857                     return Ext.isPrimitive(val) || Ext.isDate(val);
80858                 }
80859             });
80860         }
80861         return this.reader;
80862     },
80863
80864     
80865     setSource : function(dataObject) {
80866         var me = this;
80867
80868         me.source = dataObject;
80869         me.suspendEvents();
80870         me.removeAll();
80871         me.proxy.data = dataObject;
80872         me.load();
80873         me.resumeEvents();
80874         me.fireEvent('datachanged', me);
80875     },
80876
80877     
80878     getProperty : function(row) {
80879        return Ext.isNumber(row) ? this.getAt(row) : this.getById(row);
80880     },
80881
80882     
80883     setValue : function(prop, value, create){
80884         var me = this,
80885             rec = me.getRec(prop);
80886             
80887         if (rec) {
80888             rec.set('value', value);
80889             me.source[prop] = value;
80890         } else if (create) {
80891             
80892             me.source[prop] = value;
80893             rec = new Ext.grid.property.Property({name: prop, value: value}, prop);
80894             me.store.add(rec);
80895         }
80896     },
80897
80898     
80899     remove : function(prop) {
80900         var rec = this.getRec(prop);
80901         if (rec) {
80902             store.remove(rec);
80903             delete this.source[prop];
80904         }
80905     },
80906
80907     
80908     getRec : function(prop) {
80909         return this.getById(prop);
80910     },
80911
80912     
80913     getSource : function() {
80914         return this.source;
80915     }
80916 });
80917
80918
80919 Ext.define('Ext.layout.component.Body', {
80920
80921     
80922
80923     alias: ['layout.body'],
80924
80925     extend: 'Ext.layout.component.Component',
80926
80927     uses: ['Ext.layout.container.Container'],
80928
80929     
80930
80931     type: 'body',
80932     
80933     onLayout: function(width, height) {
80934         var me = this,
80935             owner = me.owner;
80936
80937         
80938         me.setTargetSize(width, height);
80939
80940         
80941         me.setBodySize.apply(me, arguments);
80942
80943         
80944         if (owner && owner.layout && owner.layout.isLayout) {
80945             if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
80946                 owner.layout.bindToOwnerCtComponent = true;
80947             }
80948             else {
80949                 owner.layout.bindToOwnerCtComponent = false;
80950             }
80951         }
80952         
80953         me.callParent(arguments);
80954     },
80955
80956     
80957     setBodySize: function(width, height) {
80958         var me = this,
80959             owner = me.owner,
80960             frameSize = owner.frameSize,
80961             isNumber = Ext.isNumber;
80962
80963         if (isNumber(width)) {
80964             width -= owner.el.getFrameWidth('lr') - frameSize.left - frameSize.right;
80965         }
80966         if (isNumber(height)) {
80967             height -= owner.el.getFrameWidth('tb') - frameSize.top - frameSize.bottom;
80968         }
80969
80970         me.setElementSize(owner.body, width, height);
80971     }
80972 });
80973
80974 Ext.define('Ext.layout.component.FieldSet', {
80975     extend: 'Ext.layout.component.Body',
80976     alias: ['layout.fieldset'],
80977
80978     type: 'fieldset',
80979
80980     doContainerLayout: function() {
80981         
80982         if (!this.owner.collapsed) {
80983             this.callParent();
80984         }
80985     }
80986 });
80987
80988 Ext.define('Ext.layout.component.Tab', {
80989
80990     alias: ['layout.tab'],
80991
80992     extend: 'Ext.layout.component.Button',
80993
80994     
80995
80996     beforeLayout: function() {
80997         var me = this, dirty = me.lastClosable !== me.owner.closable;
80998
80999         if (dirty) {
81000             delete me.adjWidth;
81001         }
81002
81003         return this.callParent(arguments) || dirty;
81004     },
81005
81006     onLayout: function () {
81007         var me = this;
81008
81009         me.callParent(arguments);
81010
81011         me.lastClosable = me.owner.closable;
81012     }
81013 });
81014
81015
81016 Ext.define('Ext.layout.component.field.File', {
81017     alias: ['layout.filefield'],
81018     extend: 'Ext.layout.component.field.Field',
81019
81020     type: 'filefield',
81021
81022     sizeBodyContents: function(width, height) {
81023         var me = this,
81024             owner = me.owner;
81025
81026         if (!owner.buttonOnly) {
81027             
81028             
81029             me.setElementSize(owner.inputEl, Ext.isNumber(width) ? width - owner.button.getWidth() - owner.buttonMargin : width);
81030         }
81031     }
81032 });
81033
81034
81035 Ext.define('Ext.layout.component.field.Slider', {
81036
81037     
81038
81039     alias: ['layout.sliderfield'],
81040
81041     extend: 'Ext.layout.component.field.Field',
81042
81043     
81044
81045     type: 'sliderfield',
81046
81047     sizeBodyContents: function(width, height) {
81048         var owner = this.owner,
81049             thumbs = owner.thumbs,
81050             length = thumbs.length,
81051             inputEl = owner.inputEl,
81052             innerEl = owner.innerEl,
81053             endEl = owner.endEl,
81054             i = 0;
81055
81056         
81057         for(; i < length; ++i) {
81058             thumbs[i].el.stopAnimation();
81059         }
81060         
81061         if (owner.vertical) {
81062             inputEl.setHeight(height);
81063             innerEl.setHeight(Ext.isNumber(height) ? height - inputEl.getPadding('t') - endEl.getPadding('b') : height);
81064         }
81065         else {
81066             inputEl.setWidth(width);
81067             innerEl.setWidth(Ext.isNumber(width) ? width - inputEl.getPadding('l') - endEl.getPadding('r') : width);
81068         }
81069         owner.syncThumbs();
81070     }
81071 });
81072
81073
81074
81075 Ext.define('Ext.layout.container.Absolute', {
81076
81077     
81078
81079     alias: 'layout.absolute',
81080     extend: 'Ext.layout.container.Anchor',
81081     requires: ['Ext.chart.axis.Axis', 'Ext.fx.Anim'],
81082     alternateClassName: 'Ext.layout.AbsoluteLayout',
81083
81084     
81085
81086     itemCls: Ext.baseCSSPrefix + 'abs-layout-item',
81087
81088     type: 'absolute',
81089
81090     onLayout: function() {
81091         var me = this,
81092             target = me.getTarget(),
81093             targetIsBody = target.dom === document.body;
81094
81095         
81096         if (!targetIsBody) {
81097             target.position();
81098         }
81099         me.paddingLeft = target.getPadding('l');
81100         me.paddingTop = target.getPadding('t');
81101         me.callParent(arguments);
81102     },
81103
81104     
81105     adjustWidthAnchor: function(value, comp) {
81106         
81107         return value ? value - comp.getPosition(true)[0] : value;
81108     },
81109
81110     
81111     adjustHeightAnchor: function(value, comp) {
81112         
81113         return value ? value - comp.getPosition(true)[1] : value;
81114     }
81115 });
81116
81117 Ext.define('Ext.layout.container.Accordion', {
81118     extend: 'Ext.layout.container.VBox',
81119     alias: ['layout.accordion'],
81120     alternateClassName: 'Ext.layout.AccordionLayout',
81121     
81122     align: 'stretch',
81123
81124     
81125     fill : true,
81126     
81127     autoWidth : true,
81128     
81129     titleCollapse : true,
81130     
81131     hideCollapseTool : false,
81132     
81133     collapseFirst : false,
81134     
81135     animate : true,
81136     
81137     activeOnTop : false,
81138     
81139     multi: false,
81140
81141     constructor: function() {
81142         var me = this;
81143
81144         me.callParent(arguments);
81145
81146         
81147         me.initialAnimate = me.animate;
81148         me.animate = false;
81149
81150         
81151         if (me.fill === false) {
81152             me.itemCls = Ext.baseCSSPrefix + 'accordion-item';
81153         }
81154     },
81155
81156     
81157     
81158     beforeLayout: function() {
81159         var me = this;
81160
81161         me.callParent(arguments);
81162         if (me.fill) {
81163             if (!me.owner.el.dom.style.height) {
81164                 return false;
81165             }
81166         } else {
81167             me.owner.componentLayout.monitorChildren = false;
81168             me.autoSize = true;
81169             me.owner.setAutoScroll(true);
81170         }
81171     },
81172
81173     renderItems : function(items, target) {
81174         var me = this,
81175             ln = items.length,
81176             i = 0,
81177             comp,
81178             targetSize = me.getLayoutTargetSize(),
81179             renderedPanels = [],
81180             border;
81181
81182         for (; i < ln; i++) {
81183             comp = items[i];
81184             if (!comp.rendered) {
81185                 renderedPanels.push(comp);
81186
81187                 
81188                 if (me.collapseFirst) {
81189                     comp.collapseFirst = me.collapseFirst;
81190                 }
81191                 if (me.hideCollapseTool) {
81192                     comp.hideCollapseTool = me.hideCollapseTool;
81193                     comp.titleCollapse = true;
81194                 }
81195                 else if (me.titleCollapse) {
81196                     comp.titleCollapse = me.titleCollapse;
81197                 }
81198
81199                 delete comp.hideHeader;
81200                 comp.collapsible = true;
81201                 comp.title = comp.title || '&#160;';
81202                 comp.setBorder(false);
81203
81204                 
81205                 comp.width = targetSize.width;
81206                 if (me.fill) {
81207                     delete comp.height;
81208                     delete comp.flex;
81209
81210                     
81211                     if (me.expandedItem !== undefined) {
81212                         comp.collapsed = true;
81213                     }
81214                     
81215                     else if (comp.collapsed === false) {
81216                         comp.flex = 1;
81217                         me.expandedItem = i;
81218                     } else {
81219                         comp.collapsed = true;
81220                     }
81221                 } else {
81222                     delete comp.flex;
81223                     comp.animCollapse = me.initialAnimate;
81224                     comp.autoHeight = true;
81225                     comp.autoScroll = false;
81226                 }
81227             }
81228         }
81229
81230         
81231         if (ln && me.expandedItem === undefined) {
81232             me.expandedItem = 0;
81233             comp = items[0];
81234             comp.collapsed = false;
81235             if (me.fill) {
81236                 comp.flex = 1;
81237             }
81238         }
81239         
81240         
81241         me.callParent(arguments);
81242                 
81243         
81244         ln = renderedPanels.length;
81245         for (i = 0; i < ln; i++) {
81246             comp = renderedPanels[i];
81247
81248             
81249             delete comp.width;
81250
81251             comp.header.addCls(Ext.baseCSSPrefix + 'accordion-hd');
81252             comp.body.addCls(Ext.baseCSSPrefix + 'accordion-body');
81253             
81254             
81255             if (me.fill) {
81256                 me.owner.mon(comp, {
81257                     show: me.onComponentShow,
81258                     beforeexpand: me.onComponentExpand,
81259                     beforecollapse: me.onComponentCollapse,
81260                     scope: me
81261                 });
81262             }
81263         }
81264     },
81265
81266     onLayout: function() {
81267         var me = this;
81268         
81269         me.updatePanelClasses();
81270                 
81271         if (me.fill) {
81272             me.callParent(arguments);
81273         } else {
81274             var targetSize = me.getLayoutTargetSize(),
81275                 items = me.getVisibleItems(),
81276                 len = items.length,
81277                 i = 0, comp;
81278
81279             for (; i < len; i++) {
81280                 comp = items[i];
81281                 if (comp.collapsed) {
81282                     items[i].setWidth(targetSize.width);
81283                 } else {
81284                     items[i].setSize(null, null);
81285                 }
81286             }
81287         }
81288         
81289         return me;
81290     },
81291     
81292     updatePanelClasses: function() {
81293         var children = this.getLayoutItems(),
81294             ln = children.length,
81295             siblingCollapsed = true,
81296             i, child;
81297             
81298         for (i = 0; i < ln; i++) {
81299             child = children[i];
81300             if (!siblingCollapsed) {
81301                 child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
81302             }
81303             else {
81304                 child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
81305             }
81306             if (i + 1 == ln && child.collapsed) {
81307                 child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
81308             }
81309             else {
81310                 child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
81311             }
81312             siblingCollapsed = child.collapsed;
81313         }
81314     },
81315
81316     
81317     
81318     
81319     onComponentExpand: function(toExpand) {
81320         var me = this,
81321             it = me.owner.items.items,
81322             len = it.length,
81323             i = 0,
81324             comp;
81325
81326         for (; i < len; i++) {
81327             comp = it[i];
81328             if (comp === toExpand && comp.collapsed) {
81329                 me.setExpanded(comp);
81330             } else if (!me.multi && (comp.rendered && comp.header.rendered && comp !== toExpand && !comp.collapsed)) {
81331                 me.setCollapsed(comp);
81332             }
81333         }
81334         
81335         me.animate = me.initialAnimate;
81336         me.layout();
81337         me.animate = false;
81338         return false;
81339     },
81340
81341     onComponentCollapse: function(comp) {
81342         var me = this,
81343             toExpand = comp.next() || comp.prev(),
81344             expanded = me.multi ? me.owner.query('>panel:not([collapsed])') : [];
81345
81346         
81347         
81348         if (me.multi) {
81349             me.setCollapsed(comp);
81350
81351             
81352             
81353             if (expanded.length === 1 && expanded[0] === comp) {
81354                 me.setExpanded(toExpand);
81355             }
81356             
81357             me.animate = me.initialAnimate;
81358             me.layout();
81359             me.animate = false;
81360         }
81361         
81362         else if (toExpand) {
81363             me.onComponentExpand(toExpand);
81364         }
81365         return false;
81366     },
81367
81368     onComponentShow: function(comp) {
81369         
81370         this.onComponentExpand(comp);
81371     },
81372
81373     setCollapsed: function(comp) {
81374         var otherDocks = comp.getDockedItems(),
81375             dockItem,
81376             len = otherDocks.length,
81377             i = 0;
81378
81379         
81380         comp.hiddenDocked = [];
81381         for (; i < len; i++) {
81382             dockItem = otherDocks[i];
81383             if ((dockItem !== comp.header) && !dockItem.hidden) {
81384                 dockItem.hidden = true;
81385                 comp.hiddenDocked.push(dockItem);
81386             }
81387         }
81388         comp.addCls(comp.collapsedCls);
81389         comp.header.addCls(comp.collapsedHeaderCls);
81390         comp.height = comp.header.getHeight();
81391         comp.el.setHeight(comp.height);
81392         comp.collapsed = true;
81393         delete comp.flex;
81394         comp.fireEvent('collapse', comp);
81395         if (comp.collapseTool) {
81396             comp.collapseTool.setType('expand-' + comp.getOppositeDirection(comp.collapseDirection));
81397         }
81398     },
81399
81400     setExpanded: function(comp) {
81401         var otherDocks = comp.hiddenDocked,
81402             len = otherDocks ? otherDocks.length : 0,
81403             i = 0;
81404
81405         
81406         for (; i < len; i++) {
81407             otherDocks[i].show();
81408         }
81409
81410         
81411         if (!comp.body.isVisible()) {
81412             comp.body.show();
81413         }
81414         delete comp.collapsed;
81415         delete comp.height;
81416         delete comp.componentLayout.lastComponentSize;
81417         comp.suspendLayout = false;
81418         comp.flex = 1;
81419         comp.removeCls(comp.collapsedCls);
81420         comp.header.removeCls(comp.collapsedHeaderCls);
81421         comp.fireEvent('expand', comp);
81422         if (comp.collapseTool) {
81423             comp.collapseTool.setType('collapse-' + comp.collapseDirection);
81424         }
81425         comp.setAutoScroll(comp.initialConfig.autoScroll);
81426     }
81427 });
81428
81429 Ext.define('Ext.resizer.Splitter', {
81430     extend: 'Ext.Component',
81431     requires: ['Ext.XTemplate'],
81432     uses: ['Ext.resizer.SplitterTracker'],
81433     alias: 'widget.splitter',
81434
81435     renderTpl: [
81436         '<tpl if="collapsible===true"><div class="' + Ext.baseCSSPrefix + 'collapse-el ' + Ext.baseCSSPrefix + 'layout-split-{collapseDir}">&nbsp;</div></tpl>'
81437     ],
81438
81439     baseCls: Ext.baseCSSPrefix + 'splitter',
81440     collapsedCls: Ext.baseCSSPrefix + 'splitter-collapsed',
81441
81442     
81443     collapsible: false,
81444
81445     
81446
81447     
81448     collapseOnDblClick: true,
81449
81450     
81451     defaultSplitMin: 40,
81452
81453     
81454     defaultSplitMax: 1000,
81455
81456     width: 5,
81457     height: 5,
81458
81459     
81460     collapseTarget: 'next',
81461
81462     
81463
81464     onRender: function() {
81465         var me = this,
81466             target = me.getCollapseTarget(),
81467             collapseDir = me.getCollapseDirection();
81468
81469         Ext.applyIf(me.renderData, {
81470             collapseDir: collapseDir,
81471             collapsible: me.collapsible || target.collapsible
81472         });
81473         Ext.applyIf(me.renderSelectors, {
81474             collapseEl: '.' + Ext.baseCSSPrefix + 'collapse-el'
81475         });
81476
81477         this.callParent(arguments);
81478
81479         
81480         if (me.performCollapse !== false) {
81481             if (me.renderData.collapsible) {
81482                 me.mon(me.collapseEl, 'click', me.toggleTargetCmp, me);
81483             }
81484             if (me.collapseOnDblClick) {
81485                 me.mon(me.el, 'dblclick', me.toggleTargetCmp, me);
81486             }
81487         }
81488
81489         
81490         me.mon(target, 'collapse', me.onTargetCollapse, me);
81491         me.mon(target, 'expand', me.onTargetExpand, me);
81492
81493         me.el.addCls(me.baseCls + '-' + me.orientation);
81494         me.el.unselectable();
81495
81496         me.tracker = Ext.create('Ext.resizer.SplitterTracker', {
81497             el: me.el
81498         });
81499
81500         
81501         me.relayEvents(me.tracker, [ 'beforedragstart', 'dragstart', 'dragend' ]);
81502     },
81503
81504     getCollapseDirection: function() {
81505         var me = this,
81506             idx,
81507             type = me.ownerCt.layout.type;
81508
81509         
81510         
81511         
81512         
81513         
81514         
81515         
81516         if (me.collapseTarget.isComponent) {
81517             idx = Number(me.ownerCt.items.indexOf(me.collapseTarget) == me.ownerCt.items.indexOf(me) - 1) << 1 | Number(type == 'hbox');
81518         } else {
81519             idx = Number(me.collapseTarget == 'prev') << 1 | Number(type == 'hbox');
81520         }
81521
81522         
81523         me.orientation = ['horizontal', 'vertical'][idx & 1];
81524         return ['bottom', 'right', 'top', 'left'][idx];
81525     },
81526
81527     getCollapseTarget: function() {
81528         return this.collapseTarget.isComponent ? this.collapseTarget : this.collapseTarget == 'prev' ? this.previousSibling() : this.nextSibling();
81529     },
81530
81531     onTargetCollapse: function(target) {
81532         this.el.addCls(this.collapsedCls);
81533     },
81534
81535     onTargetExpand: function(target) {
81536         this.el.removeCls(this.collapsedCls);
81537     },
81538
81539     toggleTargetCmp: function(e, t) {
81540         var cmp = this.getCollapseTarget();
81541
81542         if (cmp.isVisible()) {
81543             
81544             if (cmp.collapsed) {
81545                 cmp.expand(cmp.animCollapse);
81546             
81547             } else {
81548                 cmp.collapse(this.renderData.collapseDir, cmp.animCollapse);
81549             }
81550         }
81551     },
81552
81553     
81554     setSize: function() {
81555         var me = this;
81556         me.callParent(arguments);
81557         if (Ext.isIE) {
81558             me.el.repaint();
81559         }
81560     }
81561 });
81562
81563
81564 Ext.define('Ext.layout.container.Border', {
81565
81566     alias: ['layout.border'],
81567     extend: 'Ext.layout.container.Container',
81568     requires: ['Ext.resizer.Splitter', 'Ext.container.Container', 'Ext.fx.Anim'],
81569     alternateClassName: 'Ext.layout.BorderLayout',
81570
81571     targetCls: Ext.baseCSSPrefix + 'border-layout-ct',
81572
81573     itemCls: Ext.baseCSSPrefix + 'border-item',
81574
81575     bindToOwnerCtContainer: true,
81576
81577     fixedLayout: false,
81578
81579     percentageRe: /(\d+)%/,
81580
81581     slideDirection: {
81582         north: 't',
81583         south: 'b',
81584         west: 'l',
81585         east: 'r'
81586     },
81587
81588     constructor: function(config) {
81589         this.initialConfig = config;
81590         this.callParent(arguments);
81591     },
81592
81593     onLayout: function() {
81594         var me = this;
81595         if (!me.borderLayoutInitialized) {
81596             me.initializeBorderLayout();
81597         }
81598
81599         
81600         me.fixHeightConstraints();
81601         me.shadowLayout.onLayout();
81602         if (me.embeddedContainer) {
81603             me.embeddedContainer.layout.onLayout();
81604         }
81605
81606         
81607         
81608         if (!me.initialCollapsedComplete) {
81609             Ext.iterate(me.regions, function(name, region){
81610                 if (region.borderCollapse) {
81611                     me.onBeforeRegionCollapse(region, region.collapseDirection, false, 0);
81612                 }
81613             });
81614             me.initialCollapsedComplete = true;
81615         }
81616     },
81617
81618     isValidParent : function(item, target, position) {
81619         if (!this.borderLayoutInitialized) {
81620             this.initializeBorderLayout();
81621         }
81622
81623         
81624         return this.shadowLayout.isValidParent(item, target, position);
81625     },
81626
81627     beforeLayout: function() {
81628         if (!this.borderLayoutInitialized) {
81629             this.initializeBorderLayout();
81630         }
81631
81632         
81633         this.shadowLayout.beforeLayout();
81634     },
81635
81636     renderItems: function(items, target) {
81637         Ext.Error.raise('This should not be called');
81638     },
81639
81640     renderItem: function(item) {
81641         Ext.Error.raise('This should not be called');
81642     },
81643
81644     initializeBorderLayout: function() {
81645         var me = this,
81646             i = 0,
81647             items = me.getLayoutItems(),
81648             ln = items.length,
81649             regions = (me.regions = {}),
81650             vBoxItems = [],
81651             hBoxItems = [],
81652             horizontalFlex = 0,
81653             verticalFlex = 0,
81654             comp, percentage;
81655
81656         
81657         me.splitters = {};
81658
81659         
81660         for (; i < ln; i++) {
81661             comp = items[i];
81662             regions[comp.region] = comp;
81663
81664             
81665             if (comp.region != 'center' && comp.collapsible && comp.collapseMode != 'header') {
81666
81667                 
81668                 comp.borderCollapse = comp.collapsed;
81669                 delete comp.collapsed;
81670
81671                 comp.on({
81672                     beforecollapse: me.onBeforeRegionCollapse,
81673                     beforeexpand: me.onBeforeRegionExpand,
81674                     destroy: me.onRegionDestroy,
81675                     scope: me
81676                 });
81677                 me.setupState(comp);
81678             }
81679         }
81680         if (!regions.center) {
81681             Ext.Error.raise("You must specify a center region when defining a BorderLayout.");
81682         }
81683         comp = regions.center;
81684         if (!comp.flex) {
81685             comp.flex = 1;
81686         }
81687         delete comp.width;
81688         comp.maintainFlex = true;
81689
81690         
81691         comp = regions.west;
81692         if (comp) {
81693             comp.collapseDirection = Ext.Component.DIRECTION_LEFT;
81694             hBoxItems.push(comp);
81695             if (comp.split) {
81696                 hBoxItems.push(me.splitters.west = me.createSplitter(comp));
81697             }
81698             percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
81699             if (percentage) {
81700                 horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
81701                 delete comp.width;
81702             }
81703         }
81704         comp = regions.north;
81705         if (comp) {
81706             comp.collapseDirection = Ext.Component.DIRECTION_TOP;
81707             vBoxItems.push(comp);
81708             if (comp.split) {
81709                 vBoxItems.push(me.splitters.north = me.createSplitter(comp));
81710             }
81711             percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
81712             if (percentage) {
81713                 verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
81714                 delete comp.height;
81715             }
81716         }
81717
81718         
81719         if (regions.north || regions.south) {
81720             if (regions.east || regions.west) {
81721
81722                 
81723                 vBoxItems.push(me.embeddedContainer = Ext.create('Ext.container.Container', {
81724                     xtype: 'container',
81725                     region: 'center',
81726                     id: me.owner.id + '-embedded-center',
81727                     cls: Ext.baseCSSPrefix + 'border-item',
81728                     flex: regions.center.flex,
81729                     maintainFlex: true,
81730                     layout: {
81731                         type: 'hbox',
81732                         align: 'stretch'
81733                     }
81734                 }));
81735                 hBoxItems.push(regions.center);
81736             }
81737             
81738             else {
81739                 vBoxItems.push(regions.center);
81740             }
81741         }
81742         
81743         else {
81744             hBoxItems.push(regions.center);
81745         }
81746
81747         
81748         comp = regions.south;
81749         if (comp) {
81750             comp.collapseDirection = Ext.Component.DIRECTION_BOTTOM;
81751             if (comp.split) {
81752                 vBoxItems.push(me.splitters.south = me.createSplitter(comp));
81753             }
81754             percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
81755             if (percentage) {
81756                 verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
81757                 delete comp.height;
81758             }
81759             vBoxItems.push(comp);
81760         }
81761         comp = regions.east;
81762         if (comp) {
81763             comp.collapseDirection = Ext.Component.DIRECTION_RIGHT;
81764             if (comp.split) {
81765                 hBoxItems.push(me.splitters.east = me.createSplitter(comp));
81766             }
81767             percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
81768             if (percentage) {
81769                 horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
81770                 delete comp.width;
81771             }
81772             hBoxItems.push(comp);
81773         }
81774
81775         
81776         
81777         
81778         
81779         if (regions.north || regions.south) {
81780
81781             me.shadowContainer = Ext.create('Ext.container.Container', {
81782                 ownerCt: me.owner,
81783                 el: me.getTarget(),
81784                 layout: Ext.applyIf({
81785                     type: 'vbox',
81786                     align: 'stretch'
81787                 }, me.initialConfig)
81788             });
81789             me.createItems(me.shadowContainer, vBoxItems);
81790
81791             
81792             if (me.splitters.north) {
81793                 me.splitters.north.ownerCt = me.shadowContainer;
81794             }
81795             if (me.splitters.south) {
81796                 me.splitters.south.ownerCt = me.shadowContainer;
81797             }
81798
81799             
81800             if (me.embeddedContainer) {
81801                 me.embeddedContainer.ownerCt = me.shadowContainer;
81802                 me.createItems(me.embeddedContainer, hBoxItems);
81803
81804                 
81805                 if (me.splitters.east) {
81806                     me.splitters.east.ownerCt = me.embeddedContainer;
81807                 }
81808                 if (me.splitters.west) {
81809                     me.splitters.west.ownerCt = me.embeddedContainer;
81810                 }
81811
81812                 
81813                 
81814                 
81815                 
81816                 
81817                 Ext.each([me.splitters.north, me.splitters.south], function (splitter) {
81818                     if (splitter) {
81819                         splitter.on('beforedragstart', me.fixHeightConstraints, me);
81820                     }
81821                 });
81822
81823                 
81824                 if (horizontalFlex) {
81825                     regions.center.flex -= horizontalFlex;
81826                 }
81827                 
81828                 if (verticalFlex) {
81829                     me.embeddedContainer.flex -= verticalFlex;
81830                 }
81831             } else {
81832                 
81833                 if (verticalFlex) {
81834                     regions.center.flex -= verticalFlex;
81835                 }
81836             }
81837         }
81838         
81839         
81840         else {
81841             me.shadowContainer = Ext.create('Ext.container.Container', {
81842                 ownerCt: me.owner,
81843                 el: me.getTarget(),
81844                 layout: Ext.applyIf({
81845                     type: (hBoxItems.length == 1) ? 'fit' : 'hbox',
81846                     align: 'stretch'
81847                 }, me.initialConfig)
81848             });
81849             me.createItems(me.shadowContainer, hBoxItems);
81850
81851             
81852             if (me.splitters.east) {
81853                 me.splitters.east.ownerCt = me.shadowContainer;
81854             }
81855             if (me.splitters.west) {
81856                 me.splitters.west.ownerCt = me.shadowContainer;
81857             }
81858
81859             
81860             if (horizontalFlex) {
81861                 regions.center.flex -= verticalFlex;
81862             }
81863         }
81864
81865         
81866         for (i = 0, items = me.shadowContainer.items.items, ln = items.length; i < ln; i++) {
81867             items[i].shadowOwnerCt = me.shadowContainer;
81868         }
81869         if (me.embeddedContainer) {
81870             for (i = 0, items = me.embeddedContainer.items.items, ln = items.length; i < ln; i++) {
81871                 items[i].shadowOwnerCt = me.embeddedContainer;
81872             }
81873         }
81874
81875         
81876         me.shadowLayout = me.shadowContainer.getLayout();
81877
81878         me.borderLayoutInitialized = true;
81879     },
81880
81881     setupState: function(comp){
81882         var getState = comp.getState;
81883         comp.getState = function(){
81884             
81885             var state = getState.call(comp) || {},
81886                 region = comp.region;
81887
81888             state.collapsed = !!comp.collapsed;
81889             if (region == 'west' || region == 'east') {
81890                 state.width = comp.getWidth();
81891             } else {
81892                 state.height = comp.getHeight();
81893             }
81894             return state;
81895         };
81896         comp.addStateEvents(['collapse', 'expand', 'resize']);
81897     },
81898
81899     
81900     createItems: function(container, items){
81901         
81902         
81903         delete container.items;
81904         container.initItems();
81905         container.items.addAll(items);
81906     },
81907
81908     
81909     
81910     createSplitter: function(comp) {
81911         var me = this,
81912             interceptCollapse = (comp.collapseMode != 'header'),
81913             resizer;
81914
81915         resizer = Ext.create('Ext.resizer.Splitter', {
81916             hidden: !!comp.hidden,
81917             collapseTarget: comp,
81918             performCollapse: !interceptCollapse,
81919             listeners: interceptCollapse ? {
81920                 click: {
81921                     fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
81922                     element: 'collapseEl'
81923                 }
81924             } : null
81925         });
81926
81927         
81928         if (comp.collapseMode == 'mini') {
81929             comp.placeholder = resizer;
81930         }
81931
81932         
81933         comp.on({
81934             hide: me.onRegionVisibilityChange,
81935             show: me.onRegionVisibilityChange,
81936             scope: me
81937         });
81938         return resizer;
81939     },
81940
81941     
81942     
81943     fixHeightConstraints: function () {
81944         var me = this,
81945             ct = me.embeddedContainer,
81946             maxHeight = 1e99, minHeight = -1;
81947
81948         if (!ct) {
81949             return;
81950         }
81951
81952         ct.items.each(function (item) {
81953             if (Ext.isNumber(item.maxHeight)) {
81954                 maxHeight = Math.max(maxHeight, item.maxHeight);
81955             }
81956             if (Ext.isNumber(item.minHeight)) {
81957                 minHeight = Math.max(minHeight, item.minHeight);
81958             }
81959         });
81960
81961         ct.maxHeight = maxHeight;
81962         ct.minHeight = minHeight;
81963     },
81964
81965     
81966     onRegionVisibilityChange: function(comp){
81967         this.splitters[comp.region][comp.hidden ? 'hide' : 'show']();
81968         this.layout();
81969     },
81970
81971     
81972     
81973     
81974     onSplitterCollapseClick: function(comp) {
81975         if (comp.collapsed) {
81976             this.onPlaceHolderToolClick(null, null, null, {client: comp});
81977         } else {
81978             comp.collapse();
81979         }
81980     },
81981
81982     
81983     getPlaceholder: function(comp) {
81984         var me = this,
81985             placeholder = comp.placeholder,
81986             shadowContainer = comp.shadowOwnerCt,
81987             shadowLayout = shadowContainer.layout,
81988             oppositeDirection = Ext.panel.Panel.prototype.getOppositeDirection(comp.collapseDirection),
81989             horiz = (comp.region == 'north' || comp.region == 'south');
81990
81991         
81992         if (comp.collapseMode == 'header') {
81993             return;
81994         }
81995
81996         
81997         if (!placeholder) {
81998             if (comp.collapseMode == 'mini') {
81999                 placeholder = Ext.create('Ext.resizer.Splitter', {
82000                     id: 'collapse-placeholder-' + comp.id,
82001                     collapseTarget: comp,
82002                     performCollapse: false,
82003                     listeners: {
82004                         click: {
82005                             fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
82006                             element: 'collapseEl'
82007                         }
82008                     }
82009                 });
82010                 placeholder.addCls(placeholder.collapsedCls);
82011             } else {
82012                 placeholder = {
82013                     id: 'collapse-placeholder-' + comp.id,
82014                     margins: comp.initialConfig.margins || Ext.getClass(comp).prototype.margins,
82015                     xtype: 'header',
82016                     orientation: horiz ? 'horizontal' : 'vertical',
82017                     title: comp.title,
82018                     textCls: comp.headerTextCls,
82019                     iconCls: comp.iconCls,
82020                     baseCls: comp.baseCls + '-header',
82021                     ui: comp.ui,
82022                     indicateDrag: comp.draggable,
82023                     cls: Ext.baseCSSPrefix + 'region-collapsed-placeholder ' + Ext.baseCSSPrefix + 'region-collapsed-' + comp.collapseDirection + '-placeholder',
82024                     listeners: comp.floatable ? {
82025                         click: {
82026                             fn: function(e) {
82027                                 me.floatCollapsedPanel(e, comp);
82028                             },
82029                             element: 'el'
82030                         }
82031                     } : null
82032                 };
82033                 
82034                 if ((Ext.isIE6 || Ext.isIE7 || (Ext.isIEQuirks)) && !horiz) {
82035                     placeholder.width = 25;
82036                 }
82037                 if (!comp.hideCollapseTool) {
82038                     placeholder[horiz ? 'tools' : 'items'] = [{
82039                         xtype: 'tool',
82040                         client: comp,
82041                         type: 'expand-' + oppositeDirection,
82042                         handler: me.onPlaceHolderToolClick,
82043                         scope: me
82044                     }];
82045                 }
82046             }
82047             placeholder = me.owner.createComponent(placeholder);
82048             if (comp.isXType('panel')) {
82049                 comp.on({
82050                     titlechange: me.onRegionTitleChange,
82051                     iconchange: me.onRegionIconChange,
82052                     scope: me
82053                 });
82054             }
82055         }
82056
82057         
82058         comp.placeholder = placeholder;
82059         placeholder.comp = comp;
82060
82061         return placeholder;
82062     },
82063
82064     
82065     onRegionTitleChange: function(comp, newTitle) {
82066         comp.placeholder.setTitle(newTitle);
82067     },
82068
82069     
82070     onRegionIconChange: function(comp, newIconCls) {
82071         comp.placeholder.setIconCls(newIconCls);
82072     },
82073
82074     
82075     calculateChildBox: function(comp) {
82076         var me = this;
82077         if (me.shadowContainer.items.contains(comp)) {
82078             return me.shadowContainer.layout.calculateChildBox(comp);
82079         }
82080         else if (me.embeddedContainer && me.embeddedContainer.items.contains(comp)) {
82081             return me.embeddedContainer.layout.calculateChildBox(comp);
82082         }
82083     },
82084
82085     
82086     onBeforeRegionCollapse: function(comp, direction, animate) {
82087         var me = this,
82088             compEl = comp.el,
82089             width,
82090             miniCollapse = comp.collapseMode == 'mini',
82091             shadowContainer = comp.shadowOwnerCt,
82092             shadowLayout = shadowContainer.layout,
82093             placeholder = comp.placeholder,
82094             sl = me.owner.suspendLayout,
82095             scsl = shadowContainer.suspendLayout,
82096             isNorthOrWest = (comp.region == 'north' || comp.region == 'west'); 
82097
82098         
82099         me.owner.suspendLayout = true;
82100         shadowContainer.suspendLayout = true;
82101
82102         
82103         shadowLayout.layoutBusy = true;
82104         if (shadowContainer.componentLayout) {
82105             shadowContainer.componentLayout.layoutBusy = true;
82106         }
82107         me.shadowContainer.layout.layoutBusy = true;
82108         me.layoutBusy = true;
82109         me.owner.componentLayout.layoutBusy = true;
82110
82111         
82112         if (!placeholder) {
82113             placeholder = me.getPlaceholder(comp);
82114         }
82115
82116         
82117         if (placeholder.shadowOwnerCt === shadowContainer) {
82118             placeholder.show();
82119         }
82120         
82121         
82122         
82123         else {
82124             shadowContainer.insert(shadowContainer.items.indexOf(comp) + (isNorthOrWest ? 0 : 1), placeholder);
82125             placeholder.shadowOwnerCt = shadowContainer;
82126             placeholder.ownerCt = me.owner;
82127         }
82128
82129         
82130         
82131         
82132         comp.hidden = true;
82133
82134         if (!placeholder.rendered) {
82135             shadowLayout.renderItem(placeholder, shadowLayout.innerCt);
82136
82137             
82138             
82139             
82140             
82141             
82142             if (comp.region == 'north' || comp.region == 'south') {
82143                 placeholder.setCalculatedSize(comp.getWidth());
82144             } else {
82145                 placeholder.setCalculatedSize(undefined, comp.getHeight());
82146             }
82147         }
82148
82149         
82150         function afterCollapse() {
82151             
82152             me.owner.suspendLayout = sl;
82153             shadowContainer.suspendLayout = scsl;
82154             delete shadowLayout.layoutBusy;
82155             if (shadowContainer.componentLayout) {
82156                 delete shadowContainer.componentLayout.layoutBusy;
82157             }
82158             delete me.shadowContainer.layout.layoutBusy;
82159             delete me.layoutBusy;
82160             delete me.owner.componentLayout.layoutBusy;
82161
82162             
82163             comp.collapsed = true;
82164             comp.fireEvent('collapse', comp);
82165         }
82166
82167         
82168         if (comp.animCollapse && me.initialCollapsedComplete) {
82169             shadowLayout.layout();
82170             compEl.dom.style.zIndex = 100;
82171
82172             
82173             if (!miniCollapse) {
82174                 placeholder.el.hide();
82175             }
82176             compEl.slideOut(me.slideDirection[comp.region], {
82177                 duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
82178                 listeners: {
82179                     afteranimate: function() {
82180                         compEl.show().setLeftTop(-10000, -10000);
82181                         compEl.dom.style.zIndex = '';
82182
82183                         
82184                        if (!miniCollapse) {
82185                             placeholder.el.slideIn(me.slideDirection[comp.region], {
82186                                 easing: 'linear',
82187                                 duration: 100
82188                             });
82189                         }
82190                         afterCollapse();
82191                     }
82192                 }
82193             });
82194         } else {
82195             compEl.setLeftTop(-10000, -10000);
82196             shadowLayout.layout();
82197             afterCollapse();
82198         }
82199
82200         return false;
82201     },
82202
82203     
82204     onBeforeRegionExpand: function(comp, animate) {
82205         this.onPlaceHolderToolClick(null, null, null, {client: comp});
82206         return false;
82207     },
82208
82209     
82210     onPlaceHolderToolClick: function(e, target, owner, tool) {
82211         var me = this,
82212             comp = tool.client,
82213
82214             
82215             hidePlaceholder = (comp.collapseMode != 'mini') || !comp.split,
82216             compEl = comp.el,
82217             toCompBox,
82218             placeholder = comp.placeholder,
82219             placeholderEl = placeholder.el,
82220             shadowContainer = comp.shadowOwnerCt,
82221             shadowLayout = shadowContainer.layout,
82222             curSize,
82223             sl = me.owner.suspendLayout,
82224             scsl = shadowContainer.suspendLayout,
82225             isFloating;
82226
82227         
82228         
82229         
82230         if (comp.getActiveAnimation()) {
82231             comp.stopAnimation();
82232         }
82233
82234         
82235         
82236         
82237         if (comp.slideOutAnim) {
82238             
82239             compEl.un(comp.panelMouseMon);
82240             placeholderEl.un(comp.placeholderMouseMon);
82241
82242             delete comp.slideOutAnim;
82243             delete comp.panelMouseMon;
82244             delete comp.placeholderMouseMon;
82245
82246             
82247             isFloating = true;
82248         }
82249
82250         
82251         me.owner.suspendLayout = true;
82252         shadowContainer.suspendLayout = true;
82253
82254         
82255         shadowLayout.layoutBusy = true;
82256         if (shadowContainer.componentLayout) {
82257             shadowContainer.componentLayout.layoutBusy = true;
82258         }
82259         me.shadowContainer.layout.layoutBusy = true;
82260         me.layoutBusy = true;
82261         me.owner.componentLayout.layoutBusy = true;
82262
82263         
82264         
82265         comp.hidden = false;
82266         comp.collapsed = false;
82267         if (hidePlaceholder) {
82268             placeholder.hidden = true;
82269         }
82270         toCompBox = shadowLayout.calculateChildBox(comp);
82271
82272         
82273         if (comp.collapseTool) {
82274             comp.collapseTool.show();
82275         }
82276
82277         
82278         if (comp.animCollapse && !isFloating) {
82279             compEl.setStyle('visibility', 'hidden');
82280         }
82281         compEl.setLeftTop(toCompBox.left, toCompBox.top);
82282
82283         
82284         
82285         curSize = comp.getSize();
82286         if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
82287             me.setItemSize(comp, toCompBox.width, toCompBox.height);
82288         }
82289
82290         
82291         function afterExpand() {
82292             
82293             me.owner.suspendLayout = sl;
82294             shadowContainer.suspendLayout = scsl;
82295             delete shadowLayout.layoutBusy;
82296             if (shadowContainer.componentLayout) {
82297                 delete shadowContainer.componentLayout.layoutBusy;
82298             }
82299             delete me.shadowContainer.layout.layoutBusy;
82300             delete me.layoutBusy;
82301             delete me.owner.componentLayout.layoutBusy;
82302
82303             
82304             comp.removeCls(Ext.baseCSSPrefix + 'border-region-slide-in');
82305
82306             
82307             comp.fireEvent('expand', comp);
82308         }
82309
82310         
82311         if (hidePlaceholder) {
82312             placeholder.el.hide();
82313         }
82314
82315         
82316         
82317         if (comp.animCollapse && !isFloating) {
82318             compEl.dom.style.zIndex = 100;
82319             compEl.slideIn(me.slideDirection[comp.region], {
82320                 duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
82321                 listeners: {
82322                     afteranimate: function() {
82323                         compEl.dom.style.zIndex = '';
82324                         comp.hidden = false;
82325                         shadowLayout.onLayout();
82326                         afterExpand();
82327                     }
82328                 }
82329             });
82330         } else {
82331             shadowLayout.onLayout();
82332             afterExpand();
82333         }
82334     },
82335
82336     floatCollapsedPanel: function(e, comp) {
82337
82338         if (comp.floatable === false) {
82339             return;
82340         }
82341
82342         var me = this,
82343             compEl = comp.el,
82344             placeholder = comp.placeholder,
82345             placeholderEl = placeholder.el,
82346             shadowContainer = comp.shadowOwnerCt,
82347             shadowLayout = shadowContainer.layout,
82348             placeholderBox = shadowLayout.getChildBox(placeholder),
82349             scsl = shadowContainer.suspendLayout,
82350             curSize, toCompBox, compAnim;
82351
82352         
82353         if (e.getTarget('.' + Ext.baseCSSPrefix + 'tool')) {
82354             return;
82355         }
82356
82357         
82358         
82359         if (compEl.getActiveAnimation()) {
82360             return;
82361         }
82362
82363         
82364         
82365         if (comp.slideOutAnim) {
82366             me.slideOutFloatedComponent(comp);
82367             return;
82368         }
82369
82370         
82371         
82372         function onMouseLeaveFloated(e) {
82373             var slideRegion = compEl.getRegion().union(placeholderEl.getRegion()).adjust(1, -1, -1, 1);
82374
82375             
82376             if (!slideRegion.contains(e.getPoint())) {
82377                 me.slideOutFloatedComponent(comp);
82378             }
82379         }
82380
82381         
82382         comp.placeholderMouseMon = placeholderEl.monitorMouseLeave(500, onMouseLeaveFloated);
82383
82384         
82385         shadowContainer.suspendLayout = true;
82386
82387         
82388         me.layoutBusy = true;
82389         me.owner.componentLayout.layoutBusy = true;
82390
82391         
82392         
82393         if (comp.collapseTool) {
82394             comp.collapseTool.hide();
82395         }
82396
82397         
82398         comp.hidden = false;
82399         comp.collapsed = false;
82400         placeholder.hidden = true;
82401
82402         
82403         toCompBox = shadowLayout.calculateChildBox(comp);
82404         placeholder.hidden = false;
82405
82406         
82407         if (comp.region == 'north' || comp.region == 'west') {
82408             toCompBox[shadowLayout.parallelBefore] += placeholderBox[shadowLayout.parallelPrefix] - 1;
82409         } else {
82410             toCompBox[shadowLayout.parallelBefore] -= (placeholderBox[shadowLayout.parallelPrefix] - 1);
82411         }
82412         compEl.setStyle('visibility', 'hidden');
82413         compEl.setLeftTop(toCompBox.left, toCompBox.top);
82414
82415         
82416         
82417         curSize = comp.getSize();
82418         if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
82419             me.setItemSize(comp, toCompBox.width, toCompBox.height);
82420         }
82421
82422         
82423         compAnim = {
82424             listeners: {
82425                 afteranimate: function() {
82426                     shadowContainer.suspendLayout = scsl;
82427                     delete me.layoutBusy;
82428                     delete me.owner.componentLayout.layoutBusy;
82429
82430                     
82431                     compAnim.listeners = {
82432                         afterAnimate: function() {
82433                             compEl.show().removeCls(Ext.baseCSSPrefix + 'border-region-slide-in').setLeftTop(-10000, -10000);
82434
82435                             
82436                             comp.hidden = true;
82437                             comp.collapsed = true;
82438                             delete comp.slideOutAnim;
82439                             delete comp.panelMouseMon;
82440                             delete comp.placeholderMouseMon;
82441                         }
82442                     };
82443                     comp.slideOutAnim = compAnim;
82444                 }
82445             },
82446             duration: 500
82447         };
82448
82449         
82450         compEl.addCls(Ext.baseCSSPrefix + 'border-region-slide-in');
82451
82452         
82453         compEl.slideIn(me.slideDirection[comp.region], compAnim);
82454
82455         
82456         comp.panelMouseMon = compEl.monitorMouseLeave(500, onMouseLeaveFloated);
82457
82458     },
82459
82460     slideOutFloatedComponent: function(comp) {
82461         var compEl = comp.el,
82462             slideOutAnim;
82463
82464         
82465         compEl.un(comp.panelMouseMon);
82466         comp.placeholder.el.un(comp.placeholderMouseMon);
82467
82468         
82469         compEl.slideOut(this.slideDirection[comp.region], comp.slideOutAnim);
82470
82471         delete comp.slideOutAnim;
82472         delete comp.panelMouseMon;
82473         delete comp.placeholderMouseMon;
82474     },
82475
82476     
82477     onRegionDestroy: function(comp) {
82478         var placeholder = comp.placeholder;
82479         if (placeholder) {
82480             delete placeholder.ownerCt;
82481             placeholder.destroy();
82482         }
82483     },
82484
82485     
82486     onDestroy: function() {
82487         var me = this,
82488             shadowContainer = me.shadowContainer,
82489             embeddedContainer = me.embeddedContainer;
82490
82491         if (shadowContainer) {
82492             delete shadowContainer.ownerCt;
82493             Ext.destroy(shadowContainer);
82494         }
82495
82496         if (embeddedContainer) {
82497             delete embeddedContainer.ownerCt;
82498             Ext.destroy(embeddedContainer);
82499         }
82500         delete me.regions;
82501         delete me.splitters;
82502         delete me.shadowContainer;
82503         delete me.embeddedContainer;
82504         me.callParent(arguments);
82505     }
82506 });
82507
82508
82509 Ext.define('Ext.layout.container.Card', {
82510
82511     
82512
82513     alias: ['layout.card'],
82514     alternateClassName: 'Ext.layout.CardLayout',
82515
82516     extend: 'Ext.layout.container.AbstractCard',
82517
82518     
82519
82520     setActiveItem: function(newCard) {
82521         var me = this,
82522             owner = me.owner,
82523             oldCard = me.activeItem,
82524             newIndex;
82525
82526         
82527         me.layoutBusy = true;
82528
82529         newCard = me.parseActiveItem(newCard);
82530         newIndex = owner.items.indexOf(newCard);
82531
82532         
82533         if (newIndex == -1) {
82534             newIndex = owner.items.items.length;
82535             owner.add(newCard);
82536         }
82537
82538         
82539         if (newCard && oldCard != newCard) {
82540             
82541             if (!newCard.rendered) {
82542                 me.renderItem(newCard, me.getRenderTarget(), owner.items.length);
82543                 me.configureItem(newCard, 0);
82544             }
82545
82546             me.activeItem = newCard;
82547
82548             
82549             if (newCard.fireEvent('beforeactivate', newCard, oldCard) === false) {
82550                 me.layoutBusy = false;
82551                 return false;
82552             }
82553             if (oldCard && oldCard.fireEvent('beforedeactivate', oldCard, newCard) === false) {
82554                 me.layoutBusy = false;
82555                 return false;
82556             }
82557
82558             
82559             if (!me.sizeAllCards) {
82560                 me.setItemBox(newCard, me.getTargetBox());
82561             }
82562             else {
82563                 
82564                 me.onLayout();
82565             }
82566
82567             if (oldCard) {
82568                 if (me.hideInactive) {
82569                     oldCard.hide();
82570                 }
82571                 oldCard.fireEvent('deactivate', oldCard, newCard);
82572             }
82573
82574             
82575             if (newCard.hidden) {
82576                 newCard.show();
82577             }
82578
82579             newCard.fireEvent('activate', newCard, oldCard);
82580
82581             me.layoutBusy = false;
82582
82583             if (!me.sizeAllCards) {
82584                 if (!owner.componentLayout.layoutBusy) {
82585                     me.onLayout();
82586                 }
82587             }
82588             return newCard;
82589         }
82590
82591         me.layoutBusy = false;
82592         return false;
82593     }
82594 });
82595
82596 Ext.define('Ext.layout.container.Column', {
82597
82598     extend: 'Ext.layout.container.Auto',
82599     alias: ['layout.column'],
82600     alternateClassName: 'Ext.layout.ColumnLayout',
82601
82602     type: 'column',
82603
82604     itemCls: Ext.baseCSSPrefix + 'column',
82605
82606     targetCls: Ext.baseCSSPrefix + 'column-layout-ct',
82607
82608     scrollOffset: 0,
82609
82610     bindToOwnerCtComponent: false,
82611
82612     getRenderTarget : function() {
82613         if (!this.innerCt) {
82614
82615             
82616             
82617             this.innerCt = this.getTarget().createChild({
82618                 cls: Ext.baseCSSPrefix + 'column-inner'
82619             });
82620
82621             
82622             
82623             
82624             this.clearEl = this.innerCt.createChild({
82625                 cls: Ext.baseCSSPrefix + 'clear',
82626                 role: 'presentation'
82627             });
82628         }
82629         return this.innerCt;
82630     },
82631
82632     
82633     onLayout : function() {
82634         var me = this,
82635             target = me.getTarget(),
82636             items = me.getLayoutItems(),
82637             len = items.length,
82638             item,
82639             i,
82640             parallelMargins = [],
82641             itemParallelMargins,
82642             size,
82643             availableWidth,
82644             columnWidth;
82645
82646         size = me.getLayoutTargetSize();
82647         if (size.width < len * 10) { 
82648             return;
82649         }
82650
82651         
82652         
82653         
82654         if (me.adjustmentPass) {
82655             if (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) {
82656                 size.width = me.adjustedWidth;
82657             }
82658         } else {
82659             i = target.getStyle('overflow');
82660             if (i && i != 'hidden') {
82661                 me.autoScroll = true;
82662                 if (!(Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks)) {
82663                     target.setStyle('overflow', 'hidden');
82664                     size = me.getLayoutTargetSize();
82665                 }
82666             }
82667         }
82668
82669         availableWidth = size.width - me.scrollOffset;
82670         me.innerCt.setWidth(availableWidth);
82671
82672         
82673         
82674         for (i = 0; i < len; i++) {
82675             item = items[i];
82676             itemParallelMargins = parallelMargins[i] = item.getEl().getMargin('lr');
82677             if (!item.columnWidth) {
82678                 availableWidth -= (item.getWidth() + itemParallelMargins);
82679             }
82680         }
82681
82682         availableWidth = availableWidth < 0 ? 0 : availableWidth;
82683         for (i = 0; i < len; i++) {
82684             item = items[i];
82685             if (item.columnWidth) {
82686                 columnWidth = Math.floor(item.columnWidth * availableWidth) - parallelMargins[i];
82687                 if (item.getWidth() != columnWidth) {
82688                     me.setItemSize(item, columnWidth, item.height);
82689                 }
82690             }
82691         }
82692
82693         
82694         if (!me.adjustmentPass && me.autoScroll) {
82695
82696             
82697             target.setStyle('overflow', 'auto');
82698             me.adjustmentPass = (target.dom.scrollHeight > size.height);
82699             if (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) {
82700                 me.adjustedWidth = size.width - Ext.getScrollBarWidth();
82701             } else {
82702                 target.setStyle('overflow', 'auto');
82703             }
82704
82705             
82706             if (me.adjustmentPass) {
82707                 me.onLayout();
82708             }
82709         }
82710         delete me.adjustmentPass;
82711     }
82712 });
82713
82714
82715 Ext.define('Ext.layout.container.Table', {
82716
82717     
82718
82719     alias: ['layout.table'],
82720     extend: 'Ext.layout.container.Auto',
82721     alternateClassName: 'Ext.layout.TableLayout',
82722
82723     
82724
82725     
82726
82727     
82728     monitorResize:false,
82729
82730     type: 'table',
82731
82732     
82733     
82734     autoSize: true,
82735
82736     clearEl: true, 
82737
82738     targetCls: Ext.baseCSSPrefix + 'table-layout-ct',
82739     tableCls: Ext.baseCSSPrefix + 'table-layout',
82740     cellCls: Ext.baseCSSPrefix + 'table-layout-cell',
82741
82742     
82743     tableAttrs:null,
82744
82745     
82746     renderItems: function(items) {
82747         var tbody = this.getTable().tBodies[0],
82748             rows = tbody.rows,
82749             i = 0,
82750             len = items.length,
82751             cells, curCell, rowIdx, cellIdx, item, trEl, tdEl, itemCt;
82752
82753         
82754         cells = this.calculateCells(items);
82755
82756         
82757         
82758         
82759         for (; i < len; i++) {
82760             curCell = cells[i];
82761             rowIdx = curCell.rowIdx;
82762             cellIdx = curCell.cellIdx;
82763             item = items[i];
82764
82765             
82766             trEl = rows[rowIdx];
82767             if (!trEl) {
82768                 trEl = tbody.insertRow(rowIdx);
82769             }
82770
82771             
82772             itemCt = tdEl = Ext.get(trEl.cells[cellIdx] || trEl.insertCell(cellIdx));
82773             if (this.needsDivWrap()) { 
82774                 itemCt = tdEl.first() || tdEl.createChild({tag: 'div'});
82775                 itemCt.setWidth(null);
82776             }
82777
82778             
82779             if (!item.rendered) {
82780                 this.renderItem(item, itemCt, 0);
82781             }
82782             else if (!this.isValidParent(item, itemCt, 0)) {
82783                 this.moveItem(item, itemCt, 0);
82784             }
82785
82786             
82787             tdEl.set({
82788                 colSpan: item.colspan || 1,
82789                 rowSpan: item.rowspan || 1,
82790                 id: item.cellId || '',
82791                 cls: this.cellCls + ' ' + (item.cellCls || '')
82792             });
82793
82794             
82795             if (!cells[i + 1] || cells[i + 1].rowIdx !== rowIdx) {
82796                 cellIdx++;
82797                 while (trEl.cells[cellIdx]) {
82798                     trEl.deleteCell(cellIdx);
82799                 }
82800             }
82801         }
82802
82803         
82804         rowIdx++;
82805         while (tbody.rows[rowIdx]) {
82806             tbody.deleteRow(rowIdx);
82807         }
82808     },
82809
82810     afterLayout: function() {
82811         this.callParent();
82812
82813         if (this.needsDivWrap()) {
82814             
82815             Ext.Array.forEach(this.getLayoutItems(), function(item) {
82816                 Ext.fly(item.el.dom.parentNode).setWidth(item.getWidth());
82817             });
82818         }
82819     },
82820
82821     
82822     calculateCells: function(items) {
82823         var cells = [],
82824             rowIdx = 0,
82825             colIdx = 0,
82826             cellIdx = 0,
82827             totalCols = this.columns || Infinity,
82828             rowspans = [], 
82829             i = 0, j,
82830             len = items.length,
82831             item;
82832
82833         for (; i < len; i++) {
82834             item = items[i];
82835
82836             
82837             while (colIdx >= totalCols || rowspans[colIdx] > 0) {
82838                 if (colIdx >= totalCols) {
82839                     
82840                     colIdx = 0;
82841                     cellIdx = 0;
82842                     rowIdx++;
82843
82844                     
82845                     for (j = 0; j < totalCols; j++) {
82846                         if (rowspans[j] > 0) {
82847                             rowspans[j]--;
82848                         }
82849                     }
82850                 } else {
82851                     colIdx++;
82852                 }
82853             }
82854
82855             
82856             cells.push({
82857                 rowIdx: rowIdx,
82858                 cellIdx: cellIdx
82859             });
82860
82861             
82862             rowspans[colIdx] = item.rowspan || 1;
82863             colIdx += item.colspan || 1;
82864             cellIdx++;
82865         }
82866
82867         return cells;
82868     },
82869
82870     
82871     getTable: function() {
82872         var table = this.table;
82873         if (!table) {
82874             table = this.table = this.getTarget().createChild(
82875                 Ext.apply({
82876                     tag: 'table',
82877                     role: 'presentation',
82878                     cls: this.tableCls,
82879                     cellspacing: 0, 
82880                     cn: {tag: 'tbody'}
82881                 }, this.tableAttrs),
82882                 null, true
82883             );
82884         }
82885         return table;
82886     },
82887
82888     
82889     needsDivWrap: function() {
82890         return Ext.isOpera10_5;
82891     }
82892 });
82893
82894 Ext.define('Ext.menu.Item', {
82895     extend: 'Ext.Component',
82896     alias: 'widget.menuitem',
82897     alternateClassName: 'Ext.menu.TextItem',
82898     
82899     
82900
82901     
82902     activeCls: Ext.baseCSSPrefix + 'menu-item-active',
82903     
82904     
82905     ariaRole: 'menuitem',
82906     
82907     
82908     canActivate: true,
82909     
82910     
82911     clickHideDelay: 1,
82912     
82913     
82914     destroyMenu: true,
82915     
82916     
82917     disabledCls: Ext.baseCSSPrefix + 'menu-item-disabled',
82918     
82919     
82920      
82921      
82922     
82923     
82924     hideOnClick: true,
82925     
82926     
82927      
82928     
82929     
82930     isMenuItem: true,
82931     
82932     
82933     
82934     
82935     menuAlign: 'tl-tr?',
82936     
82937     
82938     menuExpandDelay: 200,
82939     
82940     
82941     menuHideDelay: 200,
82942     
82943     
82944     
82945     renderTpl: [
82946         '<tpl if="plain">',
82947             '{text}',
82948         '</tpl>',
82949         '<tpl if="!plain">',
82950             '<a class="' + Ext.baseCSSPrefix + 'menu-item-link" href="{href}" <tpl if="hrefTarget">target="{hrefTarget}"</tpl> hidefocus="true" unselectable="on">',
82951                 '<img src="{icon}" class="' + Ext.baseCSSPrefix + 'menu-item-icon {iconCls}" />',
82952                 '<span class="' + Ext.baseCSSPrefix + 'menu-item-text" <tpl if="menu">style="margin-right: 17px;"</tpl> >{text}</span>',
82953                 '<tpl if="menu">',
82954                     '<img src="' + Ext.BLANK_IMAGE_URL + '" class="' + Ext.baseCSSPrefix + 'menu-item-arrow" />',
82955                 '</tpl>',
82956             '</a>',
82957         '</tpl>'
82958     ],
82959     
82960     maskOnDisable: false,
82961     
82962     
82963     
82964     activate: function() {
82965         var me = this;
82966         
82967         if (!me.activated && me.canActivate && me.rendered && !me.isDisabled() && me.isVisible()) {
82968             me.el.addCls(me.activeCls);
82969             me.focus();
82970             me.activated = true;
82971             me.fireEvent('activate', me);
82972         }
82973     },
82974     
82975     blur: function() {
82976         this.$focused = false;
82977         this.callParent(arguments);
82978     },
82979     
82980     deactivate: function() {
82981         var me = this;
82982         
82983         if (me.activated) {
82984             me.el.removeCls(me.activeCls);
82985             me.blur();
82986             me.hideMenu();
82987             me.activated = false;
82988             me.fireEvent('deactivate', me);
82989         }
82990     },
82991     
82992     deferExpandMenu: function() {
82993         var me = this;
82994         
82995         if (!me.menu.rendered || !me.menu.isVisible()) {
82996             me.parentMenu.activeChild = me.menu;
82997             me.menu.parentItem = me;
82998             me.menu.parentMenu = me.menu.ownerCt = me.parentMenu;
82999             me.menu.showBy(me, me.menuAlign);
83000         }
83001     },
83002     
83003     deferHideMenu: function() {
83004         if (this.menu.isVisible()) {
83005             this.menu.hide();
83006         }
83007     },
83008     
83009     deferHideParentMenus: function() {
83010         Ext.menu.Manager.hideAll();
83011     },
83012     
83013     expandMenu: function(delay) {
83014         var me = this;
83015         
83016         if (me.menu) {
83017             clearTimeout(me.hideMenuTimer);
83018             if (delay === 0) {
83019                 me.deferExpandMenu();
83020             } else {
83021                 me.expandMenuTimer = Ext.defer(me.deferExpandMenu, Ext.isNumber(delay) ? delay : me.menuExpandDelay, me);
83022             }
83023         }
83024     },
83025     
83026     focus: function() {
83027         this.$focused = true;
83028         this.callParent(arguments);
83029     },
83030     
83031     getRefItems: function(deep){
83032         var menu = this.menu,
83033             items;
83034         
83035         if (menu) {
83036             items = menu.getRefItems(deep);
83037             items.unshift(menu);
83038         }   
83039         return items || [];   
83040     },
83041     
83042     hideMenu: function(delay) {
83043         var me = this;
83044         
83045         if (me.menu) {
83046             clearTimeout(me.expandMenuTimer);
83047             me.hideMenuTimer = Ext.defer(me.deferHideMenu, Ext.isNumber(delay) ? delay : me.menuHideDelay, me);
83048         }
83049     },
83050     
83051     initComponent: function() {
83052         var me = this,
83053             prefix = Ext.baseCSSPrefix,
83054             cls = [prefix + 'menu-item'];
83055         
83056         me.addEvents(
83057             
83058             'activate',
83059             
83060             
83061             'click',
83062             
83063             
83064             'deactivate'
83065         );
83066         
83067         if (me.plain) {
83068             cls.push(prefix + 'menu-item-plain');
83069         }
83070         
83071         if (me.cls) {
83072             cls.push(me.cls);
83073         }
83074         
83075         me.cls = cls.join(' ');
83076         
83077         if (me.menu) {
83078             me.menu = Ext.menu.Manager.get(me.menu);
83079         }
83080         
83081         me.callParent(arguments);
83082     },
83083     
83084     onClick: function(e) {
83085         var me = this;
83086         
83087         if (!me.href) {
83088             e.stopEvent();
83089         }
83090         
83091         if (me.disabled) {
83092             return;
83093         }
83094         
83095         if (me.hideOnClick) {
83096             me.deferHideParentMenusTimer = Ext.defer(me.deferHideParentMenus, me.clickHideDelay, me);
83097         }
83098         
83099         Ext.callback(me.handler, me.scope || me, [me, e]);
83100         me.fireEvent('click', me, e);
83101         
83102         if (!me.hideOnClick) {
83103             me.focus();
83104         }
83105     },
83106     
83107     onDestroy: function() {
83108         var me = this;
83109         
83110         clearTimeout(me.expandMenuTimer);
83111         clearTimeout(me.hideMenuTimer);
83112         clearTimeout(me.deferHideParentMenusTimer);
83113         
83114         if (me.menu) {
83115             delete me.menu.parentItem;
83116             delete me.menu.parentMenu;
83117             delete me.menu.ownerCt;
83118             if (me.destroyMenu !== false) {
83119                 me.menu.destroy();
83120             }
83121         }
83122         me.callParent(arguments);
83123     },
83124     
83125     onRender: function(ct, pos) {
83126         var me = this,
83127             prefix = '.' + Ext.baseCSSPrefix;
83128         
83129         Ext.applyIf(me.renderData, {
83130             href: me.href || '#',
83131             hrefTarget: me.hrefTarget,
83132             icon: me.icon || Ext.BLANK_IMAGE_URL,
83133             iconCls: me.iconCls,
83134             menu: Ext.isDefined(me.menu),
83135             plain: me.plain,
83136             text: me.text
83137         });
83138         
83139         Ext.applyIf(me.renderSelectors, {
83140             itemEl: prefix + 'menu-item-link',
83141             iconEl: prefix + 'menu-item-icon',
83142             textEl: prefix + 'menu-item-text',
83143             arrowEl: prefix + 'menu-item-arrow'
83144         });
83145         
83146         me.callParent(arguments);
83147     },
83148     
83149     
83150     setHandler: function(fn, scope) {
83151         this.handler = fn || null;
83152         this.scope = scope;
83153     },
83154     
83155     
83156     setIconCls: function(iconCls) {
83157         var me = this;
83158         
83159         if (me.iconEl) {
83160             if (me.iconCls) {
83161                 me.iconEl.removeCls(me.iconCls);
83162             }
83163             
83164             if (iconCls) {
83165                 me.iconEl.addCls(iconCls);
83166             }
83167         }
83168         
83169         me.iconCls = iconCls;
83170     },
83171     
83172     
83173     setText: function(text) {
83174         var me = this,
83175             el = me.textEl || me.el,
83176             newWidth;
83177         
83178         if (text && el) {
83179             el.update(text);
83180                 
83181             if (me.textEl) {
83182                 
83183                 newWidth = me.textEl.getWidth() + me.iconEl.getWidth() + 25 + (me.arrowEl ? me.arrowEl.getWidth() : 0);
83184                 if (newWidth > me.itemEl.getWidth()) {
83185                     me.parentMenu.setWidth(newWidth);
83186                 }
83187             }
83188         } else if (el) {
83189             el.update('');
83190         }
83191         
83192         me.text = text;
83193     }
83194 });
83195
83196
83197
83198 Ext.define('Ext.menu.CheckItem', {
83199     extend: 'Ext.menu.Item',
83200     alias: 'widget.menucheckitem',
83201
83202     
83203     checkedCls: Ext.baseCSSPrefix + 'menu-item-checked',
83204     
83205     uncheckedCls: Ext.baseCSSPrefix + 'menu-item-unchecked',
83206     
83207     groupCls: Ext.baseCSSPrefix + 'menu-group-icon',
83208
83209     
83210     hideOnClick: false,
83211
83212     afterRender: function() {
83213         var me = this;
83214         this.callParent();
83215         me.checked = !me.checked;
83216         me.setChecked(!me.checked, true);
83217     },
83218
83219     initComponent: function() {
83220         var me = this;
83221         me.addEvents(
83222             
83223             'beforecheckchange',
83224
83225             
83226             'checkchange'
83227         );
83228
83229         me.callParent(arguments);
83230
83231         Ext.menu.Manager.registerCheckable(me);
83232
83233         if (me.group) {
83234             if (!me.iconCls) {
83235                 me.iconCls = me.groupCls;
83236             }
83237             if (me.initialConfig.hideOnClick !== false) {
83238                 me.hideOnClick = true;
83239             }
83240         }
83241     },
83242
83243     
83244     disableCheckChange: function() {
83245         var me = this;
83246
83247         me.iconEl.addCls(me.disabledCls);
83248         me.checkChangeDisabled = true;
83249     },
83250
83251     
83252     enableCheckChange: function() {
83253         var me = this;
83254
83255         me.iconEl.removeCls(me.disabledCls);
83256         me.checkChangeDisabled = false;
83257     },
83258
83259     onClick: function(e) {
83260         var me = this;
83261         if(!me.disabled && !me.checkChangeDisabled && !(me.checked && me.group)) {
83262             me.setChecked(!me.checked);
83263         }
83264         this.callParent([e]);
83265     },
83266
83267     onDestroy: function() {
83268         Ext.menu.Manager.unregisterCheckable(this);
83269         this.callParent(arguments);
83270     },
83271
83272     
83273     setChecked: function(checked, suppressEvents) {
83274         var me = this;
83275         if (me.checked !== checked && (suppressEvents || me.fireEvent('beforecheckchange', me, checked) !== false)) {
83276             if (me.el) {
83277                 me.el[checked  ? 'addCls' : 'removeCls'](me.checkedCls)[!checked ? 'addCls' : 'removeCls'](me.uncheckedCls);
83278             }
83279             me.checked = checked;
83280             Ext.menu.Manager.onCheckChange(me, checked);
83281             if (!suppressEvents) {
83282                 Ext.callback(me.checkHandler, me.scope, [me, checked]);
83283                 me.fireEvent('checkchange', me, checked);
83284             }
83285         }
83286     }
83287 });
83288
83289
83290 Ext.define('Ext.menu.KeyNav', {
83291     extend: 'Ext.util.KeyNav',
83292
83293     requires: ['Ext.FocusManager'],
83294     
83295     constructor: function(menu) {
83296         var me = this;
83297
83298         me.menu = menu;
83299         me.callParent([menu.el, {
83300             down: me.down,
83301             enter: me.enter,
83302             esc: me.escape,
83303             left: me.left,
83304             right: me.right,
83305             space: me.enter,
83306             tab: me.tab,
83307             up: me.up
83308         }]);
83309     },
83310
83311     down: function(e) {
83312         var me = this,
83313             fi = me.menu.focusedItem;
83314
83315         if (fi && e.getKey() == Ext.EventObject.DOWN && me.isWhitelisted(fi)) {
83316             return true;
83317         }
83318         me.focusNextItem(1);
83319     },
83320
83321     enter: function(e) {
83322         var menu = this.menu;
83323
83324         if (menu.activeItem) {
83325             menu.onClick(e);
83326         }
83327     },
83328
83329     escape: function(e) {
83330         Ext.menu.Manager.hideAll();
83331     },
83332
83333     focusNextItem: function(step) {
83334         var menu = this.menu,
83335             items = menu.items,
83336             focusedItem = menu.focusedItem,
83337             startIdx = focusedItem ? items.indexOf(focusedItem) : -1,
83338             idx = startIdx + step;
83339
83340         while (idx != startIdx) {
83341             if (idx < 0) {
83342                 idx = items.length - 1;
83343             } else if (idx >= items.length) {
83344                 idx = 0;
83345             }
83346
83347             var item = items.getAt(idx);
83348             if (menu.canActivateItem(item)) {
83349                 menu.setActiveItem(item);
83350                 break;
83351             }
83352             idx += step;
83353         }
83354     },
83355
83356     isWhitelisted: function(item) {
83357         return Ext.FocusManager.isWhitelisted(item);
83358     },
83359
83360     left: function(e) {
83361         var menu = this.menu,
83362             fi = menu.focusedItem,
83363             ai = menu.activeItem;
83364
83365         if (fi && this.isWhitelisted(fi)) {
83366             return true;
83367         }
83368
83369         menu.hide();
83370         if (menu.parentMenu) {
83371             menu.parentMenu.focus();
83372         }
83373     },
83374
83375     right: function(e) {
83376         var menu = this.menu,
83377             fi = menu.focusedItem,
83378             ai = menu.activeItem,
83379             am;
83380
83381         if (fi && this.isWhitelisted(fi)) {
83382             return true;
83383         }
83384
83385         if (ai) {
83386             am = menu.activeItem.menu;
83387             if (am) {
83388                 ai.expandMenu(0);
83389                 Ext.defer(function() {
83390                     am.setActiveItem(am.items.getAt(0));
83391                 }, 25);
83392             }
83393         }
83394     },
83395
83396     tab: function(e) {
83397         var me = this;
83398
83399         if (e.shiftKey) {
83400             me.up(e);
83401         } else {
83402             me.down(e);
83403         }
83404     },
83405
83406     up: function(e) {
83407         var me = this,
83408             fi = me.menu.focusedItem;
83409
83410         if (fi && e.getKey() == Ext.EventObject.UP && me.isWhitelisted(fi)) {
83411             return true;
83412         }
83413         me.focusNextItem(-1);
83414     }
83415 });
83416
83417 Ext.define('Ext.menu.Separator', {
83418     extend: 'Ext.menu.Item',
83419     alias: 'widget.menuseparator',
83420     
83421     
83422     
83423     
83424     canActivate: false,
83425     
83426     
83427      
83428     
83429      
83430     
83431      
83432     focusable: false,
83433      
83434     
83435     
83436     
83437     
83438     
83439     hideOnClick: false,
83440     
83441     
83442     
83443     
83444     
83445     
83446     
83447     
83448     
83449     
83450     
83451     
83452     
83453     
83454     plain: true,
83455     
83456     
83457     separatorCls: Ext.baseCSSPrefix + 'menu-item-separator',
83458     
83459     
83460     text: '&#160;',
83461     
83462     onRender: function(ct, pos) {
83463         var me = this,
83464             sepCls = me.separatorCls;
83465             
83466         me.cls += ' ' + sepCls;
83467         
83468         Ext.applyIf(me.renderSelectors, {
83469             itemSepEl: '.' + sepCls
83470         });
83471         
83472         me.callParent(arguments);
83473     }
83474 });
83475
83476 Ext.define('Ext.menu.Menu', {
83477     extend: 'Ext.panel.Panel',
83478     alias: 'widget.menu',
83479     requires: [
83480         'Ext.layout.container.Fit',
83481         'Ext.layout.container.VBox',
83482         'Ext.menu.CheckItem',
83483         'Ext.menu.Item',
83484         'Ext.menu.KeyNav',
83485         'Ext.menu.Manager',
83486         'Ext.menu.Separator'
83487     ],
83488
83489     
83490     allowOtherMenus: false,
83491
83492     
83493     ariaRole: 'menu',
83494
83495     
83496
83497     
83498     defaultAlign: 'tl-bl?',
83499
83500     
83501     floating: true,
83502
83503     
83504     constrain: false,
83505
83506     
83507     hidden: true,
83508
83509     
83510     ignoreParentClicks: false,
83511
83512     isMenu: true,
83513
83514     
83515
83516     
83517     showSeparator : true,
83518
83519     
83520     minWidth: 120,
83521
83522     
83523
83524     initComponent: function() {
83525         var me = this,
83526             prefix = Ext.baseCSSPrefix,
83527             cls = [prefix + 'menu'],
83528             bodyCls = me.bodyCls ? [me.bodyCls] : [];
83529
83530         me.addEvents(
83531             
83532             'click',
83533
83534             
83535             'mouseenter',
83536
83537             
83538             'mouseleave',
83539
83540             
83541             'mouseover'
83542         );
83543
83544         Ext.menu.Manager.register(me);
83545
83546         
83547         if (me.plain) {
83548             cls.push(prefix + 'menu-plain');
83549         }
83550         me.cls = cls.join(' ');
83551
83552         
83553         bodyCls.unshift(prefix + 'menu-body');
83554         me.bodyCls = bodyCls.join(' ');
83555
83556         
83557         
83558         
83559         
83560         me.layout = {
83561             type: 'vbox',
83562             align: 'stretchmax',
83563             autoSize: true,
83564             clearInnerCtOnLayout: true,
83565             overflowHandler: 'Scroller'
83566         };
83567
83568         
83569         if (me.floating === false && me.initialConfig.hidden !== true) {
83570             me.hidden = false;
83571         }
83572
83573         me.callParent(arguments);
83574
83575         me.on('beforeshow', function() {
83576             var hasItems = !!me.items.length;
83577             
83578             
83579             
83580             if (hasItems && me.rendered) {
83581                 me.el.setStyle('visibility', null);
83582             }
83583             return hasItems;
83584         });
83585     },
83586
83587     afterRender: function(ct) {
83588         var me = this,
83589             prefix = Ext.baseCSSPrefix,
83590             space = '&#160;';
83591
83592         me.callParent(arguments);
83593
83594         
83595         if (me.showSeparator) {
83596             me.iconSepEl = me.layout.getRenderTarget().insertFirst({
83597                 cls: prefix + 'menu-icon-separator',
83598                 html: space
83599             });
83600         }
83601
83602         me.focusEl = me.el.createChild({
83603             cls: prefix + 'menu-focus',
83604             tabIndex: '-1',
83605             html: space
83606         });
83607
83608         me.mon(me.el, {
83609             click: me.onClick,
83610             mouseover: me.onMouseOver,
83611             scope: me
83612         });
83613         me.mouseMonitor = me.el.monitorMouseLeave(100, me.onMouseLeave, me);
83614
83615         if (me.showSeparator && ((!Ext.isStrict && Ext.isIE) || Ext.isIE6)) {
83616             me.iconSepEl.setHeight(me.el.getHeight());
83617         }
83618
83619         me.keyNav = Ext.create('Ext.menu.KeyNav', me);
83620     },
83621
83622     afterLayout: function() {
83623         var me = this;
83624         me.callParent(arguments);
83625
83626         
83627         
83628         
83629         
83630         if ((!Ext.iStrict && Ext.isIE) || Ext.isIE6) {
83631             var innerCt = me.layout.getRenderTarget(),
83632                 innerCtWidth = 0,
83633                 dis = me.dockedItems,
83634                 l = dis.length,
83635                 i = 0,
83636                 di, clone, newWidth;
83637
83638             innerCtWidth = innerCt.getWidth();
83639
83640             newWidth = innerCtWidth + me.body.getBorderWidth('lr') + me.body.getPadding('lr');
83641
83642             
83643             me.body.setWidth(newWidth);
83644
83645             
83646             for (; i < l, di = dis.getAt(i); i++) {
83647                 if (di.dock == 'left' || di.dock == 'right') {
83648                     newWidth += di.getWidth();
83649                 }
83650             }
83651             me.el.setWidth(newWidth);
83652         }
83653     },
83654
83655     
83656     canActivateItem: function(item) {
83657         return item && !item.isDisabled() && item.isVisible() && (item.canActivate || item.getXTypes().indexOf('menuitem') < 0);
83658     },
83659
83660     
83661     deactivateActiveItem: function() {
83662         var me = this;
83663
83664         if (me.activeItem) {
83665             me.activeItem.deactivate();
83666             if (!me.activeItem.activated) {
83667                 delete me.activeItem;
83668             }
83669         }
83670         if (me.focusedItem) {
83671             me.focusedItem.blur();
83672             if (!me.focusedItem.$focused) {
83673                 delete me.focusedItem;
83674             }
83675         }
83676     },
83677
83678     
83679     getFocusEl: function() {
83680         return this.focusEl;
83681     },
83682
83683     
83684     hide: function() {
83685         this.deactivateActiveItem();
83686         this.callParent(arguments);
83687     },
83688
83689     
83690     getItemFromEvent: function(e) {
83691         return this.getChildByElement(e.getTarget());
83692     },
83693
83694     lookupComponent: function(cmp) {
83695         var me = this;
83696
83697         if (Ext.isString(cmp)) {
83698             cmp = me.lookupItemFromString(cmp);
83699         } else if (Ext.isObject(cmp)) {
83700             cmp = me.lookupItemFromObject(cmp);
83701         }
83702
83703         
83704         
83705         cmp.minWidth = cmp.minWidth || me.minWidth;
83706
83707         return cmp;
83708     },
83709
83710     
83711     lookupItemFromObject: function(cmp) {
83712         var me = this,
83713             prefix = Ext.baseCSSPrefix,
83714             cls,
83715             intercept;
83716
83717         if (!cmp.isComponent) {
83718             if (!cmp.xtype) {
83719                 cmp = Ext.create('Ext.menu.' + (Ext.isBoolean(cmp.checked) ? 'Check': '') + 'Item', cmp);
83720             } else {
83721                 cmp = Ext.ComponentManager.create(cmp, cmp.xtype);
83722             }
83723         }
83724
83725         if (cmp.isMenuItem) {
83726             cmp.parentMenu = me;
83727         }
83728
83729         if (!cmp.isMenuItem && !cmp.dock) {
83730             cls = [prefix + 'menu-item', prefix + 'menu-item-cmp'];
83731             intercept = Ext.Function.createInterceptor;
83732
83733             
83734             cmp.focus = intercept(cmp.focus, function() {
83735                 this.$focused = true;
83736             }, cmp);
83737             cmp.blur = intercept(cmp.blur, function() {
83738                 this.$focused = false;
83739             }, cmp);
83740
83741             if (!me.plain && (cmp.indent === true || cmp.iconCls === 'no-icon')) {
83742                 cls.push(prefix + 'menu-item-indent');
83743             }
83744
83745             if (cmp.rendered) {
83746                 cmp.el.addCls(cls);
83747             } else {
83748                 cmp.cls = (cmp.cls ? cmp.cls : '') + ' ' + cls.join(' ');
83749             }
83750             cmp.isMenuItem = true;
83751         }
83752         return cmp;
83753     },
83754
83755     
83756     lookupItemFromString: function(cmp) {
83757         return (cmp == 'separator' || cmp == '-') ?
83758             Ext.createWidget('menuseparator')
83759             : Ext.createWidget('menuitem', {
83760                 canActivate: false,
83761                 hideOnClick: false,
83762                 plain: true,
83763                 text: cmp
83764             });
83765     },
83766
83767     onClick: function(e) {
83768         var me = this,
83769             item;
83770
83771         if (me.disabled) {
83772             e.stopEvent();
83773             return;
83774         }
83775
83776         if ((e.getTarget() == me.focusEl.dom) || e.within(me.layout.getRenderTarget())) {
83777             item = me.getItemFromEvent(e) || me.activeItem;
83778
83779             if (item) {
83780                 if (item.getXTypes().indexOf('menuitem') >= 0) {
83781                     if (!item.menu || !me.ignoreParentClicks) {
83782                         item.onClick(e);
83783                     } else {
83784                         e.stopEvent();
83785                     }
83786                 }
83787             }
83788             me.fireEvent('click', me, item, e);
83789         }
83790     },
83791
83792     onDestroy: function() {
83793         var me = this;
83794
83795         Ext.menu.Manager.unregister(me);
83796         if (me.rendered) {
83797             me.el.un(me.mouseMonitor);
83798             me.keyNav.destroy();
83799             delete me.keyNav;
83800         }
83801         me.callParent(arguments);
83802     },
83803
83804     onMouseLeave: function(e) {
83805         var me = this;
83806
83807         me.deactivateActiveItem();
83808
83809         if (me.disabled) {
83810             return;
83811         }
83812
83813         me.fireEvent('mouseleave', me, e);
83814     },
83815
83816     onMouseOver: function(e) {
83817         var me = this,
83818             fromEl = e.getRelatedTarget(),
83819             mouseEnter = !me.el.contains(fromEl),
83820             item = me.getItemFromEvent(e);
83821
83822         if (mouseEnter && me.parentMenu) {
83823             me.parentMenu.setActiveItem(me.parentItem);
83824             me.parentMenu.mouseMonitor.mouseenter();
83825         }
83826
83827         if (me.disabled) {
83828             return;
83829         }
83830
83831         if (item) {
83832             me.setActiveItem(item);
83833             if (item.activated && item.expandMenu) {
83834                 item.expandMenu();
83835             }
83836         }
83837         if (mouseEnter) {
83838             me.fireEvent('mouseenter', me, e);
83839         }
83840         me.fireEvent('mouseover', me, item, e);
83841     },
83842
83843     setActiveItem: function(item) {
83844         var me = this;
83845
83846         if (item && (item != me.activeItem && item != me.focusedItem)) {
83847             me.deactivateActiveItem();
83848             if (me.canActivateItem(item)) {
83849                 if (item.activate) {
83850                     item.activate();
83851                     if (item.activated) {
83852                         me.activeItem = item;
83853                         me.focusedItem = item;
83854                         me.focus();
83855                     }
83856                 } else {
83857                     item.focus();
83858                     me.focusedItem = item;
83859                 }
83860             }
83861             item.el.scrollIntoView(me.layout.getRenderTarget());
83862         }
83863     },
83864
83865     
83866     showBy: function(cmp, pos, off) {
83867         var me = this,
83868             xy,
83869             region;
83870
83871         if (me.floating && cmp) {
83872             me.layout.autoSize = true;
83873             me.show();
83874
83875             
83876             cmp = cmp.el || cmp;
83877
83878             
83879             xy = me.el.getAlignToXY(cmp, pos || me.defaultAlign, off);
83880             if (me.floatParent) {
83881                 region = me.floatParent.getTargetEl().getViewRegion();
83882                 xy[0] -= region.x;
83883                 xy[1] -= region.y;
83884             }
83885             me.showAt(xy);
83886         }
83887         return me;
83888     },
83889     
83890     
83891     showAt: function(){
83892         this.callParent(arguments);
83893         if (this.floating) {
83894             this.doConstrain();
83895         }    
83896     },
83897
83898     doConstrain : function() {
83899         var me = this,
83900             y = me.el.getY(),
83901             max, full,
83902             vector,
83903             returnY = y, normalY, parentEl, scrollTop, viewHeight;
83904
83905         delete me.height;
83906         me.setSize();
83907         full = me.getHeight();
83908         if (me.floating) {
83909             parentEl = Ext.fly(me.el.dom.parentNode);
83910             scrollTop = parentEl.getScroll().top;
83911             viewHeight = parentEl.getViewSize().height;
83912             
83913             
83914             normalY = y - scrollTop;
83915             max = me.maxHeight ? me.maxHeight : viewHeight - normalY;
83916             if (full > viewHeight) {
83917                 max = viewHeight;
83918                 
83919                 returnY = y - normalY;
83920             } else if (max < full) {
83921                 returnY = y - (full - max);
83922                 max = full;
83923             }
83924         }else{
83925             max = me.getHeight();
83926         }
83927         
83928         if (me.maxHeight){
83929             max = Math.min(me.maxHeight, max);
83930         }
83931         if (full > max && max > 0){
83932             me.layout.autoSize = false;
83933             me.setHeight(max);
83934             if (me.showSeparator){
83935                 me.iconSepEl.setHeight(me.layout.getRenderTarget().dom.scrollHeight);
83936             }
83937         }
83938         vector = me.getConstrainVector();
83939         if (vector) {
83940             me.setPosition(me.getPosition()[0] + vector[0]);
83941         }
83942         me.el.setY(returnY);
83943     }
83944 });
83945
83946  Ext.define('Ext.menu.ColorPicker', {
83947      extend: 'Ext.menu.Menu',
83948
83949      alias: 'widget.colormenu',
83950
83951      requires: [
83952         'Ext.picker.Color'
83953      ],
83954
83955     
83956     hideOnClick : true,
83957
83958     
83959     pickerId : null,
83960
83961     
83962
83963     
83964
83965     
83966
83967     
83968
83969     initComponent : function(){
83970         var me = this;
83971
83972         Ext.apply(me, {
83973             plain: true,
83974             showSeparator: false,
83975             items: Ext.applyIf({
83976                 cls: Ext.baseCSSPrefix + 'menu-color-item',
83977                 id: me.pickerId,
83978                 xtype: 'colorpicker'
83979             }, me.initialConfig)
83980         });
83981
83982         me.callParent(arguments);
83983
83984         me.picker = me.down('colorpicker');
83985
83986         
83987         me.relayEvents(me.picker, ['select']);
83988
83989         if (me.hideOnClick) {
83990             me.on('select', me.hidePickerOnSelect, me);
83991         }
83992     },
83993
83994     
83995     hidePickerOnSelect: function() {
83996         Ext.menu.Manager.hideAll();
83997     }
83998  });
83999
84000  Ext.define('Ext.menu.DatePicker', {
84001      extend: 'Ext.menu.Menu',
84002
84003      alias: 'widget.datemenu',
84004
84005      requires: [
84006         'Ext.picker.Date'
84007      ],
84008
84009     
84010     hideOnClick : true,
84011
84012     
84013     pickerId : null,
84014
84015     
84016
84017     
84018
84019     
84020
84021     
84022
84023     initComponent : function(){
84024         var me = this;
84025
84026         Ext.apply(me, {
84027             showSeparator: false,
84028             plain: true,
84029             items: Ext.applyIf({
84030                 cls: Ext.baseCSSPrefix + 'menu-date-item',
84031                 id: me.pickerId,
84032                 xtype: 'datepicker'
84033             }, me.initialConfig)
84034         });
84035
84036         me.callParent(arguments);
84037
84038         me.picker = me.down('datepicker');
84039         
84040         me.relayEvents(me.picker, ['select']);
84041
84042         if (me.hideOnClick) {
84043             me.on('select', me.hidePickerOnSelect, me);
84044         }
84045     },
84046
84047     hidePickerOnSelect: function() {
84048         Ext.menu.Manager.hideAll();
84049     }
84050  });
84051
84052 Ext.define('Ext.panel.Tool', {
84053     extend: 'Ext.Component',
84054     requires: ['Ext.tip.QuickTipManager'],
84055     alias: 'widget.tool',
84056
84057     baseCls: Ext.baseCSSPrefix + 'tool',
84058     disabledCls: Ext.baseCSSPrefix + 'tool-disabled',
84059     toolPressedCls: Ext.baseCSSPrefix + 'tool-pressed',
84060     toolOverCls: Ext.baseCSSPrefix + 'tool-over',
84061     ariaRole: 'button',
84062     renderTpl: ['<img src="{blank}" class="{baseCls}-{type}" role="presentation"/>'],
84063     
84064     
84065     
84066     
84067     
84068     
84069     
84070     
84071     
84072     
84073     stopEvent: true,
84074
84075     initComponent: function() {
84076         var me = this;
84077         me.addEvents(
84078             
84079             'click'
84080         );
84081         
84082         var types = [
84083             'close', 
84084             'collapse', 
84085             'down', 
84086             'expand', 
84087             'gear', 
84088             'help', 
84089             'left', 
84090             'maximize', 
84091             'minimize', 
84092             'minus', 
84093             'move', 
84094             'next', 
84095             'pin', 
84096             'plus', 
84097             'prev', 
84098             'print', 
84099             'refresh', 
84100             'resize', 
84101             'restore', 
84102             'right', 
84103             'save', 
84104             'search', 
84105             'toggle',
84106             'unpin', 
84107             'up'
84108         ];
84109         
84110         if (me.id && Ext.Array.indexOf(types, me.id) > -1 && Ext.global.console) {
84111             Ext.global.console.warn('When specifying a tool you should use the type option, the id can conflict now that tool is a Component');
84112         }
84113         
84114         me.type = me.type || me.id;
84115
84116         Ext.applyIf(me.renderData, {
84117             baseCls: me.baseCls,
84118             blank: Ext.BLANK_IMAGE_URL,
84119             type: me.type
84120         });
84121         me.renderSelectors.toolEl = '.' + me.baseCls + '-' + me.type;
84122         me.callParent();
84123     },
84124
84125     
84126     afterRender: function() {
84127         var me = this;
84128         me.callParent(arguments);
84129         if (me.qtip) {
84130             if (Ext.isObject(me.qtip)) {
84131                 Ext.tip.QuickTipManager.register(Ext.apply({
84132                     target: me.id
84133                 }, me.qtip));
84134             }
84135             else {
84136                 me.toolEl.dom.qtip = me.qtip;
84137             }
84138         }
84139
84140         me.mon(me.toolEl, {
84141             click: me.onClick,
84142             mousedown: me.onMouseDown,
84143             mouseover: me.onMouseOver,
84144             mouseout: me.onMouseOut,
84145             scope: me
84146         });
84147     },
84148
84149     
84150     setType: function(type) {
84151         var me = this;
84152         
84153         me.type = type;
84154         if (me.rendered) {
84155             me.toolEl.dom.className = me.baseCls + '-' + type;
84156         }
84157         return me;
84158     },
84159
84160     
84161     bindTo: function(component) {
84162         this.owner = component;
84163     },
84164
84165     
84166     onClick: function(e, target) {
84167         var me = this,
84168             owner;
84169             
84170         if (me.disabled) {
84171             return false;
84172         }
84173         owner = me.owner || me.ownerCt;
84174
84175         
84176         me.el.removeCls(me.toolPressedCls);
84177         me.el.removeCls(me.toolOverCls);
84178
84179         if (me.stopEvent !== false) {
84180             e.stopEvent();
84181         }
84182
84183         Ext.callback(me.handler, me.scope || me, [e, target, owner, me]);
84184         me.fireEvent('click', me, e);
84185         return true;
84186     },
84187     
84188     
84189     onDestroy: function(){
84190         if (Ext.isObject(this.tooltip)) {
84191             Ext.tip.QuickTipManager.unregister(this.id);
84192         }    
84193         this.callParent();
84194     },
84195
84196     
84197     onMouseDown: function() {
84198         if (this.disabled) {
84199             return false;
84200         }
84201
84202         this.el.addCls(this.toolPressedCls);
84203     },
84204
84205     
84206     onMouseOver: function() {
84207         if (this.disabled) {
84208             return false;
84209         }
84210         this.el.addCls(this.toolOverCls);
84211     },
84212
84213     
84214     onMouseOut: function() {
84215         this.el.removeCls(this.toolOverCls);
84216     }
84217 });
84218
84219 Ext.define('Ext.resizer.Handle', {
84220     extend: 'Ext.Component',
84221     handleCls: '',
84222     baseHandleCls: Ext.baseCSSPrefix + 'resizable-handle',
84223     
84224     
84225     region: '',
84226
84227     onRender: function() {
84228         this.addCls(
84229             this.baseHandleCls,
84230             this.baseHandleCls + '-' + this.region,
84231             this.handleCls
84232         );
84233         this.callParent(arguments);
84234         this.el.unselectable();
84235     }
84236 });
84237
84238
84239 Ext.define('Ext.resizer.Resizer', {
84240     mixins: {
84241         observable: 'Ext.util.Observable'
84242     },
84243     uses: ['Ext.resizer.ResizeTracker', 'Ext.Component'],
84244
84245     alternateClassName: 'Ext.Resizable',
84246
84247     handleCls: Ext.baseCSSPrefix + 'resizable-handle',
84248     pinnedCls: Ext.baseCSSPrefix + 'resizable-pinned',
84249     overCls:   Ext.baseCSSPrefix + 'resizable-over',
84250     proxyCls:  Ext.baseCSSPrefix + 'resizable-proxy',
84251     wrapCls:   Ext.baseCSSPrefix + 'resizable-wrap',
84252
84253     
84254     dynamic: true,
84255
84256     
84257     handles: 's e se',
84258
84259     
84260     height : null,
84261
84262     
84263     width : null,
84264
84265     
84266     minHeight : 20,
84267
84268     
84269     minWidth : 20,
84270
84271     
84272     maxHeight : 10000,
84273
84274     
84275     maxWidth : 10000,
84276
84277     
84278     pinned: false,
84279
84280     
84281     preserveRatio: false,
84282
84283     
84284     transparent: false,
84285
84286     
84287
84288     possiblePositions: {
84289         n:  'north',
84290         s:  'south',
84291         e:  'east',
84292         w:  'west',
84293         se: 'southeast',
84294         sw: 'southwest',
84295         nw: 'northwest',
84296         ne: 'northeast'
84297     },
84298
84299     
84300
84301     
84302
84303     constructor: function(config) {
84304         var me = this,
84305             target,
84306             tag,
84307             handles = me.handles,
84308             handleCls,
84309             possibles,
84310             len,
84311             i = 0,
84312             pos;
84313
84314         this.addEvents(
84315             
84316             'beforeresize',
84317             
84318             'resizedrag',
84319             
84320             'resize'
84321         );
84322
84323         if (Ext.isString(config) || Ext.isElement(config) || config.dom) {
84324             target = config;
84325             config = arguments[1] || {};
84326             config.target = target;
84327         }
84328         
84329         me.mixins.observable.constructor.call(me, config);
84330
84331         
84332         
84333         target = me.target;
84334         if (target) {
84335             if (target.isComponent) {
84336                 me.el = target.getEl();
84337                 if (target.minWidth) {
84338                     me.minWidth = target.minWidth;
84339                 }
84340                 if (target.minHeight) {
84341                     me.minHeight = target.minHeight;
84342                 }
84343                 if (target.maxWidth) {
84344                     me.maxWidth = target.maxWidth;
84345                 }
84346                 if (target.maxHeight) {
84347                     me.maxHeight = target.maxHeight;
84348                 }
84349                 if (target.floating) {
84350                     if (!this.hasOwnProperty('handles')) {
84351                         this.handles = 'n ne e se s sw w nw';
84352                     }
84353                 }
84354             } else {
84355                 me.el = me.target = Ext.get(target);
84356             }
84357         }
84358         
84359         else {
84360             me.target = me.el = Ext.get(me.el);
84361         }
84362
84363         
84364         
84365         
84366         tag = me.el.dom.tagName;
84367         if (tag == 'TEXTAREA' || tag == 'IMG') {
84368             
84369             me.originalTarget = me.target;
84370             me.target = me.el = me.el.wrap({
84371                 cls: me.wrapCls,
84372                 id: me.el.id + '-rzwrap'
84373             });
84374
84375             
84376             me.el.setPositioning(me.originalTarget.getPositioning());
84377             me.originalTarget.clearPositioning();
84378             var box = me.originalTarget.getBox();
84379             me.el.setBox(box);
84380         }
84381
84382         
84383         
84384         me.el.position();
84385         if (me.pinned) {
84386             me.el.addCls(me.pinnedCls);
84387         }
84388
84389         
84390         me.resizeTracker = Ext.create('Ext.resizer.ResizeTracker', {
84391             disabled: me.disabled,
84392             target: me.target,
84393             constrainTo: me.constrainTo,
84394             overCls: me.overCls,
84395             throttle: me.throttle,
84396             originalTarget: me.originalTarget,
84397             delegate: '.' + me.handleCls,
84398             dynamic: me.dynamic,
84399             preserveRatio: me.preserveRatio,
84400             minHeight: me.minHeight,
84401             maxHeight: me.maxHeight,
84402             minWidth: me.minWidth,
84403             maxWidth: me.maxWidth
84404         });
84405
84406         
84407         me.resizeTracker.on('mousedown', me.onBeforeResize, me);
84408         me.resizeTracker.on('drag', me.onResize, me);
84409         me.resizeTracker.on('dragend', me.onResizeEnd, me);
84410
84411         if (me.handles == 'all') {
84412             me.handles = 'n s e w ne nw se sw';
84413         }
84414
84415         handles = me.handles = me.handles.split(/ |\s*?[,;]\s*?/);
84416         possibles = me.possiblePositions;
84417         len = handles.length;
84418         handleCls = me.handleCls + ' ' + (this.target.isComponent ? (me.target.baseCls + '-handle ') : '') + me.handleCls + '-';
84419
84420         for(; i < len; i++){
84421             
84422             if (handles[i] && possibles[handles[i]]) {
84423                 pos = possibles[handles[i]];
84424                 
84425
84426                 me[pos] = Ext.create('Ext.Component', {
84427                     owner: this,
84428                     region: pos,
84429                     cls: handleCls + pos,
84430                     renderTo: me.el
84431                 });
84432                 me[pos].el.unselectable();
84433                 if (me.transparent) {
84434                     me[pos].el.setOpacity(0);
84435                 }
84436             }
84437         }
84438
84439         
84440         if (Ext.isNumber(me.width)) {
84441             me.width = Ext.Number.constrain(me.width, me.minWidth, me.maxWidth);
84442         }
84443         if (Ext.isNumber(me.height)) {
84444             me.height = Ext.Number.constrain(me.height, me.minHeight, me.maxHeight);
84445         }
84446
84447         
84448         if (me.width != null || me.height != null) {
84449             if (me.originalTarget) {
84450                 me.originalTarget.setWidth(me.width);
84451                 me.originalTarget.setHeight(me.height);
84452             }
84453             me.resizeTo(me.width, me.height);
84454         }
84455
84456         me.forceHandlesHeight();
84457     },
84458
84459     disable: function() {
84460         this.resizeTracker.disable();
84461     },
84462
84463     enable: function() {
84464         this.resizeTracker.enable();
84465     },
84466
84467     
84468     onBeforeResize: function(tracker, e) {
84469         var b = this.target.getBox();
84470         return this.fireEvent('beforeresize', this, b.width, b.height, e);
84471     },
84472
84473     
84474     onResize: function(tracker, e) {
84475         var me = this,
84476             b = me.target.getBox();
84477         me.forceHandlesHeight();
84478         return me.fireEvent('resizedrag', me, b.width, b.height, e);
84479     },
84480
84481     
84482     onResizeEnd: function(tracker, e) {
84483         var me = this,
84484             b = me.target.getBox();
84485         me.forceHandlesHeight();
84486         return me.fireEvent('resize', me, b.width, b.height, e);
84487     },
84488
84489     
84490     resizeTo : function(width, height){
84491         this.target.setSize(width, height);
84492         this.fireEvent('resize', this, width, height, null);
84493     },
84494
84495     
84496     getEl : function() {
84497         return this.el;
84498     },
84499
84500     
84501     getTarget: function() {
84502         return this.target;
84503     },
84504
84505     destroy: function() {
84506         var h;
84507         for (var i = 0, l = this.handles.length; i < l; i++) {
84508             h = this[this.possiblePositions[this.handles[i]]];
84509             delete h.owner;
84510             Ext.destroy(h);
84511         }
84512     },
84513
84514     
84515     forceHandlesHeight : function() {
84516         var me = this,
84517             handle;
84518         if (Ext.isIE6) {
84519             handle = me.east; 
84520             if (handle) {
84521                 handle.setHeight(me.el.getHeight());
84522             }
84523             handle = me.west; 
84524             if (handle) {
84525                 handle.setHeight(me.el.getHeight());
84526             }
84527             me.el.repaint();
84528         }
84529     }
84530 });
84531
84532
84533 Ext.define('Ext.resizer.ResizeTracker', {
84534     extend: 'Ext.dd.DragTracker',
84535     dynamic: true,
84536     preserveRatio: false,
84537
84538     
84539     constrainTo: null,
84540
84541     constructor: function(config) {
84542         var me = this;
84543
84544         if (!config.el) {
84545             if (config.target.isComponent) {
84546                 me.el = config.target.getEl();
84547             } else {
84548                 me.el = config.target;
84549             }
84550         }
84551         this.callParent(arguments);
84552
84553         
84554         if (me.preserveRatio && me.minWidth && me.minHeight) {
84555             var widthRatio = me.minWidth / me.el.getWidth(),
84556                 heightRatio = me.minHeight / me.el.getHeight();
84557
84558             
84559             
84560             
84561             if (heightRatio > widthRatio) {
84562                 me.minWidth = me.el.getWidth() * heightRatio;
84563             } else {
84564                 me.minHeight = me.el.getHeight() * widthRatio;
84565             }
84566         }
84567
84568         
84569         
84570         if (me.throttle) {
84571             var throttledResizeFn = Ext.Function.createThrottled(function() {
84572                     Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
84573                 }, me.throttle);
84574
84575             me.resize = function(box, direction, atEnd) {
84576                 if (atEnd) {
84577                     Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments);
84578                 } else {
84579                     throttledResizeFn.apply(null, arguments);
84580                 }
84581             };
84582         }
84583     },
84584
84585     onBeforeStart: function(e) {
84586         
84587         this.startBox = this.el.getBox();
84588     },
84589
84590     
84591     getDynamicTarget: function() {
84592         var d = this.target;
84593         if (this.dynamic) {
84594             return d;
84595         } else if (!this.proxy) {
84596             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());
84597             this.proxy.removeCls(Ext.baseCSSPrefix + 'proxy-el');
84598         }
84599         this.proxy.show();
84600         return this.proxy;
84601     },
84602
84603     onStart: function(e) {
84604         
84605         this.activeResizeHandle = Ext.getCmp(this.getDragTarget().id);
84606
84607         
84608         if (!this.dynamic) {
84609             this.resize(this.startBox, {
84610                 horizontal: 'none',
84611                 vertical: 'none'
84612             });
84613         }
84614     },
84615
84616     onDrag: function(e) {
84617         
84618         if (this.dynamic || this.proxy) {
84619             this.updateDimensions(e);
84620         }
84621     },
84622
84623     updateDimensions: function(e, atEnd) {
84624         var me = this,
84625             region = me.activeResizeHandle.region,
84626             offset = me.getOffset(me.constrainTo ? 'dragTarget' : null),
84627             box = me.startBox,
84628             ratio,
84629             widthAdjust = 0,
84630             heightAdjust = 0,
84631             adjustX = 0,
84632             adjustY = 0,
84633             dragRatio,
84634             horizDir = offset[0] < 0 ? 'right' : 'left',
84635             vertDir = offset[1] < 0 ? 'down' : 'up',
84636             oppositeCorner,
84637             axis; 
84638
84639         switch (region) {
84640             case 'south':
84641                 heightAdjust = offset[1];
84642                 axis = 2;
84643                 break;
84644             case 'north':
84645                 heightAdjust = -offset[1];
84646                 adjustY = -heightAdjust;
84647                 axis = 2;
84648                 break;
84649             case 'east':
84650                 widthAdjust = offset[0];
84651                 axis = 1;
84652                 break;
84653             case 'west':
84654                 widthAdjust = -offset[0];
84655                 adjustX = -widthAdjust;
84656                 axis = 1;
84657                 break;
84658             case 'northeast':
84659                 heightAdjust = -offset[1];
84660                 adjustY = -heightAdjust;
84661                 widthAdjust = offset[0];
84662                 oppositeCorner = [box.x, box.y + box.height];
84663                 axis = 3;
84664                 break;
84665             case 'southeast':
84666                 heightAdjust = offset[1];
84667                 widthAdjust = offset[0];
84668                 oppositeCorner = [box.x, box.y];
84669                 axis = 3;
84670                 break;
84671             case 'southwest':
84672                 widthAdjust = -offset[0];
84673                 adjustX = -widthAdjust;
84674                 heightAdjust = offset[1];
84675                 oppositeCorner = [box.x + box.width, box.y];
84676                 axis = 3;
84677                 break;
84678             case 'northwest':
84679                 heightAdjust = -offset[1];
84680                 adjustY = -heightAdjust;
84681                 widthAdjust = -offset[0];
84682                 adjustX = -widthAdjust;
84683                 oppositeCorner = [box.x + box.width, box.y + box.height];
84684                 axis = 3;
84685                 break;
84686         }
84687
84688         var newBox = {
84689             width: box.width + widthAdjust,
84690             height: box.height + heightAdjust,
84691             x: box.x + adjustX,
84692             y: box.y + adjustY
84693         };
84694
84695         
84696         if (newBox.width < me.minWidth || newBox.width > me.maxWidth) {
84697             newBox.width = Ext.Number.constrain(newBox.width, me.minWidth, me.maxWidth);
84698             newBox.x = me.lastX || newBox.x;
84699         } else {
84700             me.lastX = newBox.x;
84701         }
84702         if (newBox.height < me.minHeight || newBox.height > me.maxHeight) {
84703             newBox.height = Ext.Number.constrain(newBox.height, me.minHeight, me.maxHeight);
84704             newBox.y = me.lastY || newBox.y;
84705         } else {
84706             me.lastY = newBox.y;
84707         }
84708
84709         
84710         if (me.preserveRatio || e.shiftKey) {
84711             var newHeight,
84712                 newWidth;
84713
84714             ratio = me.startBox.width / me.startBox.height;
84715
84716             
84717             newHeight = Math.min(Math.max(me.minHeight, newBox.width / ratio), me.maxHeight);
84718             newWidth = Math.min(Math.max(me.minWidth, newBox.height * ratio), me.maxWidth);
84719
84720             
84721             if (axis == 1) {
84722                 newBox.height = newHeight;
84723             }
84724
84725             
84726             else if (axis == 2) {
84727                 newBox.width = newWidth;
84728             }
84729
84730             
84731             else {
84732                 
84733                 
84734                 dragRatio = Math.abs(oppositeCorner[0] - this.lastXY[0]) / Math.abs(oppositeCorner[1] - this.lastXY[1]);
84735
84736                 
84737                 if (dragRatio > ratio) {
84738                     newBox.height = newHeight;
84739                 } else {
84740                     newBox.width = newWidth;
84741                 }
84742
84743                 
84744                 if (region == 'northeast') {
84745                     newBox.y = box.y - (newBox.height - box.height);
84746                 } else if (region == 'northwest') {
84747                     newBox.y = box.y - (newBox.height - box.height);
84748                     newBox.x = box.x - (newBox.width - box.width);
84749                 } else if (region == 'southwest') {
84750                     newBox.x = box.x - (newBox.width - box.width);
84751                 }
84752             }
84753         }
84754
84755         if (heightAdjust === 0) {
84756             vertDir = 'none';
84757         }
84758         if (widthAdjust === 0) {
84759             horizDir = 'none';
84760         }
84761         me.resize(newBox, {
84762             horizontal: horizDir,
84763             vertical: vertDir
84764         }, atEnd);
84765     },
84766
84767     getResizeTarget: function(atEnd) {
84768         return atEnd ? this.target : this.getDynamicTarget();
84769     },
84770
84771     resize: function(box, direction, atEnd) {
84772         var target = this.getResizeTarget(atEnd);
84773         if (target.isComponent) {
84774             if (target.floating) {
84775                 target.setPagePosition(box.x, box.y);
84776             }
84777             target.setSize(box.width, box.height);
84778         } else {
84779             target.setBox(box);
84780             
84781             if (this.originalTarget) {
84782                 this.originalTarget.setBox(box);
84783             }
84784         }
84785     },
84786
84787     onEnd: function(e) {
84788         this.updateDimensions(e, true);
84789         if (this.proxy) {
84790             this.proxy.hide();
84791         }
84792     }
84793 });
84794
84795
84796 Ext.define('Ext.resizer.SplitterTracker', {
84797     extend: 'Ext.dd.DragTracker',
84798     requires: ['Ext.util.Region'],
84799     enabled: true,
84800     
84801     overlayCls: Ext.baseCSSPrefix + 'resizable-overlay',
84802
84803     getPrevCmp: function() {
84804         var splitter = this.getSplitter();
84805         return splitter.previousSibling();
84806     },
84807
84808     getNextCmp: function() {
84809         var splitter = this.getSplitter();
84810         return splitter.nextSibling();
84811     },
84812
84813     
84814     
84815     onBeforeStart: function(e) {
84816         var me = this,
84817             prevCmp = me.getPrevCmp(),
84818             nextCmp = me.getNextCmp();
84819
84820         
84821         if (nextCmp.collapsed || prevCmp.collapsed) {
84822             return false;
84823         }
84824         
84825         me.prevBox  = prevCmp.getEl().getBox();
84826         me.nextBox  = nextCmp.getEl().getBox();
84827         me.constrainTo = me.calculateConstrainRegion();
84828     },
84829
84830     
84831     onStart: function(e) {
84832         var splitter = this.getSplitter(),
84833             overlay;
84834             
84835         splitter.addCls(splitter.baseCls + '-active');
84836         overlay = this.overlay =  Ext.getBody().createChild({
84837             cls: this.overlayCls, 
84838             html: '&#160;'
84839         });
84840         overlay.unselectable();
84841         overlay.setSize(Ext.core.Element.getViewWidth(true), Ext.core.Element.getViewHeight(true));
84842         overlay.show();
84843     },
84844
84845     
84846     calculateConstrainRegion: function() {
84847         var me         = this,
84848             splitter   = me.getSplitter(),
84849             splitWidth = splitter.getWidth(),
84850             defaultMin = splitter.defaultSplitMin,
84851             orient     = splitter.orientation,
84852             prevBox    = me.prevBox,
84853             prevCmp    = me.getPrevCmp(),
84854             nextBox    = me.nextBox,
84855             nextCmp    = me.getNextCmp(),
84856             
84857             
84858             
84859             prevConstrainRegion, nextConstrainRegion;
84860
84861         
84862         if (orient === 'vertical') {
84863
84864             
84865             
84866             prevConstrainRegion = Ext.create('Ext.util.Region',
84867                 prevBox.y,
84868                 
84869                 
84870                 (prevCmp.maxWidth ? prevBox.x + prevCmp.maxWidth : nextBox.right - (nextCmp.minWidth || defaultMin)) + splitWidth,
84871                 prevBox.bottom,
84872                 prevBox.x + (prevCmp.minWidth || defaultMin)
84873             );
84874             
84875             nextConstrainRegion = Ext.create('Ext.util.Region',
84876                 nextBox.y,
84877                 nextBox.right - (nextCmp.minWidth || defaultMin),
84878                 nextBox.bottom,
84879                 
84880                 
84881                 (nextCmp.maxWidth ? nextBox.right - nextCmp.maxWidth : prevBox.x + (prevBox.minWidth || defaultMin)) - splitWidth
84882             );
84883         } else {
84884             
84885             prevConstrainRegion = Ext.create('Ext.util.Region',
84886                 prevBox.y + (prevCmp.minHeight || defaultMin),
84887                 prevBox.right,
84888                 
84889                 
84890                 (prevCmp.maxHeight ? prevBox.y + prevCmp.maxHeight : nextBox.bottom - (nextCmp.minHeight || defaultMin)) + splitWidth,
84891                 prevBox.x
84892             );
84893             
84894             nextConstrainRegion = Ext.create('Ext.util.Region',
84895                 
84896                 
84897                 (nextCmp.maxHeight ? nextBox.bottom - nextCmp.maxHeight : prevBox.y + (prevCmp.minHeight || defaultMin)) - splitWidth,
84898                 nextBox.right,
84899                 nextBox.bottom - (nextCmp.minHeight || defaultMin),
84900                 nextBox.x
84901             );
84902         }
84903
84904         
84905         return prevConstrainRegion.intersect(nextConstrainRegion);
84906     },
84907
84908     
84909     performResize: function(e) {
84910         var me       = this,
84911             offset   = me.getOffset('dragTarget'),
84912             splitter = me.getSplitter(),
84913             orient   = splitter.orientation,
84914             prevCmp  = me.getPrevCmp(),
84915             nextCmp  = me.getNextCmp(),
84916             owner    = splitter.ownerCt,
84917             layout   = owner.getLayout();
84918
84919         
84920         owner.suspendLayout = true;
84921
84922         if (orient === 'vertical') {
84923             if (prevCmp) {
84924                 if (!prevCmp.maintainFlex) {
84925                     delete prevCmp.flex;
84926                     prevCmp.setSize(me.prevBox.width + offset[0], prevCmp.getHeight());
84927                 }
84928             }
84929             if (nextCmp) {
84930                 if (!nextCmp.maintainFlex) {
84931                     delete nextCmp.flex;
84932                     nextCmp.setSize(me.nextBox.width - offset[0], nextCmp.getHeight());
84933                 }
84934             }
84935         
84936         } else {
84937             if (prevCmp) {
84938                 if (!prevCmp.maintainFlex) {
84939                     delete prevCmp.flex;
84940                     prevCmp.setSize(prevCmp.getWidth(), me.prevBox.height + offset[1]);
84941                 }
84942             }
84943             if (nextCmp) {
84944                 if (!nextCmp.maintainFlex) {
84945                     delete nextCmp.flex;
84946                     nextCmp.setSize(prevCmp.getWidth(), me.nextBox.height - offset[1]);
84947                 }
84948             }
84949         }
84950         delete owner.suspendLayout;
84951         layout.onLayout();
84952     },
84953
84954     
84955     onEnd: function(e) {
84956         var me = this,
84957             splitter = me.getSplitter();
84958             
84959         splitter.removeCls(splitter.baseCls + '-active');
84960          if (me.overlay) {
84961              me.overlay.remove();
84962              delete me.overlay;
84963         }
84964         me.performResize();
84965     },
84966
84967     
84968     
84969     onDrag: function(e) {
84970         var me        = this,
84971             offset    = me.getOffset('dragTarget'),
84972             splitter  = me.getSplitter(),
84973             splitEl   = splitter.getEl(),
84974             orient    = splitter.orientation;
84975
84976         if (orient === "vertical") {
84977             splitEl.setX(me.startRegion.left + offset[0]);
84978         } else {
84979             splitEl.setY(me.startRegion.top + offset[1]);
84980         }
84981     },
84982
84983     getSplitter: function() {
84984         return Ext.getCmp(this.getDragCt().id);
84985     }
84986 });
84987
84988 Ext.define('Ext.selection.CellModel', {
84989     extend: 'Ext.selection.Model',
84990     alias: 'selection.cellmodel',
84991     requires: ['Ext.util.KeyNav'],
84992     
84993     
84994     enableKeyNav: true,
84995     
84996     
84997     preventWrap: false,
84998
84999     constructor: function(){
85000         this.addEvents(
85001             
85002             'deselect',
85003             
85004             
85005             'select'
85006         );
85007         this.callParent(arguments);    
85008     },
85009
85010     bindComponent: function(view) {
85011         var me = this;
85012         me.primaryView = view;
85013         me.views = me.views || [];
85014         me.views.push(view);
85015         me.bind(view.getStore(), true);
85016
85017         view.on({
85018             cellmousedown: me.onMouseDown,
85019             refresh: me.onViewRefresh,
85020             scope: me
85021         });
85022
85023         if (me.enableKeyNav) {
85024             me.initKeyNav(view);
85025         }
85026     },
85027
85028     initKeyNav: function(view) {
85029         var me = this;
85030         
85031         if (!view.rendered) {
85032             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
85033             return;
85034         }
85035
85036         view.el.set({
85037             tabIndex: -1
85038         });
85039
85040         
85041         
85042         me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
85043             up: me.onKeyUp,
85044             down: me.onKeyDown,
85045             right: me.onKeyRight,
85046             left: me.onKeyLeft,
85047             tab: me.onKeyTab,
85048             scope: me
85049         });
85050     },
85051     
85052     getHeaderCt: function() {
85053         return this.primaryView.headerCt;
85054     },
85055
85056     onKeyUp: function(e, t) {
85057         this.move('up', e);
85058     },
85059
85060     onKeyDown: function(e, t) {
85061         this.move('down', e);
85062     },
85063
85064     onKeyLeft: function(e, t) {
85065         this.move('left', e);
85066     },
85067     
85068     onKeyRight: function(e, t) {
85069         this.move('right', e);
85070     },
85071     
85072     move: function(dir, e) {
85073         var me = this,
85074             pos = me.primaryView.walkCells(me.getCurrentPosition(), dir, e, me.preventWrap);
85075         if (pos) {
85076             me.setCurrentPosition(pos);
85077         }
85078         return pos;
85079     },
85080
85081     
85082     getCurrentPosition: function() {
85083         return this.position;
85084     },
85085     
85086     
85087     setCurrentPosition: function(pos) {
85088         var me = this;
85089         
85090         if (me.position) {
85091             me.onCellDeselect(me.position);
85092         }
85093         if (pos) {
85094             me.onCellSelect(pos);
85095         }
85096         me.position = pos;
85097     },
85098
85099     
85100     onMouseDown: function(view, cell, cellIndex, record, row, rowIndex, e) {
85101         this.setCurrentPosition({
85102             row: rowIndex,
85103             column: cellIndex
85104         });
85105     },
85106
85107     
85108     
85109     onCellSelect: function(position) {
85110         var me = this,
85111             store = me.view.getStore(),
85112             record = store.getAt(position.row);
85113
85114         me.doSelect(record);
85115         me.primaryView.onCellSelect(position);
85116         
85117         me.primaryView.onCellFocus(position);
85118         me.fireEvent('select', me, record, position.row, position.column);
85119     },
85120
85121     
85122     
85123     onCellDeselect: function(position) {
85124         var me = this,
85125             store = me.view.getStore(),
85126             record = store.getAt(position.row);
85127
85128         me.doDeselect(record);
85129         me.primaryView.onCellDeselect(position);
85130         me.fireEvent('deselect', me, record, position.row, position.column);
85131     },
85132
85133     onKeyTab: function(e, t) {
85134         var me = this,
85135             direction = e.shiftKey ? 'left' : 'right',
85136             editingPlugin = me.view.editingPlugin,
85137             position = me.move(direction, e);
85138
85139         if (editingPlugin && position && me.wasEditing) {
85140             editingPlugin.startEditByPosition(position);
85141         }
85142         delete me.wasEditing;
85143     },
85144
85145     onEditorTab: function(editingPlugin, e) {
85146         var me = this,
85147             direction = e.shiftKey ? 'left' : 'right',
85148             position  = me.move(direction, e);
85149
85150         if (position) {
85151             editingPlugin.startEditByPosition(position);
85152             me.wasEditing = true;
85153         }
85154     },
85155
85156     refresh: function() {
85157         var pos = this.getCurrentPosition();
85158         if (pos) {
85159             this.onCellSelect(pos);
85160         }
85161     },
85162
85163     onViewRefresh: function() {
85164         var pos = this.getCurrentPosition();
85165         if (pos) {
85166             this.onCellDeselect(pos);
85167             this.setCurrentPosition(null);
85168         }
85169     },
85170
85171     selectByPosition: function(position) {
85172         this.setCurrentPosition(position);
85173     }
85174 });
85175
85176 Ext.define('Ext.selection.RowModel', {
85177     extend: 'Ext.selection.Model',
85178     alias: 'selection.rowmodel',
85179     requires: ['Ext.util.KeyNav'],
85180     
85181     
85182     deltaScroll: 5,
85183     
85184     
85185     enableKeyNav: true,
85186     
85187     constructor: function(){
85188         this.addEvents(
85189             
85190             'deselect',
85191             
85192             
85193             'select'
85194         );
85195         this.callParent(arguments);    
85196     },
85197
85198     bindComponent: function(view) {
85199         var me = this;
85200         
85201         me.views = me.views || [];
85202         me.views.push(view);
85203         me.bind(view.getStore(), true);
85204
85205         view.on({
85206             itemmousedown: me.onRowMouseDown,
85207             scope: me
85208         });
85209
85210         if (me.enableKeyNav) {
85211             me.initKeyNav(view);
85212         }
85213     },
85214
85215     initKeyNav: function(view) {
85216         var me = this;
85217         
85218         if (!view.rendered) {
85219             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
85220             return;
85221         }
85222
85223         view.el.set({
85224             tabIndex: -1
85225         });
85226
85227         
85228         
85229         me.keyNav = new Ext.util.KeyNav(view.el, {
85230             up: me.onKeyUp,
85231             down: me.onKeyDown,
85232             right: me.onKeyRight,
85233             left: me.onKeyLeft,
85234             pageDown: me.onKeyPageDown,
85235             pageUp: me.onKeyPageUp,
85236             home: me.onKeyHome,
85237             end: me.onKeyEnd,
85238             scope: me
85239         });
85240         view.el.on(Ext.EventManager.getKeyEvent(), me.onKeyPress, me);
85241     },
85242
85243     
85244     
85245     
85246     getRowsVisible: function() {
85247         var rowsVisible = false,
85248             view = this.views[0],
85249             row = view.getNode(0),
85250             rowHeight, gridViewHeight;
85251
85252         if (row) {
85253             rowHeight = Ext.fly(row).getHeight();
85254             gridViewHeight = view.el.getHeight();
85255             rowsVisible = Math.floor(gridViewHeight / rowHeight);
85256         }
85257
85258         return rowsVisible;
85259     },
85260
85261     
85262     onKeyEnd: function(e, t) {
85263         var me = this,
85264             last = me.store.getAt(me.store.getCount() - 1);
85265             
85266         if (last) {
85267             if (e.shiftKey) {
85268                 me.selectRange(last, me.lastFocused || 0);
85269                 me.setLastFocused(last);
85270             } else if (e.ctrlKey) {
85271                 me.setLastFocused(last);
85272             } else {
85273                 me.doSelect(last);
85274             }
85275         }
85276     },
85277
85278     
85279     onKeyHome: function(e, t) {
85280         var me = this,
85281             first = me.store.getAt(0);
85282             
85283         if (first) {
85284             if (e.shiftKey) {
85285                 me.selectRange(first, me.lastFocused || 0);
85286                 me.setLastFocused(first);
85287             } else if (e.ctrlKey) {
85288                 me.setLastFocused(first);
85289             } else {
85290                 me.doSelect(first, false);
85291             }
85292         }
85293     },
85294
85295     
85296     onKeyPageUp: function(e, t) {
85297         var me = this,
85298             rowsVisible = me.getRowsVisible(),
85299             selIdx,
85300             prevIdx,
85301             prevRecord,
85302             currRec;
85303             
85304         if (rowsVisible) {
85305             selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
85306             prevIdx = selIdx - rowsVisible;
85307             if (prevIdx < 0) {
85308                 prevIdx = 0;
85309             }
85310             prevRecord = me.store.getAt(prevIdx);
85311             if (e.shiftKey) {
85312                 currRec = me.store.getAt(selIdx);
85313                 me.selectRange(prevRecord, currRec, e.ctrlKey, 'up');
85314                 me.setLastFocused(prevRecord);
85315             } else if (e.ctrlKey) {
85316                 e.preventDefault();
85317                 me.setLastFocused(prevRecord);
85318             } else {
85319                 me.doSelect(prevRecord);
85320             }
85321
85322         }
85323     },
85324
85325     
85326     onKeyPageDown: function(e, t) {
85327         var me = this,
85328             rowsVisible = me.getRowsVisible(),
85329             selIdx,
85330             nextIdx,
85331             nextRecord,
85332             currRec;
85333             
85334         if (rowsVisible) {
85335             selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
85336             nextIdx = selIdx + rowsVisible;
85337             if (nextIdx >= me.store.getCount()) {
85338                 nextIdx = me.store.getCount() - 1;
85339             }
85340             nextRecord = me.store.getAt(nextIdx);
85341             if (e.shiftKey) {
85342                 currRec = me.store.getAt(selIdx);
85343                 me.selectRange(nextRecord, currRec, e.ctrlKey, 'down');
85344                 me.setLastFocused(nextRecord);
85345             } else if (e.ctrlKey) {
85346                 
85347                 
85348                 e.preventDefault();
85349                 me.setLastFocused(nextRecord);
85350             } else {
85351                 me.doSelect(nextRecord);
85352             }
85353         }
85354     },
85355
85356     
85357     
85358     onKeyPress: function(e, t) {
85359         if (e.getKey() === e.SPACE) {
85360             e.stopEvent();
85361             var me = this,
85362                 record = me.lastFocused;
85363                 
85364             if (record) {
85365                 if (me.isSelected(record)) {
85366                     me.doDeselect(record, false);
85367                 } else {
85368                     me.doSelect(record, true);
85369                 }
85370             }
85371         }
85372     },
85373
85374     
85375     
85376     
85377     onKeyUp: function(e, t) {
85378         var me = this,
85379             view = me.views[0],
85380             idx  = me.store.indexOf(me.lastFocused),
85381             record;
85382             
85383         if (idx > 0) {
85384             
85385             
85386             record = me.store.getAt(idx - 1);
85387             if (e.shiftKey && me.lastFocused) {
85388                 if (me.isSelected(me.lastFocused) && me.isSelected(record)) {
85389                     me.doDeselect(me.lastFocused, true);
85390                     me.setLastFocused(record);
85391                 } else if (!me.isSelected(me.lastFocused)) {
85392                     me.doSelect(me.lastFocused, true);
85393                     me.doSelect(record, true);
85394                 } else {
85395                     me.doSelect(record, true);
85396                 }
85397             } else if (e.ctrlKey) {
85398                 me.setLastFocused(record);
85399             } else {
85400                 me.doSelect(record);
85401                 
85402             }
85403         }
85404         
85405         
85406         
85407         
85408         
85409         
85410         
85411     },
85412
85413     
85414     
85415     
85416     onKeyDown: function(e, t) {
85417         var me = this,
85418             view = me.views[0],
85419             idx  = me.store.indexOf(me.lastFocused),
85420             record;
85421             
85422         
85423         
85424         if (idx + 1 < me.store.getCount()) {
85425             record = me.store.getAt(idx + 1);
85426             if (me.selected.getCount() === 0) {
85427                 me.doSelect(record);
85428                 
85429             } else if (e.shiftKey && me.lastFocused) {
85430                 if (me.isSelected(me.lastFocused) && me.isSelected(record)) {
85431                     me.doDeselect(me.lastFocused, true);
85432                     me.setLastFocused(record);
85433                 } else if (!me.isSelected(me.lastFocused)) {
85434                     me.doSelect(me.lastFocused, true);
85435                     me.doSelect(record, true);
85436                 } else {
85437                     me.doSelect(record, true);
85438                 }
85439             } else if (e.ctrlKey) {
85440                 me.setLastFocused(record);
85441             } else {
85442                 me.doSelect(record);
85443                 
85444             }
85445         }
85446     },
85447     
85448     scrollByDeltaX: function(delta) {
85449         var view    = this.views[0],
85450             section = view.up(),
85451             hScroll = section.horizontalScroller;
85452             
85453         if (hScroll) {
85454             hScroll.scrollByDeltaX(delta);
85455         }
85456     },
85457     
85458     onKeyLeft: function(e, t) {
85459         this.scrollByDeltaX(-this.deltaScroll);
85460     },
85461     
85462     onKeyRight: function(e, t) {
85463         this.scrollByDeltaX(this.deltaScroll);
85464     },
85465
85466     
85467     
85468     onRowMouseDown: function(view, record, item, index, e) {
85469         view.el.focus();
85470         this.selectWithEvent(record, e);
85471     },
85472
85473     
85474     
85475     onSelectChange: function(record, isSelected, suppressEvent) {
85476         var me      = this,
85477             views   = me.views,
85478             viewsLn = views.length,
85479             store   = me.store,
85480             rowIdx  = store.indexOf(record),
85481             i = 0;
85482             
85483         for (; i < viewsLn; i++) {
85484             if (isSelected) {
85485                 views[i].onRowSelect(rowIdx, suppressEvent);
85486                 if (!suppressEvent) {
85487                     me.fireEvent('select', me, record, rowIdx);
85488                 }
85489             } else {
85490                 views[i].onRowDeselect(rowIdx, suppressEvent);
85491                 if (!suppressEvent) {
85492                     me.fireEvent('deselect', me, record, rowIdx);
85493                 }
85494             }
85495         }
85496     },
85497
85498     
85499     
85500     onLastFocusChanged: function(oldFocused, newFocused, supressFocus) {
85501         var views   = this.views,
85502             viewsLn = views.length,
85503             store   = this.store,
85504             rowIdx,
85505             i = 0;
85506             
85507         if (oldFocused) {
85508             rowIdx = store.indexOf(oldFocused);
85509             if (rowIdx != -1) {
85510                 for (; i < viewsLn; i++) {
85511                     views[i].onRowFocus(rowIdx, false);
85512                 }
85513             }
85514         }
85515
85516         if (newFocused) {
85517             rowIdx = store.indexOf(newFocused);
85518             if (rowIdx != -1) {
85519                 for (i = 0; i < viewsLn; i++) {
85520                     views[i].onRowFocus(rowIdx, true, supressFocus);
85521                 }
85522             }
85523         }
85524     },
85525     
85526     onEditorTab: function(editingPlugin, e) {
85527         var me = this,
85528             view = me.views[0],
85529             record = editingPlugin.getActiveRecord(),
85530             header = editingPlugin.getActiveColumn(),
85531             position = view.getPosition(record, header),
85532             direction = e.shiftKey ? 'left' : 'right',
85533             newPosition  = view.walkCells(position, direction, e, this.preventWrap);
85534             
85535         if (newPosition) {
85536             editingPlugin.startEditByPosition(newPosition);
85537         }
85538     },
85539     
85540     selectByPosition: function(position) {
85541         var record = this.store.getAt(position.row);
85542         this.select(record);
85543     }
85544 });
85545
85546 Ext.define('Ext.selection.CheckboxModel', {
85547     alias: 'selection.checkboxmodel',
85548     extend: 'Ext.selection.RowModel',
85549
85550     
85551     mode: 'MULTI',
85552
85553     
85554     injectCheckbox: 0,
85555
85556     
85557     checkOnly: false,
85558
85559     
85560     checkerOnCls: Ext.baseCSSPrefix + 'grid-hd-checker-on',
85561
85562     bindComponent: function() {
85563         this.sortable = false;
85564         this.callParent(arguments);
85565
85566         var view     = this.views[0],
85567             headerCt = view.headerCt;
85568
85569         if (this.injectCheckbox !== false) {
85570             if (this.injectCheckbox == 'first') {
85571                 this.injectCheckbox = 0;
85572             } else if (this.injectCheckbox == 'last') {
85573                 this.injectCheckbox = headerCt.getColumnCount();
85574             }
85575             headerCt.add(this.injectCheckbox,  this.getHeaderConfig());
85576         }
85577         headerCt.on('headerclick', this.onHeaderClick, this);
85578     },
85579
85580     
85581     toggleUiHeader: function(isChecked) {
85582         var view     = this.views[0],
85583             headerCt = view.headerCt,
85584             checkHd  = headerCt.child('gridcolumn[isCheckerHd]');
85585
85586         if (checkHd) {
85587             if (isChecked) {
85588                 checkHd.el.addCls(this.checkerOnCls);
85589             } else {
85590                 checkHd.el.removeCls(this.checkerOnCls);
85591             }
85592         }
85593     },
85594
85595     
85596     onHeaderClick: function(headerCt, header, e) {
85597         if (header.isCheckerHd) {
85598             e.stopEvent();
85599             var isChecked = header.el.hasCls(Ext.baseCSSPrefix + 'grid-hd-checker-on');
85600             if (isChecked) {
85601                 
85602                 this.deselectAll(true);
85603             } else {
85604                 
85605                 this.selectAll(true);
85606             }
85607         }
85608     },
85609
85610     
85611     getHeaderConfig: function() {
85612         return {
85613             isCheckerHd: true,
85614             text : '&#160;',
85615             width: 24,
85616             sortable: false,
85617             fixed: true,
85618             hideable: false,
85619             menuDisabled: true,
85620             dataIndex: '',
85621             cls: Ext.baseCSSPrefix + 'column-header-checkbox ',
85622             renderer: Ext.Function.bind(this.renderer, this)
85623         };
85624     },
85625
85626     
85627     renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
85628         metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
85629         return '<div class="' + Ext.baseCSSPrefix + 'grid-row-checker">&#160;</div>';
85630     },
85631
85632     
85633     onRowMouseDown: function(view, record, item, index, e) {
85634         view.el.focus();
85635         var me = this,
85636             checker = e.getTarget('.' + Ext.baseCSSPrefix + 'grid-row-checker');
85637
85638         
85639         if (me.checkOnly && !checker) {
85640             return;
85641         }
85642
85643         if (checker) {
85644             var mode = me.getSelectionMode();
85645             
85646             
85647             if (mode !== 'SINGLE') {
85648                 me.setSelectionMode('SIMPLE');
85649             }
85650             me.selectWithEvent(record, e);
85651             me.setSelectionMode(mode);
85652         } else {
85653             me.selectWithEvent(record, e);
85654         }
85655     },
85656
85657     
85658     onSelectChange: function(record, isSelected) {
85659         this.callParent([record, isSelected]);
85660         
85661         var hdSelectStatus = this.selected.getCount() === this.store.getCount();
85662         this.toggleUiHeader(hdSelectStatus);
85663     }
85664 });
85665
85666
85667 Ext.define('Ext.selection.TreeModel', {
85668     extend: 'Ext.selection.RowModel',
85669     alias: 'selection.treemodel',
85670     
85671     
85672     
85673     
85674     pruneRemoved: false,
85675     
85676     onKeyRight: function(e, t) {
85677         var focused = this.getLastFocused(),
85678             view    = this.view;
85679             
85680         if (focused) {
85681             
85682             
85683             
85684             if (focused.isExpanded()) {
85685                 this.onKeyDown(e, t);
85686             
85687             } else if (!focused.isLeaf()) {
85688                 view.expand(focused);
85689             }
85690         }
85691     },
85692     
85693     onKeyLeft: function(e, t) {
85694         var focused = this.getLastFocused(),
85695             view    = this.view,
85696             viewSm  = view.getSelectionModel(),
85697             parentNode, parentRecord;
85698
85699         if (focused) {
85700             parentNode = focused.parentNode;
85701             
85702             if (focused.isExpanded()) {
85703                 view.collapse(focused);
85704             
85705             
85706             } else if (parentNode && !parentNode.isRoot()) {
85707                 
85708                 if (e.shiftKey) {
85709                     viewSm.selectRange(parentNode, focused, e.ctrlKey, 'up');
85710                     viewSm.setLastFocused(parentNode);
85711                 
85712                 } else if (e.ctrlKey) {
85713                     viewSm.setLastFocused(parentNode);
85714                 
85715                 } else {
85716                     viewSm.select(parentNode);
85717                 }
85718             }
85719         }
85720     },
85721     
85722     onKeyPress: function(e, t) {
85723         var selected, checked;
85724         
85725         if (e.getKey() === e.SPACE || e.getKey() === e.ENTER) {
85726             e.stopEvent();
85727             selected = this.getLastSelected();
85728             if (selected && selected.isLeaf()) {
85729                 checked = selected.get('checked');
85730                 if (Ext.isBoolean(checked)) {
85731                     selected.set('checked', !checked);
85732                 }
85733             }
85734         } else {
85735             this.callParent(arguments);
85736         }
85737     }
85738 });
85739
85740
85741 Ext.define('Ext.slider.Thumb', {
85742     requires: ['Ext.dd.DragTracker', 'Ext.util.Format'],
85743     
85744     topZIndex: 10000,
85745     
85746     constructor: function(config) {
85747         var me = this;
85748         
85749         
85750         Ext.apply(me, config || {}, {
85751             cls: Ext.baseCSSPrefix + 'slider-thumb',
85752
85753             
85754             constrain: false
85755         });
85756         me.callParent([config]);
85757
85758         if (me.slider.vertical) {
85759             Ext.apply(me, Ext.slider.Thumb.Vertical);
85760         }
85761     },
85762
85763     
85764     render: function() {
85765         var me = this;
85766         
85767         me.el = me.slider.innerEl.insertFirst({cls: me.cls});
85768         if (me.disabled) {
85769             me.disable();
85770         }
85771         me.initEvents();
85772     },
85773     
85774     
85775     move: function(v, animate){
85776         if(!animate){
85777             this.el.setLeft(v);
85778         }else{
85779             Ext.create('Ext.fx.Anim', {
85780                 target: this.el,
85781                 duration: 350,
85782                 to: {
85783                     left: v
85784                 }
85785             });
85786         }
85787     },
85788
85789     
85790     bringToFront: function() {
85791         this.el.setStyle('zIndex', this.topZIndex);
85792     },
85793     
85794     
85795     sendToBack: function() {
85796         this.el.setStyle('zIndex', '');
85797     },
85798     
85799     
85800     enable: function() {
85801         var me = this;
85802         
85803         me.disabled = false;
85804         if (me.el) {
85805             me.el.removeCls(me.slider.disabledCls);
85806         }
85807     },
85808
85809     
85810     disable: function() {
85811         var me = this;
85812         
85813         me.disabled = true;
85814         if (me.el) {
85815             me.el.addCls(me.slider.disabledCls);
85816         }
85817     },
85818
85819     
85820     initEvents: function() {
85821         var me = this,
85822             el = me.el;
85823
85824         me.tracker = Ext.create('Ext.dd.DragTracker', {
85825             onBeforeStart: Ext.Function.bind(me.onBeforeDragStart, me),
85826             onStart      : Ext.Function.bind(me.onDragStart, me),
85827             onDrag       : Ext.Function.bind(me.onDrag, me),
85828             onEnd        : Ext.Function.bind(me.onDragEnd, me),
85829             tolerance    : 3,
85830             autoStart    : 300,
85831             overCls      : Ext.baseCSSPrefix + 'slider-thumb-over'
85832         });
85833
85834         me.tracker.initEl(el);
85835     },
85836
85837     
85838     onBeforeDragStart : function(e) {
85839         if (this.disabled) {
85840             return false;
85841         } else {
85842             this.slider.promoteThumb(this);
85843             return true;
85844         }
85845     },
85846
85847     
85848     onDragStart: function(e){
85849         var me = this;
85850         
85851         me.el.addCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
85852         me.dragging = true;
85853         me.dragStartValue = me.value;
85854
85855         me.slider.fireEvent('dragstart', me.slider, e, me);
85856     },
85857
85858     
85859     onDrag: function(e) {
85860         var me       = this,
85861             slider   = me.slider,
85862             index    = me.index,
85863             newValue = me.getNewValue(),
85864             above,
85865             below;
85866
85867         if (me.constrain) {
85868             above = slider.thumbs[index + 1];
85869             below = slider.thumbs[index - 1];
85870
85871             if (below !== undefined && newValue <= below.value) {
85872                 newValue = below.value;
85873             }
85874             
85875             if (above !== undefined && newValue >= above.value) {
85876                 newValue = above.value;
85877             }
85878         }
85879
85880         slider.setValue(index, newValue, false);
85881         slider.fireEvent('drag', slider, e, me);
85882     },
85883
85884     getNewValue: function() {
85885         var slider = this.slider,
85886             pos = slider.innerEl.translatePoints(this.tracker.getXY());
85887
85888         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
85889     },
85890
85891     
85892     onDragEnd: function(e) {
85893         var me     = this,
85894             slider = me.slider,
85895             value  = me.value;
85896
85897         me.el.removeCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
85898
85899         me.dragging = false;
85900         slider.fireEvent('dragend', slider, e);
85901
85902         if (me.dragStartValue != value) {
85903             slider.fireEvent('changecomplete', slider, value, me);
85904         }
85905     },
85906
85907     destroy: function() {
85908         Ext.destroy(this.tracker);
85909     },
85910     statics: {
85911         
85912         Vertical: {
85913             getNewValue: function() {
85914                 var slider   = this.slider,
85915                     innerEl  = slider.innerEl,
85916                     pos      = innerEl.translatePoints(this.tracker.getXY()),
85917                     bottom   = innerEl.getHeight() - pos.top;
85918
85919                 return Ext.util.Format.round(slider.reverseValue(bottom), slider.decimalPrecision);
85920             },
85921             move: function(v, animate) {
85922                 if (!animate) {
85923                     this.el.setBottom(v);
85924                 } else {
85925                     Ext.create('Ext.fx.Anim', {
85926                         target: this.el,
85927                         duration: 350,
85928                         to: {
85929                             bottom: v
85930                         }
85931                     });
85932                 }
85933             }
85934         }
85935     }
85936 });
85937
85938
85939 Ext.define('Ext.slider.Tip', {
85940     extend: 'Ext.tip.Tip',
85941     minWidth: 10,
85942     alias: 'widget.slidertip',
85943     offsets : [0, -10],
85944     
85945     isSliderTip: true,
85946
85947     init: function(slider) {
85948         var me = this;
85949         
85950         slider.on({
85951             scope    : me,
85952             dragstart: me.onSlide,
85953             drag     : me.onSlide,
85954             dragend  : me.hide,
85955             destroy  : me.destroy
85956         });
85957     },
85958     
85959     onSlide : function(slider, e, thumb) {
85960         var me = this;
85961         me.show();
85962         me.update(me.getText(thumb));
85963         me.doComponentLayout();
85964         me.el.alignTo(thumb.el, 'b-t?', me.offsets);
85965     },
85966
85967     
85968     getText : function(thumb) {
85969         return String(thumb.value);
85970     }
85971 });
85972
85973 Ext.define('Ext.slider.Multi', {
85974     extend: 'Ext.form.field.Base',
85975     alias: 'widget.multislider',
85976     alternateClassName: 'Ext.slider.MultiSlider',
85977
85978     requires: [
85979         'Ext.slider.Thumb',
85980         'Ext.slider.Tip',
85981         'Ext.Number',
85982         'Ext.util.Format',
85983         'Ext.Template',
85984         'Ext.layout.component.field.Slider'
85985     ],
85986
85987     fieldSubTpl: [
85988         '<div class="' + Ext.baseCSSPrefix + 'slider {fieldCls} {vertical}" aria-valuemin="{minValue}" aria-valuemax="{maxValue}" aria-valuenow="{value}" aria-valuetext="{value}">',
85989             '<div class="' + Ext.baseCSSPrefix + 'slider-end" role="presentation">',
85990                 '<div class="' + Ext.baseCSSPrefix + 'slider-inner" role="presentation">',
85991                     '<a class="' + Ext.baseCSSPrefix + 'slider-focus" href="#" tabIndex="-1" hidefocus="on" role="presentation"></a>',
85992                 '</div>',
85993             '</div>',
85994         '</div>',
85995         {
85996             disableFormats: true,
85997             compiled: true
85998         }
85999     ],
86000
86001     
86002
86003     
86004
86005     
86006     vertical: false,
86007     
86008     minValue: 0,
86009     
86010     maxValue: 100,
86011     
86012     decimalPrecision: 0,
86013     
86014     keyIncrement: 1,
86015     
86016     increment: 0,
86017
86018     
86019     clickRange: [5,15],
86020
86021     
86022     clickToChange : true,
86023     
86024     animate: true,
86025
86026     
86027     dragging: false,
86028
86029     
86030     constrainThumbs: true,
86031
86032     componentLayout: 'sliderfield',
86033
86034     
86035     useTips : true,
86036
86037     
86038     tipText : null,
86039
86040     ariaRole: 'slider',
86041
86042     
86043     initValue: function() {
86044         var me = this,
86045             extValue = Ext.value,
86046             
86047             values = extValue(me.values, [extValue(me.value, extValue(me.minValue, 0))]),
86048             i = 0,
86049             len = values.length;
86050
86051         
86052         me.originalValue = values;
86053
86054         
86055         for (; i < len; i++) {
86056             me.addThumb(values[i]);
86057         }
86058     },
86059
86060     
86061     initComponent : function() {
86062         var me = this,
86063             tipPlug,
86064             hasTip;
86065         
86066         
86067         me.thumbs = [];
86068
86069         me.keyIncrement = Math.max(me.increment, me.keyIncrement);
86070
86071         me.addEvents(
86072             
86073             'beforechange',
86074
86075             
86076             'change',
86077
86078             
86079             'changecomplete',
86080
86081             
86082             'dragstart',
86083
86084             
86085             'drag',
86086
86087             
86088             'dragend'
86089         );
86090
86091         if (me.vertical) {
86092             Ext.apply(me, Ext.slider.Multi.Vertical);
86093         }
86094
86095         me.callParent();
86096
86097         
86098         if (me.useTips) {
86099             tipPlug = me.tipText ? {getText: me.tipText} : {};
86100             me.plugins = me.plugins || [];
86101             Ext.each(me.plugins, function(plug){
86102                 if (plug.isSliderTip) {
86103                     hasTip = true;
86104                     return false;
86105                 }
86106             });
86107             if (!hasTip) {
86108                 me.plugins.push(Ext.create('Ext.slider.Tip', tipPlug));
86109             }
86110         }
86111     },
86112
86113     
86114     addThumb: function(value) {
86115         var me = this,
86116             thumb = Ext.create('Ext.slider.Thumb', {
86117             value    : value,
86118             slider   : me,
86119             index    : me.thumbs.length,
86120             constrain: me.constrainThumbs
86121         });
86122         me.thumbs.push(thumb);
86123
86124         
86125         if (me.rendered) {
86126             thumb.render();
86127         }
86128
86129         return thumb;
86130     },
86131
86132     
86133     promoteThumb: function(topThumb) {
86134         var thumbs = this.thumbs,
86135             ln = thumbs.length,
86136             zIndex, thumb, i;
86137             
86138         for (i = 0; i < ln; i++) {
86139             thumb = thumbs[i];
86140
86141             if (thumb == topThumb) {
86142                 thumb.bringToFront();
86143             } else {
86144                 thumb.sendToBack();
86145             }
86146         }
86147     },
86148
86149     
86150     onRender : function() {
86151         var me = this,
86152             i = 0,
86153             thumbs = me.thumbs,
86154             len = thumbs.length,
86155             thumb;
86156
86157         Ext.applyIf(me.subTplData, {
86158             vertical: me.vertical ? Ext.baseCSSPrefix + 'slider-vert' : Ext.baseCSSPrefix + 'slider-horz',
86159             minValue: me.minValue,
86160             maxValue: me.maxValue,
86161             value: me.value
86162         });
86163
86164         Ext.applyIf(me.renderSelectors, {
86165             endEl: '.' + Ext.baseCSSPrefix + 'slider-end',
86166             innerEl: '.' + Ext.baseCSSPrefix + 'slider-inner',
86167             focusEl: '.' + Ext.baseCSSPrefix + 'slider-focus'
86168         });
86169
86170         me.callParent(arguments);
86171
86172         
86173         for (; i < len; i++) {
86174             thumbs[i].render();
86175         }
86176
86177         
86178         thumb = me.innerEl.down('.' + Ext.baseCSSPrefix + 'slider-thumb');
86179         me.halfThumb = (me.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
86180
86181     },
86182
86183     
86184     onChange : function(slider, v) {
86185         this.setValue(v, undefined, true);
86186     },
86187
86188     
86189     initEvents : function() {
86190         var me = this;
86191         
86192         me.mon(me.el, {
86193             scope    : me,
86194             mousedown: me.onMouseDown,
86195             keydown  : me.onKeyDown,
86196             change : me.onChange
86197         });
86198
86199         me.focusEl.swallowEvent("click", true);
86200     },
86201
86202     
86203     onMouseDown : function(e) {
86204         var me = this,
86205             thumbClicked = false,
86206             i = 0,
86207             thumbs = me.thumbs,
86208             len = thumbs.length,
86209             local;
86210             
86211         if (me.disabled) {
86212             return;
86213         }
86214
86215         
86216         for (; i < len; i++) {
86217             thumbClicked = thumbClicked || e.target == thumbs[i].el.dom;
86218         }
86219
86220         if (me.clickToChange && !thumbClicked) {
86221             local = me.innerEl.translatePoints(e.getXY());
86222             me.onClickChange(local);
86223         }
86224         me.focus();
86225     },
86226
86227     
86228     onClickChange : function(local) {
86229         var me = this,
86230             thumb, index;
86231             
86232         if (local.top > me.clickRange[0] && local.top < me.clickRange[1]) {
86233             
86234             thumb = me.getNearest(local, 'left');
86235             if (!thumb.disabled) {
86236                 index = thumb.index;
86237                 me.setValue(index, Ext.util.Format.round(me.reverseValue(local.left), me.decimalPrecision), undefined, true);
86238             }
86239         }
86240     },
86241
86242     
86243     getNearest: function(local, prop) {
86244         var me = this,
86245             localValue = prop == 'top' ? me.innerEl.getHeight() - local[prop] : local[prop],
86246             clickValue = me.reverseValue(localValue),
86247             nearestDistance = (me.maxValue - me.minValue) + 5, 
86248             index = 0,
86249             nearest = null,
86250             thumbs = me.thumbs,
86251             i = 0,
86252             len = thumbs.length,
86253             thumb,
86254             value,
86255             dist;
86256
86257         for (; i < len; i++) {
86258             thumb = me.thumbs[i];
86259             value = thumb.value;
86260             dist  = Math.abs(value - clickValue);
86261
86262             if (Math.abs(dist <= nearestDistance)) {
86263                 nearest = thumb;
86264                 index = i;
86265                 nearestDistance = dist;
86266             }
86267         }
86268         return nearest;
86269     },
86270
86271     
86272     onKeyDown : function(e) {
86273         
86274         var me = this,
86275             k,
86276             val;
86277         
86278         if(me.disabled || me.thumbs.length !== 1) {
86279             e.preventDefault();
86280             return;
86281         }
86282         k = e.getKey();
86283         
86284         switch(k) {
86285             case e.UP:
86286             case e.RIGHT:
86287                 e.stopEvent();
86288                 val = e.ctrlKey ? me.maxValue : me.getValue(0) + me.keyIncrement;
86289                 me.setValue(0, val, undefined, true);
86290             break;
86291             case e.DOWN:
86292             case e.LEFT:
86293                 e.stopEvent();
86294                 val = e.ctrlKey ? me.minValue : me.getValue(0) - me.keyIncrement;
86295                 me.setValue(0, val, undefined, true);
86296             break;
86297             default:
86298                 e.preventDefault();
86299         }
86300     },
86301
86302     
86303     doSnap : function(value) {
86304         var newValue = value,
86305             inc = this.increment,
86306             m;
86307             
86308         if (!(inc && value)) {
86309             return value;
86310         }
86311         m = value % inc;
86312         if (m !== 0) {
86313             newValue -= m;
86314             if (m * 2 >= inc) {
86315                 newValue += inc;
86316             } else if (m * 2 < -inc) {
86317                 newValue -= inc;
86318             }
86319         }
86320         return Ext.Number.constrain(newValue, this.minValue,  this.maxValue);
86321     },
86322
86323     
86324     afterRender : function() {
86325         var me = this,
86326             i = 0,
86327             thumbs = me.thumbs,
86328             len = thumbs.length,
86329             thumb,
86330             v;
86331             
86332         me.callParent(arguments);
86333
86334         for (; i < len; i++) {
86335             thumb = thumbs[i];
86336
86337             if (thumb.value !== undefined) {
86338                 v = me.normalizeValue(thumb.value);
86339                 if (v !== thumb.value) {
86340                     
86341                     me.setValue(i, v, false);
86342                 } else {
86343                     thumb.move(me.translateValue(v), false);
86344                 }
86345             }
86346         }
86347     },
86348
86349     
86350     getRatio : function() {
86351         var w = this.innerEl.getWidth(),
86352             v = this.maxValue - this.minValue;
86353         return v === 0 ? w : (w/v);
86354     },
86355
86356     
86357     normalizeValue : function(v) {
86358         var me = this;
86359         
86360         v = me.doSnap(v);
86361         v = Ext.util.Format.round(v, me.decimalPrecision);
86362         v = Ext.Number.constrain(v, me.minValue, me.maxValue);
86363         return v;
86364     },
86365
86366     
86367     setMinValue : function(val) {
86368         var me = this,
86369             i = 0,
86370             thumbs = me.thumbs,
86371             len = thumbs.length,
86372             t;
86373             
86374         me.minValue = val;
86375         me.inputEl.dom.setAttribute('aria-valuemin', val);
86376
86377         for (; i < len; ++i) {
86378             t = thumbs[i];
86379             t.value = t.value < val ? val : t.value;
86380         }
86381         me.syncThumbs();
86382     },
86383
86384     
86385     setMaxValue : function(val) {
86386         var me = this,
86387             i = 0,
86388             thumbs = me.thumbs,
86389             len = thumbs.length,
86390             t;
86391             
86392         me.maxValue = val;
86393         me.inputEl.dom.setAttribute('aria-valuemax', val);
86394
86395         for (; i < len; ++i) {
86396             t = thumbs[i];
86397             t.value = t.value > val ? val : t.value;
86398         }
86399         me.syncThumbs();
86400     },
86401
86402     
86403     setValue : function(index, value, animate, changeComplete) {
86404         var me = this,
86405             thumb = me.thumbs[index];
86406
86407         
86408         value = me.normalizeValue(value);
86409
86410         if (value !== thumb.value && me.fireEvent('beforechange', me, value, thumb.value, thumb) !== false) {
86411             thumb.value = value;
86412             if (me.rendered) {
86413                 
86414                 
86415                 me.inputEl.set({
86416                     'aria-valuenow': value,
86417                     'aria-valuetext': value
86418                 });
86419
86420                 thumb.move(me.translateValue(value), Ext.isDefined(animate) ? animate !== false : me.animate);
86421
86422                 me.fireEvent('change', me, value, thumb);
86423                 if (changeComplete) {
86424                     me.fireEvent('changecomplete', me, value, thumb);
86425                 }
86426             }
86427         }
86428     },
86429
86430     
86431     translateValue : function(v) {
86432         var ratio = this.getRatio();
86433         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
86434     },
86435
86436     
86437     reverseValue : function(pos) {
86438         var ratio = this.getRatio();
86439         return (pos + (this.minValue * ratio)) / ratio;
86440     },
86441
86442     
86443     focus : function() {
86444         this.focusEl.focus(10);
86445     },
86446
86447     
86448     onDisable: function() {
86449         var me = this,
86450             i = 0,
86451             thumbs = me.thumbs,
86452             len = thumbs.length,
86453             thumb,
86454             el,
86455             xy;
86456             
86457         me.callParent();
86458
86459         for (; i < len; i++) {
86460             thumb = thumbs[i];
86461             el = thumb.el;
86462
86463             thumb.disable();
86464
86465             if(Ext.isIE) {
86466                 
86467                 
86468                 xy = el.getXY();
86469                 el.hide();
86470
86471                 me.innerEl.addCls(me.disabledCls).dom.disabled = true;
86472
86473                 if (!me.thumbHolder) {
86474                     me.thumbHolder = me.endEl.createChild({cls: Ext.baseCSSPrefix + 'slider-thumb ' + me.disabledCls});
86475                 }
86476
86477                 me.thumbHolder.show().setXY(xy);
86478             }
86479         }
86480     },
86481
86482     
86483     onEnable: function() {
86484         var me = this,
86485             i = 0,
86486             thumbs = me.thumbs,
86487             len = thumbs.length,
86488             thumb,
86489             el;
86490             
86491         this.callParent();
86492
86493         for (; i < len; i++) {
86494             thumb = thumbs[i];
86495             el = thumb.el;
86496
86497             thumb.enable();
86498
86499             if (Ext.isIE) {
86500                 me.innerEl.removeCls(me.disabledCls).dom.disabled = false;
86501
86502                 if (me.thumbHolder) {
86503                     me.thumbHolder.hide();
86504                 }
86505
86506                 el.show();
86507                 me.syncThumbs();
86508             }
86509         }
86510     },
86511
86512     
86513     syncThumbs : function() {
86514         if (this.rendered) {
86515             var thumbs = this.thumbs,
86516                 length = thumbs.length,
86517                 i = 0;
86518
86519             for (; i < length; i++) {
86520                 thumbs[i].move(this.translateValue(thumbs[i].value));
86521             }
86522         }
86523     },
86524
86525     
86526     getValue : function(index) {
86527         return Ext.isNumber(index) ? this.thumbs[index].value : this.getValues();
86528     },
86529
86530     
86531     getValues: function() {
86532         var values = [],
86533             i = 0,
86534             thumbs = this.thumbs,
86535             len = thumbs.length;
86536
86537         for (; i < len; i++) {
86538             values.push(thumbs[i].value);
86539         }
86540
86541         return values;
86542     },
86543
86544     getSubmitValue: function() {
86545         var me = this;
86546         return (me.disabled || !me.submitValue) ? null : me.getValue();
86547     },
86548
86549     reset: function() {
86550         var me = this,
86551             Array = Ext.Array;
86552         Array.forEach(Array.from(me.originalValue), function(val, i) {
86553             me.setValue(i, val);
86554         });
86555         me.clearInvalid();
86556         
86557         delete me.wasValid;
86558     },
86559
86560     
86561     beforeDestroy : function() {
86562         var me = this;
86563         
86564         Ext.destroyMembers(me.innerEl, me.endEl, me.focusEl);
86565         Ext.each(me.thumbs, function(thumb) {
86566             Ext.destroy(thumb);
86567         }, me);
86568
86569         me.callParent();
86570     },
86571
86572     statics: {
86573         
86574         Vertical: {
86575             getRatio : function() {
86576                 var h = this.innerEl.getHeight(),
86577                     v = this.maxValue - this.minValue;
86578                 return h/v;
86579             },
86580
86581             onClickChange : function(local) {
86582                 var me = this,
86583                     thumb, index, bottom;
86584
86585                 if (local.left > me.clickRange[0] && local.left < me.clickRange[1]) {
86586                     thumb = me.getNearest(local, 'top');
86587                     if (!thumb.disabled) {
86588                         index = thumb.index;
86589                         bottom =  me.reverseValue(me.innerEl.getHeight() - local.top);
86590
86591                         me.setValue(index, Ext.util.Format.round(me.minValue + bottom, me.decimalPrecision), undefined, true);
86592                     }
86593                 }
86594             }
86595         }
86596     }
86597 });
86598
86599
86600 Ext.define('Ext.slider.Single', {
86601     extend: 'Ext.slider.Multi',
86602     alias: ['widget.slider', 'widget.sliderfield'],
86603     alternateClassName: ['Ext.Slider', 'Ext.form.SliderField', 'Ext.slider.SingleSlider', 'Ext.slider.Slider'],
86604
86605     
86606     getValue: function() {
86607         
86608         return this.callParent([0]);
86609     },
86610
86611     
86612     setValue: function(value, animate) {
86613         var args = Ext.toArray(arguments),
86614             len  = args.length;
86615
86616         
86617         
86618         
86619         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
86620             args.unshift(0);
86621         }
86622
86623         return this.callParent(args);
86624     },
86625
86626     
86627     getNearest : function(){
86628         
86629         return this.thumbs[0];
86630     }
86631 });
86632
86633
86634 Ext.define('Ext.tab.Tab', {
86635     extend: 'Ext.button.Button',
86636     alias: 'widget.tab',
86637     
86638     requires: [
86639         'Ext.layout.component.Tab',
86640         'Ext.util.KeyNav'
86641     ],
86642
86643     componentLayout: 'tab',
86644
86645     isTab: true,
86646
86647     baseCls: Ext.baseCSSPrefix + 'tab',
86648
86649     
86650     activeCls: 'active',
86651     
86652     
86653
86654     
86655     closableCls: 'closable',
86656
86657     
86658     closable: true,
86659
86660     
86661     closeText: 'Close Tab',
86662
86663     
86664     active: false,
86665
86666     
86667
86668     scale: false,
86669
86670     position: 'top',
86671     
86672     initComponent: function() {
86673         var me = this;
86674
86675         me.addEvents(
86676             
86677             'activate',
86678
86679             
86680             'deactivate',
86681
86682             
86683             'beforeclose',
86684
86685             
86686             'close'
86687         );
86688         
86689         me.callParent(arguments);
86690
86691         if (me.card) {
86692             me.setCard(me.card);
86693         }
86694     },
86695
86696     
86697     onRender: function() {
86698         var me = this;
86699         
86700         me.addClsWithUI(me.position);
86701         
86702         
86703         
86704
86705         me.syncClosableUI();
86706
86707         me.callParent(arguments);
86708         
86709         if (me.active) {
86710             me.activate(true);
86711         }
86712
86713         me.syncClosableElements();
86714         
86715         me.keyNav = Ext.create('Ext.util.KeyNav', me.el, {
86716             enter: me.onEnterKey,
86717             del: me.onDeleteKey,
86718             scope: me
86719         });
86720     },
86721     
86722     
86723     enable : function(silent) {
86724         var me = this;
86725
86726         me.callParent(arguments);
86727         
86728         me.removeClsWithUI(me.position + '-disabled');
86729
86730         return me;
86731     },
86732
86733     
86734     disable : function(silent) {
86735         var me = this;
86736         
86737         me.callParent(arguments);
86738         
86739         me.addClsWithUI(me.position + '-disabled');
86740
86741         return me;
86742     },
86743     
86744     
86745     onDestroy: function() {
86746         var me = this;
86747
86748         if (me.closeEl) {
86749             me.closeEl.un('click', Ext.EventManager.preventDefault);
86750             me.closeEl = null;
86751         }
86752
86753         Ext.destroy(me.keyNav);
86754         delete me.keyNav;
86755
86756         me.callParent(arguments);
86757     },
86758
86759     
86760     setClosable: function(closable) {
86761         var me = this;
86762
86763         
86764         closable = (!arguments.length || !!closable);
86765
86766         if (me.closable != closable) {
86767             me.closable = closable;
86768
86769             
86770             if (me.card) {
86771                 me.card.closable = closable;
86772             }
86773
86774             me.syncClosableUI();
86775
86776             if (me.rendered) {
86777                 me.syncClosableElements();
86778
86779                 
86780                 me.doComponentLayout();
86781                 if (me.ownerCt) {
86782                     me.ownerCt.doLayout();
86783                 }
86784             }
86785         }
86786     },
86787
86788     
86789     syncClosableElements: function () {
86790         var me = this;
86791
86792         if (me.closable) {
86793             if (!me.closeEl) {
86794                 me.closeEl = me.el.createChild({
86795                     tag: 'a',
86796                     cls: me.baseCls + '-close-btn',
86797                     href: '#',
86798                     html: me.closeText,
86799                     title: me.closeText
86800                 }).on('click', Ext.EventManager.preventDefault);  
86801             }
86802         } else {
86803             var closeEl = me.closeEl;
86804             if (closeEl) {
86805                 closeEl.un('click', Ext.EventManager.preventDefault);
86806                 closeEl.remove();
86807                 me.closeEl = null;
86808             }
86809         }
86810     },
86811
86812     
86813     syncClosableUI: function () {
86814         var me = this, classes = [me.closableCls, me.closableCls + '-' + me.position];
86815
86816         if (me.closable) {
86817             me.addClsWithUI(classes);
86818         } else {
86819             me.removeClsWithUI(classes);
86820         }
86821     },
86822
86823     
86824     setCard: function(card) {
86825         var me = this;
86826
86827         me.card = card;
86828         me.setText(me.title || card.title);
86829         me.setIconCls(me.iconCls || card.iconCls);
86830     },
86831
86832     
86833     onCloseClick: function() {
86834         var me = this;
86835
86836         if (me.fireEvent('beforeclose', me) !== false) {
86837             if (me.tabBar) {
86838                 if (me.tabBar.closeTab(me) === false) {
86839                     
86840                     return;
86841                 }
86842             } else {
86843                 
86844                 me.fireEvent('close', me);
86845             }
86846         }
86847     },
86848     
86849     
86850     fireClose: function(){
86851         this.fireEvent('close', this);
86852     },
86853     
86854     
86855     onEnterKey: function(e) {
86856         var me = this;
86857         
86858         if (me.tabBar) {
86859             me.tabBar.onClick(e, me.el);
86860         }
86861     },
86862     
86863    
86864     onDeleteKey: function(e) {
86865         var me = this;
86866         
86867         if (me.closable) {
86868             me.onCloseClick();
86869         }
86870     },
86871     
86872     
86873     activate : function(supressEvent) {
86874         var me = this;
86875         
86876         me.active = true;
86877         me.addClsWithUI([me.activeCls, me.position + '-' + me.activeCls]);
86878
86879         if (supressEvent !== true) {
86880             me.fireEvent('activate', me);
86881         }
86882     },
86883
86884     
86885     deactivate : function(supressEvent) {
86886         var me = this;
86887         
86888         me.active = false;
86889         me.removeClsWithUI([me.activeCls, me.position + '-' + me.activeCls]);
86890         
86891         if (supressEvent !== true) {
86892             me.fireEvent('deactivate', me);
86893         }
86894     }
86895 });
86896
86897
86898 Ext.define('Ext.tab.Bar', {
86899     extend: 'Ext.panel.Header',
86900     alias: 'widget.tabbar',
86901     baseCls: Ext.baseCSSPrefix + 'tab-bar',
86902
86903     requires: [
86904         'Ext.tab.Tab',
86905         'Ext.FocusManager'
86906     ],
86907
86908     
86909     defaultType: 'tab',
86910
86911     
86912     plain: false,
86913
86914     
86915     renderTpl: [
86916         '<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>',
86917         '<div class="{baseCls}-strip<tpl if="ui"> {baseCls}-strip-{ui}<tpl for="uiCls"> {parent.baseCls}-strip-{parent.ui}-{.}</tpl></tpl>"></div>'
86918     ],
86919
86920     
86921     minTabWidth: 30,
86922
86923     
86924     maxTabWidth: undefined,
86925
86926     
86927     initComponent: function() {
86928         var me = this,
86929             keys;
86930
86931         if (me.plain) {
86932             me.setUI(me.ui + '-plain');
86933         }
86934         
86935         me.addClsWithUI(me.dock);
86936
86937         me.addEvents(
86938             
86939             'change'
86940         );
86941
86942         Ext.applyIf(me.renderSelectors, {
86943             body : '.' + me.baseCls + '-body',
86944             strip: '.' + me.baseCls + '-strip'
86945         });
86946         me.callParent(arguments);
86947
86948         
86949         me.layout.align = (me.orientation == 'vertical') ? 'left' : 'top';
86950         me.layout.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.Scroller', me.layout);
86951         me.items.removeAt(me.items.getCount() - 1);
86952         me.items.removeAt(me.items.getCount() - 1);
86953         
86954         
86955         keys = me.orientation == 'vertical' ? ['up', 'down'] : ['left', 'right'];
86956         Ext.FocusManager.subscribe(me, {
86957             keys: keys
86958         });
86959     },
86960
86961     
86962     onAdd: function(tab) {
86963         var me = this,
86964             tabPanel = me.tabPanel,
86965             hasOwner = !!tabPanel;
86966
86967         me.callParent(arguments);
86968         tab.position = me.dock;
86969         if (hasOwner) {
86970             tab.minWidth = tabPanel.minTabWidth;
86971         }
86972         else {
86973             tab.minWidth = me.minTabWidth + (tab.iconCls ? 25 : 0);
86974         }
86975         tab.maxWidth = me.maxTabWidth || (hasOwner ? tabPanel.maxTabWidth : undefined);
86976     },
86977
86978     
86979     afterRender: function() {
86980         var me = this;
86981
86982         me.mon(me.el, {
86983             scope: me,
86984             click: me.onClick,
86985             delegate: '.' + Ext.baseCSSPrefix + 'tab'
86986         });
86987         me.callParent(arguments);
86988         
86989     },
86990
86991     afterComponentLayout : function() {
86992         var me = this;
86993         
86994         me.callParent(arguments);
86995         me.strip.setWidth(me.el.getWidth());
86996     },
86997
86998     
86999     onClick: function(e, target) {
87000         
87001         var tab = Ext.getCmp(target.id),
87002             tabPanel = this.tabPanel,
87003             allowActive = true;
87004
87005         target = e.getTarget();
87006
87007         if (tab && tab.isDisabled && !tab.isDisabled()) {
87008             if (tab.closable && target === tab.closeEl.dom) {
87009                 tab.onCloseClick();
87010             } else {
87011                 if (tabPanel) {
87012                     
87013                     tabPanel.setActiveTab(tab.card);
87014                 } else {
87015                     this.setActiveTab(tab);
87016                 }
87017                 tab.focus();
87018             }
87019         }
87020     },
87021
87022     
87023     closeTab: function(tab) {
87024         var me = this,
87025             card = tab.card,
87026             tabPanel = me.tabPanel,
87027             nextTab;
87028             
87029         if (card && card.fireEvent('beforeclose', card) === false) {
87030             return false;
87031         }
87032
87033         if (tab.active && me.items.getCount() > 1) {
87034             nextTab = tab.next('tab') || me.items.items[0];
87035             me.setActiveTab(nextTab);
87036             if (tabPanel) {
87037                 tabPanel.setActiveTab(nextTab.card);
87038             }
87039         }
87040         
87041         tab.fireClose();
87042         me.remove(tab);
87043
87044         if (tabPanel && card) {
87045             card.fireEvent('close', card);
87046             tabPanel.remove(card);
87047         }
87048         
87049         if (nextTab) {
87050             nextTab.focus();
87051         }
87052     },
87053
87054     
87055     setActiveTab: function(tab) {
87056         if (tab.disabled) {
87057             return;
87058         }
87059         var me = this;
87060         if (me.activeTab) {
87061             me.activeTab.deactivate();
87062         }
87063         tab.activate();
87064         
87065         if (me.rendered) {
87066             me.layout.layout();
87067             tab.el.scrollIntoView(me.layout.getRenderTarget());
87068         }
87069         me.activeTab = tab;
87070         me.fireEvent('change', me, tab, tab.card);
87071     }
87072 });
87073
87074 Ext.define('Ext.tab.Panel', {
87075     extend: 'Ext.panel.Panel',
87076     alias: 'widget.tabpanel',
87077     alternateClassName: ['Ext.TabPanel'],
87078
87079     requires: ['Ext.layout.container.Card', 'Ext.tab.Bar'],
87080
87081     
87082     tabPosition : 'top',
87083     
87084     
87085
87086     
87087
87088     
87089     removePanelHeader: true,
87090
87091     
87092     plain: false,
87093
87094     
87095     itemCls: 'x-tabpanel-child',
87096
87097     
87098
87099     
87100     deferredRender : true,
87101
87102     
87103     initComponent: function() {
87104         var me = this,
87105             dockedItems = me.dockedItems || [],
87106             activeTab = me.activeTab || 0;
87107
87108         me.layout = Ext.create('Ext.layout.container.Card', Ext.apply({
87109             owner: me,
87110             deferredRender: me.deferredRender,
87111             itemCls: me.itemCls
87112         }, me.layout));
87113
87114         
87115         me.tabBar = Ext.create('Ext.tab.Bar', Ext.apply({}, me.tabBar, {
87116             dock: me.tabPosition,
87117             plain: me.plain,
87118             border: me.border,
87119             cardLayout: me.layout,
87120             tabPanel: me
87121         }));
87122
87123         if (dockedItems && !Ext.isArray(dockedItems)) {
87124             dockedItems = [dockedItems];
87125         }
87126
87127         dockedItems.push(me.tabBar);
87128         me.dockedItems = dockedItems;
87129
87130         me.addEvents(
87131             
87132             'beforetabchange',
87133
87134             
87135             'tabchange'
87136         );
87137         me.callParent(arguments);
87138
87139         
87140         me.setActiveTab(activeTab);
87141         
87142         me.on('afterlayout', me.afterInitialLayout, me, {single: true});
87143     },
87144
87145     
87146     afterInitialLayout: function() {
87147         var me = this,
87148             card = me.getComponent(me.activeTab);
87149             
87150         if (card) {
87151             me.layout.setActiveItem(card);
87152         }
87153     },
87154
87155     
87156     setActiveTab: function(card) {
87157         var me = this,
87158             previous;
87159
87160         card = me.getComponent(card);
87161         if (card) {
87162             previous = me.getActiveTab();
87163             
87164             if (previous && previous !== card && me.fireEvent('beforetabchange', me, card, previous) === false) {
87165                 return false;
87166             }
87167             
87168             me.tabBar.setActiveTab(card.tab);
87169             me.activeTab = card;
87170             if (me.rendered) {
87171                 me.layout.setActiveItem(card);
87172             }
87173             
87174             if (previous && previous !== card) {
87175                 me.fireEvent('tabchange', me, card, previous);
87176             }
87177         }
87178     },
87179
87180     
87181     getActiveTab: function() {
87182         return this.activeTab;
87183     },
87184
87185     
87186     getTabBar: function() {
87187         return this.tabBar;
87188     },
87189
87190     
87191     onAdd: function(item, index) {
87192         var me = this;
87193
87194         item.tab = me.tabBar.insert(index, {
87195             xtype: 'tab',
87196             card: item,
87197             disabled: item.disabled,
87198             closable: item.closable,
87199             hidden: item.hidden,
87200             tabBar: me.tabBar
87201         });
87202         
87203         item.on({
87204             scope : me,
87205             enable: me.onItemEnable,
87206             disable: me.onItemDisable,
87207             beforeshow: me.onItemBeforeShow,
87208             iconchange: me.onItemIconChange,
87209             titlechange: me.onItemTitleChange
87210         });
87211
87212         if (item.isPanel) {
87213             if (me.removePanelHeader) {
87214                 item.preventHeader = true;
87215                 if (item.rendered) {
87216                     item.updateHeader();
87217                 }
87218             }
87219             if (item.isPanel && me.border) {
87220                 item.setBorder(false);
87221             }
87222         }
87223
87224         
87225         if (this.rendered && me.items.getCount() === 1) {
87226             me.setActiveTab(0);
87227         }
87228     },
87229     
87230     
87231     onItemEnable: function(item){
87232         item.tab.enable();
87233     },
87234
87235         
87236     onItemDisable: function(item){
87237         item.tab.disable();
87238     },
87239     
87240     
87241     onItemBeforeShow: function(item) {
87242         if (item !== this.activeTab) {
87243             this.setActiveTab(item);
87244             return false;
87245         }    
87246     },
87247     
87248     
87249     onItemIconChange: function(item, newIconCls) {
87250         item.tab.setIconCls(newIconCls);
87251         this.getTabBar().doLayout();
87252     },
87253     
87254     
87255     onItemTitleChange: function(item, newTitle) {
87256         item.tab.setText(newTitle);
87257         this.getTabBar().doLayout();
87258     },
87259
87260
87261     
87262     doRemove: function(item, autoDestroy) {
87263         var me = this,
87264             items = me.items,
87265             
87266             hasItemsLeft = items.getCount() > 1;
87267
87268         if (me.destroying || !hasItemsLeft) {
87269             me.activeTab = null;
87270         } else if (item === me.activeTab) {
87271              me.setActiveTab(item.next() || items.getAt(0)); 
87272         }
87273         me.callParent(arguments);
87274
87275         
87276         delete item.tab.card;
87277         delete item.tab;
87278     },
87279
87280     
87281     onRemove: function(item, autoDestroy) {
87282         var me = this;
87283         
87284         item.un({
87285             scope : me,
87286             enable: me.onItemEnable,
87287             disable: me.onItemDisable,
87288             beforeshow: me.onItemBeforeShow
87289         });
87290         if (!me.destroying && item.tab.ownerCt == me.tabBar) {
87291             me.tabBar.remove(item.tab);
87292         }
87293     }
87294 });
87295
87296
87297 Ext.define('Ext.toolbar.Spacer', {
87298     extend: 'Ext.Component',
87299     alias: 'widget.tbspacer',
87300     alternateClassName: 'Ext.Toolbar.Spacer',
87301     baseCls: Ext.baseCSSPrefix + 'toolbar-spacer',
87302     focusable: false
87303 });
87304
87305 Ext.define('Ext.tree.Column', {
87306     extend: 'Ext.grid.column.Column',
87307     alias: 'widget.treecolumn',
87308
87309     initComponent: function() {
87310         var origRenderer = this.renderer || this.defaultRenderer,
87311             origScope    = this.scope || window;
87312
87313         this.renderer = function(value, metaData, record, rowIdx, colIdx, store, view) {
87314             var buf   = [],
87315                 format = Ext.String.format,
87316                 depth = record.getDepth(),
87317                 treePrefix  = Ext.baseCSSPrefix + 'tree-',
87318                 elbowPrefix = treePrefix + 'elbow-',
87319                 expanderCls = treePrefix + 'expander',
87320                 imgText     = '<img src="{1}" class="{0}" />',
87321                 checkboxText= '<input type="button" role="checkbox" class="{0}" {1} />',
87322                 formattedValue = origRenderer.apply(origScope, arguments),
87323                 href = record.get('href'),
87324                 target = record.get('hrefTarget'),
87325                 cls = record.get('cls');
87326
87327             while (record) {
87328                 if (!record.isRoot() || (record.isRoot() && view.rootVisible)) {
87329                     if (record.getDepth() === depth) {
87330                         buf.unshift(format(imgText,
87331                             treePrefix + 'icon ' + 
87332                             treePrefix + 'icon' + (record.get('icon') ? '-inline ' : (record.isLeaf() ? '-leaf ' : '-parent ')) +
87333                             (record.get('iconCls') || ''),
87334                             record.get('icon') || Ext.BLANK_IMAGE_URL
87335                         ));
87336                         if (record.get('checked') !== null) {
87337                             buf.unshift(format(
87338                                 checkboxText,
87339                                 (treePrefix + 'checkbox') + (record.get('checked') ? ' ' + treePrefix + 'checkbox-checked' : ''),
87340                                 record.get('checked') ? 'aria-checked="true"' : ''
87341                             ));
87342                             if (record.get('checked')) {
87343                                 metaData.tdCls += (' ' + Ext.baseCSSPrefix + 'tree-checked');
87344                             }
87345                         }
87346                         if (record.isLast()) {
87347                             if (record.isLeaf() || (record.isLoaded() && !record.hasChildNodes())) {
87348                                 buf.unshift(format(imgText, (elbowPrefix + 'end'), Ext.BLANK_IMAGE_URL));
87349                             } else {
87350                                 buf.unshift(format(imgText, (elbowPrefix + 'end-plus ' + expanderCls), Ext.BLANK_IMAGE_URL));
87351                             }
87352                             
87353                         } else {
87354                             if (record.isLeaf() || (record.isLoaded() && !record.hasChildNodes())) {
87355                                 buf.unshift(format(imgText, (treePrefix + 'elbow'), Ext.BLANK_IMAGE_URL));
87356                             } else {
87357                                 buf.unshift(format(imgText, (elbowPrefix + 'plus ' + expanderCls), Ext.BLANK_IMAGE_URL));
87358                             }
87359                         }
87360                     } else {
87361                         if (record.isLast() || record.getDepth() === 0) {
87362                             buf.unshift(format(imgText, (elbowPrefix + 'empty'), Ext.BLANK_IMAGE_URL));
87363                         } else if (record.getDepth() !== 0) {
87364                             buf.unshift(format(imgText, (elbowPrefix + 'line'), Ext.BLANK_IMAGE_URL));
87365                         }                      
87366                     }
87367                 }
87368                 record = record.parentNode;
87369             }
87370             if (href) {
87371                 formattedValue = format('<a href="{0}" target="{1}">{2}</a>', href, target, formattedValue);
87372             }
87373             if (cls) {
87374                 metaData.tdCls += ' ' + cls;
87375             }
87376             return buf.join("") + formattedValue;
87377         };
87378         this.callParent(arguments);
87379     },
87380
87381     defaultRenderer: function(value) {
87382         return value;
87383     }
87384 });
87385
87386 Ext.define('Ext.tree.View', {
87387     extend: 'Ext.view.Table',
87388     alias: 'widget.treeview',
87389
87390     loadingCls: Ext.baseCSSPrefix + 'grid-tree-loading',
87391     expandedCls: Ext.baseCSSPrefix + 'grid-tree-node-expanded',
87392
87393     expanderSelector: '.' + Ext.baseCSSPrefix + 'tree-expander',
87394     checkboxSelector: '.' + Ext.baseCSSPrefix + 'tree-checkbox',
87395     expanderIconOverCls: Ext.baseCSSPrefix + 'tree-expander-over',
87396
87397     blockRefresh: true,
87398
87399     
87400     rootVisible: true,
87401
87402     
87403
87404     expandDuration: 250,
87405     collapseDuration: 250,
87406     
87407     toggleOnDblClick: true,
87408
87409     initComponent: function() {
87410         var me = this;
87411         
87412         if (me.initialConfig.animate === undefined) {
87413             me.animate = Ext.enableFx;
87414         }
87415         
87416         me.store = Ext.create('Ext.data.NodeStore', {
87417             recursive: true,
87418             rootVisible: me.rootVisible,
87419             listeners: {
87420                 beforeexpand: me.onBeforeExpand,
87421                 expand: me.onExpand,
87422                 beforecollapse: me.onBeforeCollapse,
87423                 collapse: me.onCollapse,
87424                 scope: me
87425             }
87426         });
87427         
87428         if (me.node) {
87429             me.setRootNode(me.node);
87430         }
87431         me.animQueue = {};
87432         me.callParent(arguments);
87433     },
87434     
87435     onClear: function(){
87436         this.store.removeAll();    
87437     },
87438
87439     setRootNode: function(node) {
87440         var me = this;        
87441         me.store.setNode(node);
87442         me.node = node;
87443         if (!me.rootVisible) {
87444             node.expand();
87445         }
87446     },
87447     
87448     onRender: function() {
87449         var me = this,
87450             opts = {delegate: me.expanderSelector},
87451             el;
87452
87453         me.callParent(arguments);
87454
87455         el = me.el;
87456         el.on({
87457             scope: me,
87458             delegate: me.expanderSelector,
87459             mouseover: me.onExpanderMouseOver,
87460             mouseout: me.onExpanderMouseOut
87461         });
87462         el.on({
87463             scope: me,
87464             delegate: me.checkboxSelector,
87465             click: me.onCheckboxChange
87466         });
87467     },
87468
87469     onCheckboxChange: function(e, t) {
87470         var item = e.getTarget(this.getItemSelector(), this.getTargetEl()),
87471             record, value;
87472             
87473         if (item) {
87474             record = this.getRecord(item);
87475             value = !record.get('checked');
87476             record.set('checked', value);
87477             this.fireEvent('checkchange', record, value);
87478         }
87479     },
87480
87481     getChecked: function() {
87482         var checked = [];
87483         this.node.cascadeBy(function(rec){
87484             if (rec.get('checked')) {
87485                 checked.push(rec);
87486             }
87487         });
87488         return checked;
87489     },
87490     
87491     isItemChecked: function(rec){
87492         return rec.get('checked');
87493     },
87494
87495     createAnimWrap: function(record, index) {
87496         var thHtml = '',
87497             headerCt = this.panel.headerCt,
87498             headers = headerCt.getGridColumns(),
87499             i = 0, len = headers.length, item,
87500             node = this.getNode(record),
87501             tmpEl, nodeEl;
87502
87503         for (; i < len; i++) {
87504             item = headers[i];
87505             thHtml += '<th style="width: ' + (item.hidden ? 0 : item.getDesiredWidth()) + 'px; height: 0px;"></th>';
87506         }
87507
87508         nodeEl = Ext.get(node);        
87509         tmpEl = nodeEl.insertSibling({
87510             tag: 'tr',
87511             html: [
87512                 '<td colspan="' + headerCt.getColumnCount() + '">',
87513                     '<div class="' + Ext.baseCSSPrefix + 'tree-animator-wrap' + '">',
87514                         '<table class="' + Ext.baseCSSPrefix + 'grid-table" style="width: ' + headerCt.getFullWidth() + 'px;"><tbody>',
87515                             thHtml,
87516                         '</tbody></table>',
87517                     '</div>',
87518                 '</td>'
87519             ].join('')
87520         }, 'after');
87521
87522         return {
87523             record: record,
87524             node: node,
87525             el: tmpEl,
87526             expanding: false,
87527             collapsing: false,
87528             animating: false,
87529             animateEl: tmpEl.down('div'),
87530             targetEl: tmpEl.down('tbody')
87531         };
87532     },
87533
87534     getAnimWrap: function(parent) {
87535         if (!this.animate) {
87536             return null;
87537         }
87538
87539         
87540         while (parent) {
87541             if (parent.animWrap) {
87542                 return parent.animWrap;
87543             }
87544             parent = parent.parentNode;
87545         }
87546         return null;
87547     },
87548
87549     doAdd: function(nodes, records, index) {
87550         
87551         
87552         var me = this,
87553             record = records[0],
87554             parent = record.parentNode,
87555             a = me.all.elements,
87556             relativeIndex = 0,
87557             animWrap = me.getAnimWrap(parent),
87558             targetEl, children, len;
87559
87560         if (!animWrap || !animWrap.expanding) {
87561             me.resetScrollers();
87562             return me.callParent(arguments);
87563         }
87564
87565         
87566         parent = animWrap.record;
87567         
87568         
87569         targetEl = animWrap.targetEl;
87570         children = targetEl.dom.childNodes;
87571         
87572         
87573         len = children.length - 1;
87574         
87575         
87576         relativeIndex = index - me.indexOf(parent) - 1;
87577         
87578         
87579         
87580         if (!len || relativeIndex >= len) {
87581             targetEl.appendChild(nodes);
87582         }
87583         
87584         
87585         else {
87586             
87587             Ext.fly(children[relativeIndex + 1]).insertSibling(nodes, 'before', true);
87588         }
87589         
87590         
87591         if (index < a.length) {
87592             a.splice.apply(a, [index, 0].concat(nodes));
87593         }
87594         else {            
87595             a.push.apply(a, nodes);
87596         }
87597         
87598         
87599         
87600         if (animWrap.isAnimating) {
87601             me.onExpand(parent);
87602         }
87603     },
87604     
87605     doRemove: function(record, index) {
87606         
87607         
87608         var me = this,
87609             parent = record.parentNode,
87610             all = me.all,
87611             animWrap = me.getAnimWrap(record),
87612             node = all.item(index).dom;
87613
87614         if (!animWrap || !animWrap.collapsing) {
87615             me.resetScrollers();
87616             return me.callParent(arguments);
87617         }
87618
87619         animWrap.targetEl.appendChild(node);
87620         all.removeElement(index);
87621     },
87622
87623     onBeforeExpand: function(parent, records, index) {
87624         var me = this,
87625             animWrap;
87626             
87627         if (!me.rendered || !me.animate) {
87628             return;
87629         }
87630
87631         if (me.getNode(parent)) {
87632             animWrap = me.getAnimWrap(parent);
87633             if (!animWrap) {
87634                 animWrap = parent.animWrap = me.createAnimWrap(parent);
87635                 animWrap.animateEl.setHeight(0);
87636             }
87637             else if (animWrap.collapsing) {
87638                 
87639                 
87640                 animWrap.targetEl.select(me.itemSelector).remove();
87641             } 
87642             animWrap.expanding = true;
87643             animWrap.collapsing = false;
87644         }
87645     },
87646
87647     onExpand: function(parent) {
87648         var me = this,
87649             queue = me.animQueue,
87650             id = parent.getId(),
87651             animWrap,
87652             animateEl, 
87653             targetEl,
87654             queueItem;        
87655         
87656         if (me.singleExpand) {
87657             me.ensureSingleExpand(parent);
87658         }
87659         
87660         animWrap = me.getAnimWrap(parent);
87661
87662         if (!animWrap) {
87663             me.resetScrollers();
87664             return;
87665         }
87666         
87667         animateEl = animWrap.animateEl;
87668         targetEl = animWrap.targetEl;
87669
87670         animateEl.stopAnimation();
87671         
87672         queue[id] = true;
87673         animateEl.slideIn('t', {
87674             duration: me.expandDuration,
87675             listeners: {
87676                 scope: me,
87677                 lastframe: function() {
87678                     
87679                     animWrap.el.insertSibling(targetEl.query(me.itemSelector), 'before');
87680                     animWrap.el.remove();
87681                     me.resetScrollers();
87682                     delete animWrap.record.animWrap;
87683                     delete queue[id];
87684                 }
87685             }
87686         });
87687         
87688         animWrap.isAnimating = true;
87689     },
87690     
87691     resetScrollers: function(){
87692         var panel = this.panel;
87693         
87694         panel.determineScrollbars();
87695         panel.invalidateScroller();
87696     },
87697
87698     onBeforeCollapse: function(parent, records, index) {
87699         var me = this,
87700             animWrap;
87701             
87702         if (!me.rendered || !me.animate) {
87703             return;
87704         }
87705
87706         if (me.getNode(parent)) {
87707             animWrap = me.getAnimWrap(parent);
87708             if (!animWrap) {
87709                 animWrap = parent.animWrap = me.createAnimWrap(parent, index);
87710             }
87711             else if (animWrap.expanding) {
87712                 
87713                 
87714                 animWrap.targetEl.select(this.itemSelector).remove();
87715             }
87716             animWrap.expanding = false;
87717             animWrap.collapsing = true;
87718         }
87719     },
87720     
87721     onCollapse: function(parent) {
87722         var me = this,
87723             queue = me.animQueue,
87724             id = parent.getId(),
87725             animWrap = me.getAnimWrap(parent),
87726             animateEl, targetEl;
87727
87728         if (!animWrap) {
87729             me.resetScrollers();
87730             return;
87731         }
87732         
87733         animateEl = animWrap.animateEl;
87734         targetEl = animWrap.targetEl;
87735
87736         queue[id] = true;
87737         
87738         
87739         animateEl.stopAnimation();
87740         animateEl.slideOut('t', {
87741             duration: me.collapseDuration,
87742             listeners: {
87743                 scope: me,
87744                 lastframe: function() {
87745                     animWrap.el.remove();
87746                     delete animWrap.record.animWrap;
87747                     me.resetScrollers();
87748                     delete queue[id];
87749                 }             
87750             }
87751         });
87752         animWrap.isAnimating = true;
87753     },
87754     
87755     
87756     isAnimating: function(node) {
87757         return !!this.animQueue[node.getId()];    
87758     },
87759     
87760     collectData: function(records) {
87761         var data = this.callParent(arguments),
87762             rows = data.rows,
87763             len = rows.length,
87764             i = 0,
87765             row, record;
87766             
87767         for (; i < len; i++) {
87768             row = rows[i];
87769             record = records[i];
87770             if (record.get('qtip')) {
87771                 row.rowAttr = 'data-qtip="' + record.get('qtip') + '"';
87772                 if (record.get('qtitle')) {
87773                     row.rowAttr += ' ' + 'data-qtitle="' + record.get('qtitle') + '"';
87774                 }
87775             }
87776             if (record.isExpanded()) {
87777                 row.rowCls = (row.rowCls || '') + ' ' + this.expandedCls;
87778             }
87779             if (record.isLoading()) {
87780                 row.rowCls = (row.rowCls || '') + ' ' + this.loadingCls;
87781             }
87782         }
87783         
87784         return data;
87785     },
87786     
87787     
87788     expand: function(record, deep, callback, scope) {
87789         return record.expand(deep, callback, scope);
87790     },
87791     
87792     
87793     collapse: function(record, deep, callback, scope) {
87794         return record.collapse(deep, callback, scope);
87795     },
87796     
87797     
87798     toggle: function(record) {
87799         this[record.isExpanded() ? 'collapse' : 'expand'](record);
87800     },
87801     
87802     onItemDblClick: function(record, item, index) {
87803         this.callParent(arguments);
87804         if (this.toggleOnDblClick) {
87805             this.toggle(record);
87806         }
87807     },
87808     
87809     onBeforeItemMouseDown: function(record, item, index, e) {
87810         if (e.getTarget(this.expanderSelector, item)) {
87811             return false;
87812         }
87813         return this.callParent(arguments);
87814     },
87815     
87816     onItemClick: function(record, item, index, e) {
87817         if (e.getTarget(this.expanderSelector, item)) {
87818             this.toggle(record);
87819             return false;
87820         }
87821         return this.callParent(arguments);
87822     },
87823     
87824     onExpanderMouseOver: function(e, t) {
87825         e.getTarget(this.cellSelector, 10, true).addCls(this.expanderIconOverCls);
87826     },
87827     
87828     onExpanderMouseOut: function(e, t) {
87829         e.getTarget(this.cellSelector, 10, true).removeCls(this.expanderIconOverCls);
87830     },
87831     
87832     
87833     getTreeStore: function() {
87834         return this.panel.store;
87835     },    
87836     
87837     ensureSingleExpand: function(node) {
87838         var parent = node.parentNode;
87839         if (parent) {
87840             parent.eachChild(function(child) {
87841                 if (child !== node && child.isExpanded()) {
87842                     child.collapse();
87843                 }
87844             });
87845         }
87846     }
87847 });
87848
87849 Ext.define('Ext.tree.Panel', {
87850     extend: 'Ext.panel.Table',
87851     alias: 'widget.treepanel',
87852     alternateClassName: ['Ext.tree.TreePanel', 'Ext.TreePanel'],
87853     requires: ['Ext.tree.View', 'Ext.selection.TreeModel', 'Ext.tree.Column'],
87854     viewType: 'treeview',
87855     selType: 'treemodel',
87856     
87857     treeCls: Ext.baseCSSPrefix + 'tree-panel',
87858     
87859     
87860     lines: true,
87861     
87862     
87863     useArrows: false,
87864     
87865     
87866     singleExpand: false,
87867     
87868     ddConfig: {
87869         enableDrag: true,
87870         enableDrop: true
87871     },
87872     
87873     
87874             
87875     
87876     rootVisible: true,
87877     
87878         
87879     displayField: 'text',
87880
87881     
87882     root: null,
87883     
87884     
87885     
87886     normalCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible', 'scroll'],
87887     lockedCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible'],
87888
87889     
87890     
87891      
87892     
87893     constructor: function(config) {
87894         config = config || {};
87895         if (config.animate === undefined) {
87896             config.animate = Ext.enableFx;
87897         }
87898         this.enableAnimations = config.animate;
87899         delete config.animate;
87900         
87901         this.callParent([config]);
87902     },
87903     
87904     initComponent: function() {
87905         var me = this,
87906             cls = [me.treeCls];
87907
87908         if (me.useArrows) {
87909             cls.push(Ext.baseCSSPrefix + 'tree-arrows');
87910             me.lines = false;
87911         }
87912         
87913         if (me.lines) {
87914             cls.push(Ext.baseCSSPrefix + 'tree-lines');
87915         } else if (!me.useArrows) {
87916             cls.push(Ext.baseCSSPrefix + 'tree-no-lines');
87917         }
87918         
87919         if (Ext.isString(me.store)) {
87920             me.store = Ext.StoreMgr.lookup(me.store);
87921         } else if (!me.store || Ext.isObject(me.store) && !me.store.isStore) {
87922             me.store = Ext.create('Ext.data.TreeStore', Ext.apply({}, me.store || {}, {
87923                 root: me.root,
87924                 fields: me.fields,
87925                 model: me.model,
87926                 folderSort: me.folderSort
87927             }));
87928         } else if (me.root) {
87929             me.store = Ext.data.StoreManager.lookup(me.store);
87930             me.store.setRootNode(me.root);
87931             if (me.folderSort !== undefined) {
87932                 me.store.folderSort = me.folderSort;
87933                 me.store.sort();
87934             }            
87935         }
87936         
87937         
87938         
87939         
87940         
87941         
87942         me.viewConfig = Ext.applyIf(me.viewConfig || {}, {
87943             rootVisible: me.rootVisible,
87944             animate: me.enableAnimations,
87945             singleExpand: me.singleExpand,
87946             node: me.store.getRootNode(),
87947             hideHeaders: me.hideHeaders
87948         });
87949         
87950         me.mon(me.store, {
87951             scope: me,
87952             rootchange: me.onRootChange,
87953             clear: me.onClear
87954         });
87955     
87956         me.relayEvents(me.store, [
87957             
87958             'beforeload',
87959
87960             
87961             'load'   
87962         ]);
87963         
87964         me.store.on({
87965             
87966             append: me.createRelayer('itemappend'),
87967             
87968             
87969             remove: me.createRelayer('itemremove'),
87970             
87971             
87972             move: me.createRelayer('itemmove'),
87973             
87974             
87975             insert: me.createRelayer('iteminsert'),
87976             
87977             
87978             beforeappend: me.createRelayer('beforeitemappend'),
87979             
87980             
87981             beforeremove: me.createRelayer('beforeitemremove'),
87982             
87983             
87984             beforemove: me.createRelayer('beforeitemmove'),
87985             
87986             
87987             beforeinsert: me.createRelayer('beforeiteminsert'),
87988              
87989             
87990             expand: me.createRelayer('itemexpand'),
87991              
87992             
87993             collapse: me.createRelayer('itemcollapse'),
87994              
87995             
87996             beforeexpand: me.createRelayer('beforeitemexpand'),
87997              
87998             
87999             beforecollapse: me.createRelayer('beforeitemcollapse')
88000         });
88001         
88002         
88003         if (!me.columns) {
88004             if (me.initialConfig.hideHeaders === undefined) {
88005                 me.hideHeaders = true;
88006             }
88007             me.columns = [{
88008                 xtype    : 'treecolumn',
88009                 text     : 'Name',
88010                 flex     : 1,
88011                 dataIndex: me.displayField         
88012             }];
88013         }
88014         
88015         if (me.cls) {
88016             cls.push(me.cls);
88017         }
88018         me.cls = cls.join(' ');
88019         me.callParent();
88020         
88021         me.relayEvents(me.getView(), [
88022             
88023             'checkchange'
88024         ]);
88025             
88026         
88027         if (!me.getView().rootVisible && !me.getRootNode()) {
88028             me.setRootNode({
88029                 expanded: true
88030             });
88031         }
88032     },
88033     
88034     onClear: function(){
88035         this.view.onClear();
88036     },
88037     
88038     setRootNode: function() {
88039         return this.store.setRootNode.apply(this.store, arguments);
88040     },
88041     
88042     getRootNode: function() {
88043         return this.store.getRootNode();
88044     },
88045     
88046     onRootChange: function(root) {
88047         this.view.setRootNode(root);
88048     },
88049
88050     
88051     getChecked: function() {
88052         return this.getView().getChecked();
88053     },
88054     
88055     isItemChecked: function(rec) {
88056         return rec.get('checked');
88057     },
88058         
88059     
88060     expandAll : function(callback, scope) {
88061         var root = this.getRootNode();
88062         if (root) {
88063             root.expand(true, callback, scope);
88064         }
88065     },
88066
88067     
88068     collapseAll : function(callback, scope) {
88069         var root = this.getRootNode();
88070         if (root) {
88071             if (this.getView().rootVisible) {
88072                 root.collapse(true, callback, scope);
88073             }
88074             else {
88075                 root.collapseChildren(true, callback, scope);
88076             }
88077         }
88078     },
88079
88080     
88081     expandPath: function(path, field, separator, callback, scope) {
88082         var me = this,
88083             current = me.getRootNode(),
88084             index = 1,
88085             view = me.getView(),
88086             keys,
88087             expander;
88088         
88089         field = field || me.getRootNode().idProperty;
88090         separator = separator || '/';
88091         
88092         if (Ext.isEmpty(path)) {
88093             Ext.callback(callback, scope || me, [false, null]);
88094             return;
88095         }
88096         
88097         keys = path.split(separator);
88098         if (current.get(field) != keys[1]) {
88099             
88100             Ext.callback(callback, scope || me, [false, current]);
88101             return;
88102         }
88103         
88104         expander = function(){
88105             if (++index === keys.length) {
88106                 Ext.callback(callback, scope || me, [true, current]);
88107                 return;
88108             }
88109             var node = current.findChild(field, keys[index]);
88110             if (!node) {
88111                 Ext.callback(callback, scope || me, [false, current]);
88112                 return;
88113             }
88114             current = node;
88115             current.expand(false, expander);
88116         };
88117         current.expand(false, expander);
88118     },
88119     
88120     
88121     selectPath: function(path, field, separator, callback, scope) {
88122         var me = this,
88123             keys,
88124             last;
88125         
88126         field = field || me.getRootNode().idProperty;
88127         separator = separator || '/';
88128         
88129         keys = path.split(separator);
88130         last = keys.pop();
88131         
88132         me.expandPath(keys.join('/'), field, separator, function(success, node){
88133             var doSuccess = false;
88134             if (success && node) {
88135                 node = node.findChild(field, last);
88136                 if (node) {
88137                     me.getSelectionModel().select(node);
88138                     Ext.callback(callback, scope || me, [true, node]);
88139                     doSuccess = true;
88140                 }
88141             } else if (node === me.getRootNode()) {
88142                 doSuccess = true;
88143             }
88144             Ext.callback(callback, scope || me, [doSuccess, node]);
88145         }, me);
88146     }
88147 });
88148
88149 Ext.define('Ext.view.DragZone', {
88150     extend: 'Ext.dd.DragZone',
88151     containerScroll: false,
88152
88153     constructor: function(config) {
88154         var me = this;
88155
88156         Ext.apply(me, config);
88157
88158         
88159         
88160         
88161         
88162         
88163         if (!me.ddGroup) {
88164             me.ddGroup = 'view-dd-zone-' + me.view.id;
88165         }
88166
88167         
88168         
88169         
88170         
88171         
88172         
88173         
88174         me.callParent([me.view.el.dom.parentNode]);
88175
88176         me.ddel = Ext.get(document.createElement('div'));
88177         me.ddel.addCls(Ext.baseCSSPrefix + 'grid-dd-wrap');
88178     },
88179
88180     init: function(id, sGroup, config) {
88181         this.initTarget(id, sGroup, config);
88182         this.view.mon(this.view, {
88183             itemmousedown: this.onItemMouseDown,
88184             scope: this
88185         });
88186     },
88187
88188     onItemMouseDown: function(view, record, item, index, e) {
88189         if (!this.isPreventDrag(e, record, item, index)) {
88190             this.handleMouseDown(e);
88191         }
88192     },
88193
88194     
88195     isPreventDrag: function(e) {
88196         return false;
88197     },
88198
88199     getDragData: function(e) {
88200         var view = this.view,
88201             item = e.getTarget(view.getItemSelector()),
88202             record, selectionModel, records;
88203
88204         if (item) {
88205             record = view.getRecord(item);
88206             selectionModel = view.getSelectionModel();
88207             records = selectionModel.getSelection();
88208             return {
88209                 copy: this.view.copy || (this.view.allowCopy && e.ctrlKey),
88210                 event: new Ext.EventObjectImpl(e),
88211                 view: view,
88212                 ddel: this.ddel,
88213                 item: item,
88214                 records: records,
88215                 fromPosition: Ext.fly(item).getXY()
88216             };
88217         }
88218     },
88219
88220     onInitDrag: function(x, y) {
88221         var me = this,
88222             data = me.dragData,
88223             view = data.view,
88224             selectionModel = view.getSelectionModel(),
88225             record = view.getRecord(data.item),
88226             e = data.event;
88227
88228         
88229         
88230         if (!selectionModel.isSelected(record) || e.hasModifier()) {
88231             selectionModel.selectWithEvent(record, e);
88232         }
88233         data.records = selectionModel.getSelection();
88234
88235         me.ddel.update(me.getDragText());
88236         me.proxy.update(me.ddel.dom);
88237         me.onStartDrag(x, y);
88238         return true;
88239     },
88240
88241     getDragText: function() {
88242         var count = this.dragData.records.length;
88243         return Ext.String.format(this.dragText, count, count == 1 ? '' : 's');
88244     },
88245
88246     getRepairXY : function(e, data){
88247         return data ? data.fromPosition : false;
88248     }
88249 });
88250 Ext.define('Ext.tree.ViewDragZone', {
88251     extend: 'Ext.view.DragZone',
88252
88253     isPreventDrag: function(e, record) {
88254         return (record.get('allowDrag') === false) || !!e.getTarget(this.view.expanderSelector);
88255     },
88256     
88257     afterRepair: function() {
88258         var me = this,
88259             view = me.view,
88260             selectedRowCls = view.selectedItemCls,
88261             records = me.dragData.records,
88262             fly = Ext.fly;
88263         
88264         if (Ext.enableFx && me.repairHighlight) {
88265             
88266             Ext.Array.forEach(records, function(record) {
88267                 
88268                 
88269                 var item = view.getNode(record);
88270                 
88271                 
88272                 
88273                 fly(item.firstChild).highlight(me.repairHighlightColor, {
88274                     listeners: {
88275                         beforeanimate: function() {
88276                             if (view.isSelected(item)) {
88277                                 fly(item).removeCls(selectedRowCls);
88278                             }
88279                         },
88280                         afteranimate: function() {
88281                             if (view.isSelected(item)) {
88282                                 fly(item).addCls(selectedRowCls);
88283                             }
88284                         }
88285                     }
88286                 });
88287             });
88288         }
88289         me.dragging = false;
88290     }
88291 });
88292
88293 Ext.define('Ext.tree.ViewDropZone', {
88294     extend: 'Ext.view.DropZone',
88295
88296     
88297     allowParentInserts: false,
88298  
88299     
88300     allowContainerDrops: false,
88301
88302     
88303     appendOnly: false,
88304
88305     
88306     expandDelay : 500,
88307
88308     indicatorCls: 'x-tree-ddindicator',
88309
88310     
88311     expandNode : function(node) {
88312         var view = this.view;
88313         if (!node.isLeaf() && !node.isExpanded()) {
88314             view.expand(node);
88315             this.expandProcId = false;
88316         }
88317     },
88318
88319     
88320     queueExpand : function(node) {
88321         this.expandProcId = Ext.Function.defer(this.expandNode, this.expandDelay, this, [node]);
88322     },
88323
88324     
88325     cancelExpand : function() {
88326         if (this.expandProcId) {
88327             clearTimeout(this.expandProcId);
88328             this.expandProcId = false;
88329         }
88330     },
88331
88332     getPosition: function(e, node) {
88333         var view = this.view,
88334             record = view.getRecord(node),
88335             y = e.getPageY(),
88336             noAppend = record.isLeaf(),
88337             noBelow = false,
88338             region = Ext.fly(node).getRegion(),
88339             fragment;
88340
88341         
88342         if (record.isRoot()) {
88343             return 'append';
88344         }
88345
88346         
88347         if (this.appendOnly) {
88348             return noAppend ? false : 'append';
88349         }
88350
88351         if (!this.allowParentInsert) {
88352             noBelow = record.hasChildNodes() && record.isExpanded();
88353         }
88354
88355         fragment = (region.bottom - region.top) / (noAppend ? 2 : 3);
88356         if (y >= region.top && y < (region.top + fragment)) {
88357             return 'before';
88358         }
88359         else if (!noBelow && (noAppend || (y >= (region.bottom - fragment) && y <= region.bottom))) {
88360             return 'after';
88361         }
88362         else {
88363             return 'append';
88364         }
88365     },
88366
88367     isValidDropPoint : function(node, position, dragZone, e, data) {
88368         if (!node || !data.item) {
88369             return false;
88370         }
88371
88372         var view = this.view,
88373             targetNode = view.getRecord(node),
88374             draggedRecords = data.records,
88375             dataLength = draggedRecords.length,
88376             ln = draggedRecords.length,
88377             i, record;
88378
88379         
88380         if (!(targetNode && position && dataLength)) {
88381             return false;
88382         }
88383
88384         
88385         for (i = 0; i < ln; i++) {
88386             record = draggedRecords[i];
88387             if (record.isNode && record.contains(targetNode)) {
88388                 return false;
88389             }
88390         }
88391         
88392         
88393         if (position === 'append' && targetNode.get('allowDrop') == false) {
88394             return false;
88395         }
88396         else if (position != 'append' && targetNode.parentNode.get('allowDrop') == false) {
88397             return false;
88398         }
88399
88400         
88401         if (Ext.Array.contains(draggedRecords, targetNode)) {
88402              return false;
88403         }
88404
88405         
88406         
88407         return true;
88408     },
88409
88410     onNodeOver : function(node, dragZone, e, data) {
88411         var position = this.getPosition(e, node),
88412             returnCls = this.dropNotAllowed,
88413             view = this.view,
88414             targetNode = view.getRecord(node),
88415             indicator = this.getIndicator(),
88416             indicatorX = 0,
88417             indicatorY = 0;
88418
88419         
88420         this.cancelExpand();
88421         if (position == 'append' && !this.expandProcId && !Ext.Array.contains(data.records, targetNode) && !targetNode.isLeaf() && !targetNode.isExpanded()) {
88422             this.queueExpand(targetNode);
88423         }
88424             
88425         if (this.isValidDropPoint(node, position, dragZone, e, data)) {
88426             this.valid = true;
88427             this.currentPosition = position;
88428             this.overRecord = targetNode;
88429
88430             indicator.setWidth(Ext.fly(node).getWidth());
88431             indicatorY = Ext.fly(node).getY() - Ext.fly(view.el).getY() - 1;
88432
88433             if (position == 'before') {
88434                 returnCls = targetNode.isFirst() ? Ext.baseCSSPrefix + 'tree-drop-ok-above' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
88435                 indicator.showAt(0, indicatorY);
88436                 indicator.toFront();
88437             }
88438             else if (position == 'after') {
88439                 returnCls = targetNode.isLast() ? Ext.baseCSSPrefix + 'tree-drop-ok-below' : Ext.baseCSSPrefix + 'tree-drop-ok-between';
88440                 indicatorY += Ext.fly(node).getHeight();
88441                 indicator.showAt(0, indicatorY);
88442                 indicator.toFront();
88443             }
88444             else {
88445                 returnCls = Ext.baseCSSPrefix + 'tree-drop-ok-append';
88446                 
88447                 indicator.hide();
88448             }
88449         }
88450         else {
88451             this.valid = false;
88452         }
88453
88454         this.currentCls = returnCls;
88455         return returnCls;
88456     },
88457
88458     onContainerOver : function(dd, e, data) {
88459         return e.getTarget('.' + this.indicatorCls) ? this.currentCls : this.dropNotAllowed;
88460     },
88461     
88462     notifyOut: function() {
88463         this.callParent(arguments);
88464         this.cancelExpand();
88465     },
88466
88467     handleNodeDrop : function(data, targetNode, position) {
88468         var me = this,
88469             view = me.view,
88470             parentNode = targetNode.parentNode,
88471             store = view.getStore(),
88472             recordDomNodes = [],
88473             records, i, len,
88474             insertionMethod, argList,
88475             needTargetExpand,
88476             transferData,
88477             processDrop;
88478
88479         
88480         if (data.copy) {
88481             records = data.records;
88482             data.records = [];
88483             for (i = 0, len = records.length; i < len; i++) {
88484                 data.records.push(Ext.apply({}, records[i].data));
88485             }
88486         }
88487
88488         
88489         me.cancelExpand();
88490
88491         
88492         
88493         
88494         
88495         if (position == 'before') {
88496             insertionMethod = parentNode.insertBefore;
88497             argList = [null, targetNode];
88498             targetNode = parentNode;
88499         }
88500         else if (position == 'after') {
88501             if (targetNode.nextSibling) {
88502                 insertionMethod = parentNode.insertBefore;
88503                 argList = [null, targetNode.nextSibling];
88504             }
88505             else {
88506                 insertionMethod = parentNode.appendChild;
88507                 argList = [null];
88508             }
88509             targetNode = parentNode;
88510         }
88511         else {
88512             if (!targetNode.isExpanded()) {
88513                 needTargetExpand = true;
88514             }
88515             insertionMethod = targetNode.appendChild;
88516             argList = [null];
88517         }
88518
88519         
88520         transferData = function() {
88521             var node;
88522             for (i = 0, len = data.records.length; i < len; i++) {
88523                 argList[0] = data.records[i];
88524                 node = insertionMethod.apply(targetNode, argList);
88525                 
88526                 if (Ext.enableFx && me.dropHighlight) {
88527                     recordDomNodes.push(view.getNode(node));
88528                 }
88529             }
88530             
88531             
88532             
88533             if (Ext.enableFx && me.dropHighlight) {
88534                 
88535                 
88536                 Ext.Array.forEach(recordDomNodes, function(n) {
88537                     Ext.fly(n.firstChild ? n.firstChild : n).highlight(me.dropHighlightColor);
88538                 });
88539             }
88540         };
88541
88542         
88543         if (needTargetExpand) {
88544             targetNode.expand(false, transferData);
88545         }
88546         
88547         else {
88548             transferData();
88549         }
88550     }
88551 });
88552
88553 Ext.define('Ext.tree.plugin.TreeViewDragDrop', {
88554     extend: 'Ext.AbstractPlugin',
88555     alias: 'plugin.treeviewdragdrop',
88556
88557     uses: [
88558         'Ext.tree.ViewDragZone',
88559         'Ext.tree.ViewDropZone'
88560     ],
88561
88562     
88563
88564     
88565
88566     dragText : '{0} selected node{1}',
88567
88568     
88569     allowParentInserts: false,
88570
88571     
88572     allowContainerDrops: false,
88573
88574     
88575     appendOnly: false,
88576
88577     
88578     ddGroup : "TreeDD",
88579
88580     
88581
88582     
88583
88584     
88585     expandDelay : 1000,
88586
88587     
88588     enableDrop: true,
88589
88590     
88591     enableDrag: true,
88592     
88593     
88594     nodeHighlightColor: 'c3daf9',
88595     
88596     
88597     nodeHighlightOnDrop: Ext.enableFx,
88598     
88599     
88600     nodeHighlightOnRepair: Ext.enableFx,
88601
88602     init : function(view) {
88603         view.on('render', this.onViewRender, this, {single: true});
88604     },
88605
88606     
88607     destroy: function() {
88608         Ext.destroy(this.dragZone, this.dropZone);
88609     },
88610
88611     onViewRender : function(view) {
88612         var me = this;
88613
88614         if (me.enableDrag) {
88615             me.dragZone = Ext.create('Ext.tree.ViewDragZone', {
88616                 view: view,
88617                 ddGroup: me.dragGroup || me.ddGroup,
88618                 dragText: me.dragText,
88619                 repairHighlightColor: me.nodeHighlightColor,
88620                 repairHighlight: me.nodeHighlightOnRepair
88621             });
88622         }
88623
88624         if (me.enableDrop) {
88625             me.dropZone = Ext.create('Ext.tree.ViewDropZone', {
88626                 view: view,
88627                 ddGroup: me.dropGroup || me.ddGroup,
88628                 allowContainerDrops: me.allowContainerDrops,
88629                 appendOnly: me.appendOnly,
88630                 allowParentInserts: me.allowParentInserts,
88631                 expandDelay: me.expandDelay,
88632                 dropHighlightColor: me.nodeHighlightColor,
88633                 dropHighlight: me.nodeHighlightOnDrop
88634             });
88635         }
88636     }
88637 });
88638
88639 Ext.define('Ext.util.Cookies', {
88640     singleton: true,
88641     
88642     
88643     set : function(name, value){
88644         var argv = arguments,
88645             argc = arguments.length,
88646             expires = (argc > 2) ? argv[2] : null,
88647             path = (argc > 3) ? argv[3] : '/',
88648             domain = (argc > 4) ? argv[4] : null,
88649             secure = (argc > 5) ? argv[5] : false;
88650             
88651         document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : "");
88652     },
88653
88654     
88655     get : function(name){
88656         var arg = name + "=",
88657             alen = arg.length,
88658             clen = document.cookie.length,
88659             i = 0,
88660             j = 0;
88661             
88662         while(i < clen){
88663             j = i + alen;
88664             if(document.cookie.substring(i, j) == arg){
88665                 return this.getCookieVal(j);
88666             }
88667             i = document.cookie.indexOf(" ", i) + 1;
88668             if(i === 0){
88669                 break;
88670             }
88671         }
88672         return null;
88673     },
88674
88675     
88676     clear : function(name, path){
88677         if(this.get(name)){
88678             path = path || '/';
88679             document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT; path=' + path;
88680         }
88681     },
88682     
88683     
88684     getCookieVal : function(offset){
88685         var endstr = document.cookie.indexOf(";", offset);
88686         if(endstr == -1){
88687             endstr = document.cookie.length;
88688         }
88689         return unescape(document.cookie.substring(offset, endstr));
88690     }
88691 });
88692
88693
88694 Ext.define('Ext.util.CSS', function() {
88695     var rules = null;
88696     var doc = document;
88697
88698     var camelRe = /(-[a-z])/gi;
88699     var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
88700
88701     return {
88702
88703         singleton: true,
88704
88705         constructor: function() {
88706             this.rules = {};
88707             this.initialized = false;
88708         },
88709  
88710         
88711         createStyleSheet : function(cssText, id) {
88712             var ss,
88713                 head = doc.getElementsByTagName("head")[0],
88714                 styleEl = doc.createElement("style");
88715
88716             styleEl.setAttribute("type", "text/css");
88717             if (id) {
88718                styleEl.setAttribute("id", id);
88719             }
88720
88721             if (Ext.isIE) {
88722                head.appendChild(styleEl);
88723                ss = styleEl.styleSheet;
88724                ss.cssText = cssText;
88725             } else {
88726                 try{
88727                     styleEl.appendChild(doc.createTextNode(cssText));
88728                 } catch(e) {
88729                    styleEl.cssText = cssText;
88730                 }
88731                 head.appendChild(styleEl);
88732                 ss = styleEl.styleSheet ? styleEl.styleSheet : (styleEl.sheet || doc.styleSheets[doc.styleSheets.length-1]);
88733             }
88734             this.cacheStyleSheet(ss);
88735             return ss;
88736         },
88737
88738         
88739         removeStyleSheet : function(id) {
88740             var existing = document.getElementById(id);
88741             if (existing) {
88742                 existing.parentNode.removeChild(existing);
88743             }
88744         },
88745
88746         
88747         swapStyleSheet : function(id, url) {
88748             var doc = document;
88749             this.removeStyleSheet(id);
88750             var ss = doc.createElement("link");
88751             ss.setAttribute("rel", "stylesheet");
88752             ss.setAttribute("type", "text/css");
88753             ss.setAttribute("id", id);
88754             ss.setAttribute("href", url);
88755             doc.getElementsByTagName("head")[0].appendChild(ss);
88756         },
88757
88758         
88759         refreshCache : function() {
88760             return this.getRules(true);
88761         },
88762
88763         
88764         cacheStyleSheet : function(ss) {
88765             if(!rules){
88766                 rules = {};
88767             }
88768             try {
88769                 var ssRules = ss.cssRules || ss.rules,
88770                     selectorText,
88771                     i = ssRules.length - 1,
88772                     j,
88773                     selectors;
88774
88775                 for (; i >= 0; --i) {
88776                     selectorText = ssRules[i].selectorText;
88777                     if (selectorText) {
88778  
88779                         
88780                         selectorText = selectorText.split(',');
88781                         selectors = selectorText.length;
88782                         for (j = 0; j < selectors; j++) {
88783                             rules[Ext.String.trim(selectorText[j]).toLowerCase()] = ssRules[i];
88784                         }
88785                     }
88786                 }
88787             } catch(e) {}
88788         },
88789
88790         
88791         getRules : function(refreshCache) {
88792             if (rules === null || refreshCache) {
88793                 rules = {};
88794                 var ds = doc.styleSheets,
88795                     i = 0,
88796                     len = ds.length;
88797
88798                 for (; i < len; i++) {
88799                     try {
88800                         if (!ds[i].disabled) {
88801                             this.cacheStyleSheet(ds[i]);
88802                         }
88803                     } catch(e) {} 
88804                 }
88805             }
88806             return rules;
88807         },
88808
88809         
88810         getRule: function(selector, refreshCache) {
88811             var rs = this.getRules(refreshCache);
88812             if (!Ext.isArray(selector)) {
88813                 return rs[selector.toLowerCase()];
88814             }
88815             for (var i = 0; i < selector.length; i++) {
88816                 if (rs[selector[i]]) {
88817                     return rs[selector[i].toLowerCase()];
88818                 }
88819             }
88820             return null;
88821         },
88822
88823         
88824         updateRule : function(selector, property, value){
88825             if (!Ext.isArray(selector)) {
88826                 var rule = this.getRule(selector);
88827                 if (rule) {
88828                     rule.style[property.replace(camelRe, camelFn)] = value;
88829                     return true;
88830                 }
88831             } else {
88832                 for (var i = 0; i < selector.length; i++) {
88833                     if (this.updateRule(selector[i], property, value)) {
88834                         return true;
88835                     }
88836                 }
88837             }
88838             return false;
88839         }
88840     };
88841 }());
88842
88843 Ext.define('Ext.util.History', {
88844     singleton: true,
88845     alternateClassName: 'Ext.History',
88846     mixins: {
88847         observable: 'Ext.util.Observable'
88848     },
88849     
88850     constructor: function() {
88851         var me = this;
88852         me.oldIEMode = Ext.isIE6 || Ext.isIE7 || !Ext.isStrict && Ext.isIE8;
88853         me.iframe = null;
88854         me.hiddenField = null;
88855         me.ready = false;
88856         me.currentToken = null;
88857     },
88858     
88859     getHash: function() {
88860         var href = window.location.href,
88861             i = href.indexOf("#");
88862             
88863         return i >= 0 ? href.substr(i + 1) : null;
88864     },
88865
88866     doSave: function() {
88867         this.hiddenField.value = this.currentToken;
88868     },
88869     
88870
88871     handleStateChange: function(token) {
88872         this.currentToken = token;
88873         this.fireEvent('change', token);
88874     },
88875
88876     updateIFrame: function(token) {
88877         var html = '<html><body><div id="state">' + 
88878                     Ext.util.Format.htmlEncode(token) + 
88879                     '</div></body></html>';
88880
88881         try {
88882             var doc = this.iframe.contentWindow.document;
88883             doc.open();
88884             doc.write(html);
88885             doc.close();
88886             return true;
88887         } catch (e) {
88888             return false;
88889         }
88890     },
88891
88892     checkIFrame: function () {
88893         var me = this,
88894             contentWindow = me.iframe.contentWindow;
88895             
88896         if (!contentWindow || !contentWindow.document) {
88897             Ext.Function.defer(this.checkIFrame, 10, this);
88898             return;
88899         }
88900        
88901         var doc = contentWindow.document,
88902             elem = doc.getElementById("state"),
88903             oldToken = elem ? elem.innerText : null,
88904             oldHash = me.getHash();
88905            
88906         Ext.TaskManager.start({
88907             run: function () {
88908                 var doc = contentWindow.document,
88909                     elem = doc.getElementById("state"),
88910                     newToken = elem ? elem.innerText : null,
88911                     newHash = me.getHash();
88912
88913                 if (newToken !== oldToken) {
88914                     oldToken = newToken;
88915                     me.handleStateChange(newToken);
88916                     window.top.location.hash = newToken;
88917                     oldHash = newToken;
88918                     me.doSave();
88919                 } else if (newHash !== oldHash) {
88920                     oldHash = newHash;
88921                     me.updateIFrame(newHash);
88922                 }
88923             }, 
88924             interval: 50,
88925             scope: me
88926         });
88927         me.ready = true;
88928         me.fireEvent('ready', me);            
88929     },
88930
88931     startUp: function () {
88932         var me = this;
88933         
88934         me.currentToken = me.hiddenField.value || this.getHash();
88935
88936         if (me.oldIEMode) {
88937             me.checkIFrame();
88938         } else {
88939             var hash = me.getHash();
88940             Ext.TaskManager.start({
88941                 run: function () {
88942                     var newHash = me.getHash();
88943                     if (newHash !== hash) {
88944                         hash = newHash;
88945                         me.handleStateChange(hash);
88946                         me.doSave();
88947                     }
88948                 },
88949                 interval: 50,
88950                 scope: me
88951             });
88952             me.ready = true;
88953             me.fireEvent('ready', me);
88954         }
88955         
88956     },
88957
88958     
88959     fieldId: Ext.baseCSSPrefix + 'history-field',
88960     
88961     iframeId: Ext.baseCSSPrefix + 'history-frame',
88962
88963     
88964     init: function (onReady, scope) {
88965         var me = this;
88966         
88967         if (me.ready) {
88968             Ext.callback(onReady, scope, [me]);
88969             return;
88970         }
88971         
88972         if (!Ext.isReady) {
88973             Ext.onReady(function() {
88974                 me.init(onReady, scope);
88975             });
88976             return;
88977         }
88978         
88979         me.hiddenField = Ext.getDom(me.fieldId);
88980         
88981         if (me.oldIEMode) {
88982             me.iframe = Ext.getDom(me.iframeId);
88983         }
88984         
88985         me.addEvents(
88986             
88987             'ready',
88988             
88989             'change'
88990         );
88991         
88992         if (onReady) {
88993             me.on('ready', onReady, scope, {single: true});
88994         }
88995         me.startUp();
88996     },
88997
88998     
88999     add: function (token, preventDup) {
89000         var me = this;
89001         
89002         if (preventDup !== false) {
89003             if (me.getToken() === token) {
89004                 return true;
89005             }
89006         }
89007         
89008         if (me.oldIEMode) {
89009             return me.updateIFrame(token);
89010         } else {
89011             window.top.location.hash = token;
89012             return true;
89013         }
89014     },
89015
89016     
89017     back: function() {
89018         window.history.go(-1);
89019     },
89020
89021     
89022     forward: function(){
89023         window.history.go(1);
89024     },
89025
89026     
89027     getToken: function() {
89028         return this.ready ? this.currentToken : this.getHash();
89029     }
89030 });
89031
89032 Ext.define('Ext.view.TableChunker', {
89033     singleton: true,
89034     requires: ['Ext.XTemplate'],
89035     metaTableTpl: [
89036         '{[this.openTableWrap()]}',
89037         '<table class="' + Ext.baseCSSPrefix + 'grid-table ' + Ext.baseCSSPrefix + 'grid-table-resizer" border="0" cellspacing="0" cellpadding="0" {[this.embedFullWidth()]}>',
89038             '<tbody>',
89039             '<tr>',
89040             '<tpl for="columns">',
89041                 '<th class="' + Ext.baseCSSPrefix + 'grid-col-resizer-{id}" style="width: {width}px; height: 0px;"></th>',
89042             '</tpl>',
89043             '</tr>',
89044             '{[this.openRows()]}',
89045                 '{row}',
89046                 '<tpl for="features">',
89047                     '{[this.embedFeature(values, parent, xindex, xcount)]}',
89048                 '</tpl>',
89049             '{[this.closeRows()]}',
89050             '</tbody>',
89051         '</table>',
89052         '{[this.closeTableWrap()]}'
89053     ],
89054
89055     constructor: function() {
89056         Ext.XTemplate.prototype.recurse = function(values, reference) {
89057             return this.apply(reference ? values[reference] : values);
89058         };
89059     },
89060
89061     embedFeature: function(values, parent, x, xcount) {
89062         var tpl = '';
89063         if (!values.disabled) {
89064             tpl = values.getFeatureTpl(values, parent, x, xcount);
89065         }
89066         return tpl;
89067     },
89068
89069     embedFullWidth: function() {
89070         return 'style="width: {fullWidth}px;"';
89071     },
89072
89073     openRows: function() {
89074         return '<tpl for="rows">';
89075     },
89076
89077     closeRows: function() {
89078         return '</tpl>';
89079     },
89080
89081     metaRowTpl: [
89082         '<tr class="' + Ext.baseCSSPrefix + 'grid-row {addlSelector} {[this.embedRowCls()]}" {[this.embedRowAttr()]}>',
89083             '<tpl for="columns">',
89084                 '<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>',
89085             '</tpl>',
89086         '</tr>'
89087     ],
89088     
89089     firstOrLastCls: function(xindex, xcount) {
89090         var cssCls = '';
89091         if (xindex === 1) {
89092             cssCls = Ext.baseCSSPrefix + 'grid-cell-first';
89093         } else if (xindex === xcount) {
89094             cssCls = Ext.baseCSSPrefix + 'grid-cell-last';
89095         }
89096         return cssCls;
89097     },
89098     
89099     embedRowCls: function() {
89100         return '{rowCls}';
89101     },
89102     
89103     embedRowAttr: function() {
89104         return '{rowAttr}';
89105     },
89106     
89107     openTableWrap: function() {
89108         return '';
89109     },
89110     
89111     closeTableWrap: function() {
89112         return '';
89113     },
89114
89115     getTableTpl: function(cfg, textOnly) {
89116         var tpl,
89117             tableTplMemberFns = {
89118                 openRows: this.openRows,
89119                 closeRows: this.closeRows,
89120                 embedFeature: this.embedFeature,
89121                 embedFullWidth: this.embedFullWidth,
89122                 openTableWrap: this.openTableWrap,
89123                 closeTableWrap: this.closeTableWrap
89124             },
89125             tplMemberFns = {},
89126             features = cfg.features || [],
89127             ln = features.length,
89128             i  = 0,
89129             memberFns = {
89130                 embedRowCls: this.embedRowCls,
89131                 embedRowAttr: this.embedRowAttr,
89132                 firstOrLastCls: this.firstOrLastCls
89133             },
89134             
89135             metaRowTpl = Array.prototype.slice.call(this.metaRowTpl, 0),
89136             metaTableTpl;
89137             
89138         for (; i < ln; i++) {
89139             if (!features[i].disabled) {
89140                 features[i].mutateMetaRowTpl(metaRowTpl);
89141                 Ext.apply(memberFns, features[i].getMetaRowTplFragments());
89142                 Ext.apply(tplMemberFns, features[i].getFragmentTpl());
89143                 Ext.apply(tableTplMemberFns, features[i].getTableFragments());
89144             }
89145         }
89146         
89147         metaRowTpl = Ext.create('Ext.XTemplate', metaRowTpl.join(''), memberFns);
89148         cfg.row = metaRowTpl.applyTemplate(cfg);
89149         
89150         metaTableTpl = Ext.create('Ext.XTemplate', this.metaTableTpl.join(''), tableTplMemberFns);
89151         
89152         tpl = metaTableTpl.applyTemplate(cfg);
89153         
89154         
89155         if (!textOnly) {
89156             tpl = Ext.create('Ext.XTemplate', tpl, tplMemberFns);
89157         }
89158         return tpl;
89159         
89160     }
89161 });
89162
89163
89164
89165